在编译器语法中翻译if then else

时间:2015-04-09 17:01:55

标签: c compiler-construction bison lex lr

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

markerNext都是EMPTY规则

上面的语法规则和实现的问题是,当表达式为

时,它无法生成正确的代码
bool a;
if(a){
  printf("hi");
}
else{
  prinf("die");
}

它期望赋值表达式必须包含relopORANDgenerate correct code。 由于在这种情况下,我们对relop进行了比较,同样的情况适用于ORAND

但是因为上面的代码中没有包含任何东西,所以它无法生成正确的代码。 可以使用以下规则生成正确的代码,但这会导致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

找到

2 个答案:

答案 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{}
;

我无法确认这对你有用,而且可能不完美,但希望你能得到这个想法。每种不同类型的表达式都需要能够简化为表达式。

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

(你可能会有不同的因素;这只是一个建议。)