用ebnf文法描述c
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)* ‘}’
我想修改上面的限制条件:
- CASE 标签只能用于直接包含在命令 SWITCH 中的命令,而不能用于其嵌套的 IF 或 WHILE 命令中。
- BREAK 命令只能出现在 WHILE 命令或一个
SWITCH 命令,包括这些嵌套命令。
- CONTINUE 命令只能出现在 WHILE 命令中,
包括嵌套命令。
我的回答:
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)* ‘}’
这样对吗?
Is this right?
没有。语法展示只是说“只有 switch
、break
和 continue
可以有 case some-constant :
标签,而其他的可以有 some-constant :
.
也就是说 case
标签只能用于直接位于 switch
内部的命令、开关的主体,或者可能是作为主体的复合语句的主体开关的,必须是可以有 case
标签的语句或语句列表,而出现在其他地方的语句或语句列表必须是不能有 case
标签的语句类型.
因此定义一个像 MayBeLabeledStatement
这样可以有一个 case
标签的语法标记和另一个像 Statement
这样不能有一个 case
标签的语法标记。这两个语句都可以扩展为各种语句(表达式、if
、while
等),但是 MayBeLabeledStatement
的语句也可能具有 case
标签。此外,所有 within a MayBeLabeledStatement
的语句都应该是 Statement
类型的语句,不能有 case
标签——除非你可能需要考虑如何处理 switch
中的单个语句(可以是复合语句,也可以不是)。
同样,您将需要不同的语法标记来处理 while
或 switch
(允许 break
)内的语句与不在 while
或 switch
和 while
中的另一个(允许 continue)
与不在 while
中的那些。对于 [=24 中的语句,您可能还需要一些组合=] 并且直接在 switch
内与 while
内而不直接在 switch
.
内的语句
您面临的任务非常复杂。作为一种方法(我认为这里没有足够的地方来充分解释它)你可以首先开始写类似的 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...
也是一样)你知道这是在哪里吗给我们带来?在每个地方,我们都需要某种规则,无论有无,我们都将规则的数量加倍......你会随着你做出的此类决定的数量呈指数级增长。
这是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)* ‘}’
我想修改上面的限制条件:
- CASE 标签只能用于直接包含在命令 SWITCH 中的命令,而不能用于其嵌套的 IF 或 WHILE 命令中。
- BREAK 命令只能出现在 WHILE 命令或一个 SWITCH 命令,包括这些嵌套命令。
- CONTINUE 命令只能出现在 WHILE 命令中, 包括嵌套命令。
我的回答:
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)* ‘}’
这样对吗?
Is this right?
没有。语法展示只是说“只有 switch
、break
和 continue
可以有 case some-constant :
标签,而其他的可以有 some-constant :
.
也就是说 case
标签只能用于直接位于 switch
内部的命令、开关的主体,或者可能是作为主体的复合语句的主体开关的,必须是可以有 case
标签的语句或语句列表,而出现在其他地方的语句或语句列表必须是不能有 case
标签的语句类型.
因此定义一个像 MayBeLabeledStatement
这样可以有一个 case
标签的语法标记和另一个像 Statement
这样不能有一个 case
标签的语法标记。这两个语句都可以扩展为各种语句(表达式、if
、while
等),但是 MayBeLabeledStatement
的语句也可能具有 case
标签。此外,所有 within a MayBeLabeledStatement
的语句都应该是 Statement
类型的语句,不能有 case
标签——除非你可能需要考虑如何处理 switch
中的单个语句(可以是复合语句,也可以不是)。
同样,您将需要不同的语法标记来处理 while
或 switch
(允许 break
)内的语句与不在 while
或 switch
和 while
中的另一个(允许 continue)
与不在 while
中的那些。对于 [=24 中的语句,您可能还需要一些组合=] 并且直接在 switch
内与 while
内而不直接在 switch
.
您面临的任务非常复杂。作为一种方法(我认为这里没有足够的地方来充分解释它)你可以首先开始写类似的 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...
也是一样)你知道这是在哪里吗给我们带来?在每个地方,我们都需要某种规则,无论有无,我们都将规则的数量加倍......你会随着你做出的此类决定的数量呈指数级增长。