繁体   English   中英

用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)* ‘}’

我想用这些限制修改上述内容:

  1. CASE 标签只能用于直接包含在命令 SWITCH 中的命令,不能用于其嵌套的 IF 或 WHILE 命令中。
  2. BREAK 命令只能出现在 WHILE 命令或一个 SWITCH 命令中,包括这些嵌套命令。
  3. 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)* ‘}’

这是正确的吗?

你面临的任务非常复杂。 作为一种方法(我认为这里没有足够的地方来完全解释它)你可以首先开始写类似的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_breakstmt_w_case_w_break (对于stmt_wo_case...也是如此),您知道这会给我们带来什么吗? 在每个地方,我们都需要某种规则,无论有没有,我们都将规则的数量增加一倍……随着您做出的此类决策的数量呈指数增长。

这是正确的吗?

不。语法节目只是说“只有switchbreakcontinue可以有case some-constant:标签,而其他的可以有some-constant:

要说case label 只能用于直接在 switch 内部的命令, switch的主体,或者可能是 switch 主体的复合语句的主体,必须是语句或语句列表可以有case标签的类型,而出现在别处的语句或语句列表必须是不能有case标签的类型的语句。

所以定义一个语法标记,比如MayBeLabeledStatement ,它可以有一个case label 和另一个语法标记,比如Statement ,它不能有一个case label。 两种语句都可以扩展为各种语句(表达式、 ifwhile等),但MayBeLabeledStatement的语句也可能有case标签。 此外, MayBeLabeledStatement中的所有语句应该是Statement类型的语句,不能有case标签——除非您可能需要考虑如何处理switch中的单个语句(可能是复合语句,也可能不是复合语句)。

同样,您将需要不同的语法标记来处理whileswitch内的语句(允许break )与那些不在whileswitch内的语句,另一个用于处理while或 switch 内的语句(允许continue)与不在while内的语句。 您可能还需要一些组合,对于在while内且直接在switch内的语句与在while内且不直接在switch内的语句。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM