Describing c with ebnf grammar

stmt-> ( CONST ‘:’)* expression ‘;’ definitely does not make much sense. the whole grammar does not make much sense to be honest. Just have a switch_stmt and then define that separately, don't wrap every single possible statement into a (CASE CONST ':')* , that is just confusing.

Commented Feb 11, 2021 at 12:05

Note that applying the restrictions you propose is changing the language from C to C- (a smaller subset of C).

Commented Feb 14, 2021 at 17:49

2 Answers 2

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. They must be both derived from the original stmt you have posted.

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_wo_case -> expression ‘;’ | IF ‘(’ expression ‘)’ stmt [ELSE stmt] | WHILE ‘(’ expression ‘)’ stmt | SWITCH ‘(’ expression ‘)’ stmt | RETURN [expression] ‘;’ | BREAK ‘;’ | CONTINUE ‘;’ | ‘’ 

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

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_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 ‘;’ | ‘’ 

(see how stmt_wo_case propagates it's condition to the embedded stmt between brackets < and >and similarly for the 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. 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? 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.

answered Feb 14, 2021 at 17:42 Luis Colorado Luis Colorado 12.3k 1 1 gold badge 17 17 silver badges 34 34 bronze badges Thank you very much. Commented Feb 22, 2021 at 16:47 I would be grateful if you can check this : stackoverflow.com/questions/66320002/… Commented Feb 22, 2021 at 17:58

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 : .

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.

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. 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. 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).

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 . 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 .