0
...
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);
} 
...

赋值表达式是可以使用 C 运算符的任何赋值表达式=, +=, -=, *=, /=

LP = (
RP = )

marker并且Next都是EMPTY规则

上述语法规则和实现的问题是表达式为 as 时无法生成正确的代码

bool a;
if(a){
  printf("hi");
}
else{
  prinf("die");
}

它期望 assignment-expression 必须包含reloporORANDto generate 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 语法规则,但无法解决这个问题。完整的语法可以在这里找到Github

4

2 回答 2

1

看起来您的语法对expression.

赋值表达式只是应该能够简化为表达式的许多非终结符之一。对于 if/then/else 构造,您通常需要允许在括号之间出现任何表达式。正如您所指出的,您的第一个示例是完全有效的 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{}
;

我无法真正验证这是否适合您,它可能并不完美,但希望您能明白这一点。每种不同类型的表达式都需要能够简化为一个表达式。你在语法的早期有一些非常相似的东西statement,所以这应该是有道理的。

阅读或观看一些关于LR 语法如何工作的教程可能会有所帮助。

于 2015-04-09T17:17:51.247 回答
1

为了插入中间规则动作,您需要左因子;否则,野牛生成的解析器无法决定要减少两个 MRA 中的哪一个。(即使它们可能是相同的,野牛也不知道。)

if_prefix: "if" '(' expression ')' { $$ = $3; /* Normalize the flist */ }
if: if_prefix marker statement { ... }
  | if_prefix marker statement "else" Next statement { ... }

(你可以留下不同的因素;这只是一个建议。)

于 2015-04-09T22:33:22.977 回答