简体   繁体   English

用ebnf语法描述c

[英]Describing c with ebnf grammar

This is a grammar in EBNF to describe C:这是 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)* ‘}’

I want to modify the above with these restrictions:我想用这些限制修改上述内容:

  1. The CASE labelcan only be used on commands that are directly contained in a command SWITCH, and not inside its nested IF or WHILE commands. CASE 标签只能用于直接包含在命令 SWITCH 中的命令,不能用于其嵌套的 IF 或 WHILE 命令中。
  2. The BREAK command can only appear inside a WHILE command or one SWITCH command, including these nested commands. BREAK 命令只能出现在 WHILE 命令或一个 SWITCH 命令中,包括这些嵌套命令。
  3. The CONTINUE command can only appear inside a WHILE command, including nested commands. CONTINUE 命令只能出现在 WHILE 命令中,包括嵌套命令。

My answer:我的答案:

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?这是正确的吗?

The task you face up is very complicated.你面临的任务非常复杂。 As an approach (I don't think there's enough place here to explain it fully) you can first start writting to similar stmt nonterminals, one that accepts case statements on it, and one that doesn't.作为一种方法(我认为这里没有足够的地方来完全解释它)你可以首先开始写类似的stmt非终结符,一个接受case语句,一个不接受。 They must be both derived from the original stmt you have posted.它们必须都源自您发布的原始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)* ‘}’

Now you said that you wanted stmt_w_case inside switch statements only, then the while stmt should be changed into stmt_w_case while all the others must be changed into stmt_wo_case , as现在您说您只想在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)* ‘}’

(see how stmt_wo_case propagates it's condition to the embedded stmt between brackets { and } and similarly for the stmt_w_case ) (查看stmt_wo_case如何将它的条件传播到括号{}之间的嵌入stmt ,对于stmt_w_case也是如此)

Then you can say:然后你可以说:

stmt -> stmt_wo_case

and your grammar is ready (but probably you'll run in trouble later, see below)你的语法已经准备好了(但可能你以后会遇到麻烦,见下文)

In the case of the break statement, you should do the same with the new grammar, but be careful, as in this case you can have a break well nested in any of the statements of a if statement or similar.break语句的情况下,您应该对新语法执行相同的操作,但要小心,因为在这种情况下,您可以将break很好地嵌套在if语句或类似语句的任何语句中。 For each of the rules we have just forked two.... you need to do a different stmt_w_case_no_break and a stmt_w_case_w_break (and the same for stmt_wo_case... ) and do you see where does this bring us?对于我们刚刚分叉的每条规则...。您需要执行不同的stmt_w_case_no_breakstmt_w_case_w_break (对于stmt_wo_case...也是如此),您知道这会给我们带来什么吗? in each place we want some kind of rule with, and without, we are doubling the number of rules.... you grow exponentially with the number of decisions of this type you make.在每个地方,我们都需要某种规则,无论有没有,我们都将规则的数量增加一倍……随着您做出的此类决策的数量呈指数增长。

Is this right?这是正确的吗?

No. The grammar show merely says things like “Only switch , break , and continue can have case some-constant: labels, while the others can have some-constant: .不。语法节目只是说“只有switchbreakcontinue可以有case some-constant:标签,而其他的可以有some-constant:

To say that a case label can only be used on commands that are directly inside a switch , the body of a switch, or presumably the body of a compound statement that is the body of a switch, must be a statement or list of statements of a type that can have case labels, whereas the statements or list of statements that appear elsewhere must be statements of a type that cannot have case labels.要说case label 只能用于直接在 switch 内部的命令, switch的主体,或者可能是 switch 主体的复合语句的主体,必须是语句或语句列表可以有case标签的类型,而出现在别处的语句或语句列表必须是不能有case标签的类型的语句。

So define a grammar token like MayBeLabeledStatement that can have a case label and another grammar token like Statement that cannot have a case label.所以定义一个语法标记,比如MayBeLabeledStatement ,它可以有一个case label 和另一个语法标记,比如Statement ,它不能有一个case label。 Both statements may expand to the various kinds of statements (expression, if , while , and so on), but the ones for MayBeLabeledStatement also may have case labels.两种语句都可以扩展为各种语句(表达式、 ifwhile等),但MayBeLabeledStatement的语句也可能有case标签。 Further, all the statements within a MayBeLabeledStatement should be Statement type statements, which cannot have case labels—except you may need to think about how to handle the single statement inside a switch (which could be a compound statement or not).此外, MayBeLabeledStatement中的所有语句应该是Statement类型的语句,不能有case标签——除非您可能需要考虑如何处理switch中的单个语句(可能是复合语句,也可能不是复合语句)。

Similarly, you will need different grammar tokens to handle statements inside a while or switch (which allow break ) versus those not inside a while or switch and another for those within a while (which allow continue) versus those not inside a while .同样,您将需要不同的语法标记来处理whileswitch内的语句(允许break )与那些不在whileswitch内的语句,另一个用于处理while或 switch 内的语句(允许continue)与不在while内的语句。 You may also need some combinations, for statements that are inside a while and are directly inside a switch versus statements that are inside a while and are not directly inside a switch .您可能还需要一些组合,对于在while内且直接在switch内的语句与在while内且不直接在switch内的语句。

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

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