[英]Describing c with ebnf grammar
这是 EBNF 中描述 C 的语法:
stmt-> (CASE CONST ‘:’)* expression ‘;’
| (CASE CONST ‘:’)* IF ‘(’ expression ‘)’ stmt [ELSE stmt]
| (CASE CONST ‘:’)* WHILE ‘(’ expression ‘)’ stmt
| (CASE CONST ‘:’)* SWITCH ‘(’ expression ‘)’ stmt
| (CASE CONST ‘:’)* RETURN [expression] ‘;’
| (CASE CONST ‘:’)* BREAK ‘;’
| (CASE CONST ‘:’)* CONTINUE ‘;’
| ‘{’ (stmt)* ‘}’
我想用这些限制修改上述内容:
我的答案:
stmt-> ( CONST ‘:’)* expression ‘;’
| ( CONST ‘:’)* IF ‘(’ expression ‘)’ stmt [ELSE stmt]
| (CASE CONST ‘:’)* SWITCH ‘(’ expression ‘)’ stmt
| ( CONST ‘:’)* WHILE ‘(’ expression ‘)’ stmt
| (CASE CONST ‘:’)* BREAK ‘;’
| (CASE CONST ‘:’)* CONTINUE ‘;’
| ( CONST ‘:’)* RETURN [expression] ‘;’
| ‘{’ (stmt)* ‘}’
这是正确的吗?
你面临的任务非常复杂。 作为一种方法(我认为这里没有足够的地方来完全解释它)你可以首先开始写类似的stmt
非终结符,一个接受case
语句,一个不接受。 它们必须都源自您发布的原始stmt
。
stmt_w_case -> (CASE CONST ‘:’)* expression ‘;’
| (CASE CONST ‘:’)* IF ‘(’ expression ‘)’ stmt [ELSE stmt]
| (CASE CONST ‘:’)* WHILE ‘(’ expression ‘)’ stmt
| (CASE CONST ‘:’)* SWITCH ‘(’ expression ‘)’ stmt
| (CASE CONST ‘:’)* RETURN [expression] ‘;’
| (CASE CONST ‘:’)* BREAK ‘;’
| (CASE CONST ‘:’)* CONTINUE ‘;’
| ‘{’ (stmt)* ‘}’
stmt_wo_case -> expression ‘;’
| IF ‘(’ expression ‘)’ stmt [ELSE stmt]
| WHILE ‘(’ expression ‘)’ stmt
| SWITCH ‘(’ expression ‘)’ stmt
| RETURN [expression] ‘;’
| BREAK ‘;’
| CONTINUE ‘;’
| ‘{’ (stmt)* ‘}’
现在您说您只想在switch
语句中使用stmt_w_case
,那么 while stmt
应该更改为stmt_w_case
而所有其他必须更改为stmt_wo_case
,如
stmt_w_case -> (CASE CONST ‘:’)* expression ‘;’
| (CASE CONST ‘:’)* IF ‘(’ expression ‘)’ stmt_wo_case [ELSE stmt_wo_case]
| (CASE CONST ‘:’)* WHILE ‘(’ expression ‘)’ stmt_wo_case
| (CASE CONST ‘:’)* SWITCH ‘(’ expression ‘)’ stmt_w_case
| (CASE CONST ‘:’)* RETURN [expression] ‘;’
| (CASE CONST ‘:’)* BREAK ‘;’
| (CASE CONST ‘:’)* CONTINUE ‘;’
| ‘{’ (stmt_w_case)* ‘}’
stmt_wo_case -> expression ‘;’
| IF ‘(’ expression ‘)’ stmt_wo_case [ELSE stmt_wo_case]
| WHILE ‘(’ expression ‘)’ stmt_wo_case
| SWITCH ‘(’ expression ‘)’ stmt_w_case
| RETURN [expression] ‘;’
| BREAK ‘;’
| CONTINUE ‘;’
| ‘{’ (stmt_wo_case)* ‘}’
(查看stmt_wo_case
如何将它的条件传播到括号{
和}
之间的嵌入stmt
,对于stmt_w_case
也是如此)
然后你可以说:
stmt -> stmt_wo_case
你的语法已经准备好了(但可能你以后会遇到麻烦,见下文)
在break
语句的情况下,您应该对新语法执行相同的操作,但要小心,因为在这种情况下,您可以将break
很好地嵌套在if
语句或类似语句的任何语句中。 对于我们刚刚分叉的每条规则...。您需要执行不同的stmt_w_case_no_break
和stmt_w_case_w_break
(对于stmt_wo_case...
也是如此),您知道这会给我们带来什么吗? 在每个地方,我们都需要某种规则,无论有没有,我们都将规则的数量增加一倍……随着您做出的此类决策的数量呈指数增长。
这是正确的吗?
不。语法节目只是说“只有switch
、 break
和continue
可以有case some-constant:
标签,而其他的可以有some-constant:
。
要说case
label 只能用于直接在 switch 内部的命令, switch
的主体,或者可能是 switch 主体的复合语句的主体,必须是语句或语句列表可以有case
标签的类型,而出现在别处的语句或语句列表必须是不能有case
标签的类型的语句。
所以定义一个语法标记,比如MayBeLabeledStatement
,它可以有一个case
label 和另一个语法标记,比如Statement
,它不能有一个case
label。 两种语句都可以扩展为各种语句(表达式、 if
、 while
等),但MayBeLabeledStatement
的语句也可能有case
标签。 此外, MayBeLabeledStatement
中的所有语句都应该是Statement
类型的语句,不能有case
标签——除非您可能需要考虑如何处理switch
中的单个语句(可能是复合语句,也可能不是复合语句)。
同样,您将需要不同的语法标记来处理while
或switch
内的语句(允许break
)与那些不在while
或switch
内的语句,另一个用于处理while
或 switch 内的语句(允许continue)
与不在while
内的语句。 您可能还需要一些组合,对于在while
内且直接在switch
内的语句与在while
内且不直接在switch
内的语句。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.