...
IF LP assignment-expression RP marker statement {
backpatch($3.tlist,$5.instr);
$$.nextList = mergeList($3.flist,$6.nextList);
}
|IF LP assignment-expression RP marker statement ELSE Next statement {
backpatch($3.tlist,$5.instr);
backpatch($3.flist,$8.instr);
YYSTYPE::BackpatchList *temp = mergeList($6.nextList,$8.nextList);
$$.nextList = mergeList(temp,$9.nextList);
}
...
Assignment-expression是使用C运算符=, +=, -=, *=, /=
可能的任何赋值表达式。
LP = (
RP = )
marker
和Next
都是EMPTY
规则
上面的语法规则和实现的问题是,当表达式为
时,它无法生成正确的代码bool a;
if(a){
printf("hi");
}
else{
prinf("die");
}
它期望赋值表达式必须包含relop
或OR
或AND
到generate correct code
。
由于在这种情况下,我们对relop
进行了比较,同样的情况适用于OR
和AND
。
但是因为上面的代码中没有包含任何东西,所以它无法生成正确的代码。
可以使用以下规则生成正确的代码,但这会导致two reduce-reduce conflict
。
...
IF LP assignment-expression {
if($3.flist == NULL && $3.tlist == NULL)
...
} RP marker statement {
...
}
|IF LP assignment-expression{
if($3.flist == NULL && $3.tlist == NULL)
...
} RP marker statement ELSE Next statement {
...
}
...
我应该在语法规则中进行哪些修改,以便它能按预期工作?
我试过IF ELSE grammar rule 从这里以及龙书但无法解决这个问题。 整个语法可以在Github
找到答案 0 :(得分:1)
看起来你的语法对expression
的定义不正确。
赋值表达式只是应该能够缩减为表达式的许多非终端中的一个。对于if / then / else构造,通常需要在parens之间允许任何表达式。正如你所指出的,你的第一个例子是完全有效的C,但不包含任务。
在你的语法中,你有这一行:
/*Expression list**/
expression:
assignment-expression{}
|expression COMMA assignment-expression{}
;
但是,表达式应该能够包含多个赋值表达式。我不太熟悉yacc / bison,我猜您需要将其更改为以下内容:
/*Expression **/
expression:
assignment-expression{}
|logical-OR-expression{}
|logical-AND-expression{}
|inclusive-OR-expression{}
|exclusive-OR-expression{}
|inclusive-AND-expression{}
|equality-expression{}
|relational-expression{}
|additive-expression{}
|multiplicative-expression{}
|exponentiation-expression{}
|unary-expression{}
|postfix-expression{}
|primary-expression{}
|expression COMMA expression{}
;
我无法确认这对你有用,而且可能不完美,但希望你能得到这个想法。每种不同类型的表达式都需要能够简化为表达式。 1}}你的语法中有一些非常相似的东西,所以这应该是有道理的。
在how LR grammars work上阅读或观看一些教程可能会有所帮助。
答案 1 :(得分:1)
为了插入中规则动作,你需要左因子;否则,野牛生成的解析器无法决定减少两个MRA中的哪一个。 (尽管它们大概相同,但野牛并不知道。)
if_prefix: "if" '(' expression ')' { $$ = $3; /* Normalize the flist */ }
if: if_prefix marker statement { ... }
| if_prefix marker statement "else" Next statement { ... }
(你可能会有不同的因素;这只是一个建议。)