0

我有以下解析器语法(这是一个小示例):

expr:
        ident assignop expr
        {
            $$ = new NAssignment(new NAssignmentIdentifier(*$1), $2, *$3);
        } |
        STAR expr %prec IDEREF
        {
            $$ = new NDereferenceOperator(*$2);
        } |
        STAR expr assignop expr %prec IDEREF
        {
            $$ = new NAssignment(new NAssignmentDereference(*$2), $3, *$4);
        } |
        ... ;

...

assignop:
        ASSIGN_EQUAL |
        ASSIGN_ADD |
        ASSIGN_SUBTRACT |
        ASSIGN_MULTIPLY |
        ASSIGN_DIVIDE ;

现在我正在尝试解析以下任何一行:

*0x8000 = 0x7000;
*mem = 0x7000;

但是,Bison 一直看到“*mem”并减少了“STAR expr”规则,并且没有执行前瞻来查看“STAR expr assignop...”是否匹配。据我了解野牛,它应该做这个前瞻性。我最接近的猜测是 %prec 正在关闭前瞻或类似的奇怪东西,但我不明白为什么会这样做(因为 prec 值是相等的)。

在这种情况下,如何让它执行前瞻?

编辑:

遇到'STAR expr'时进入的状态是:

state 45

   28 expr: STAR expr .
   29     | STAR expr . assignop expr
   35     | expr . binaryop expr

    $default  reduce using rule 28 (expr)

    assignop  go to state 81
    binaryop  go to state 79

所以我不明白为什么它可以选择 assignop 时选择 $default (请注意,在这种情况下,parser.y 文件中规则的顺序不会影响它选择哪一个;我已经尝试重新排序 assignop 一个高于标准的'STAR expr')。

4

2 回答 2

0

如果IDREF优先级高于ASSIGN_EQUAL,等,就会发生这种情况。具体来说,在这种情况下,使用原始解析器(在应用优先级之前),您在规则和各种XXX 标记ASSIGN_ADD之间存在移位/减少冲突。您拥有的优先规则解决了所有有利于减少的冲突。expr: STAR exprASSIGN_

in 状态是 goto,而assignop不是 shift 或 reduce,因此根本不进入前瞻或令牌处理 - goto 仅在某些令牌被移动然后减少到有问题的非终端后才会发生。

于 2012-04-09T01:40:38.043 回答
0

我最终通过创建另一个规则“deref”来解决这个问题,如下所示:

deref:
        STAR ident
        {
            $$ = new NDereferenceOperator(*$<ident>2);
        } |
        STAR numeric
        {
            $$ = new NDereferenceOperator(*$2);
        } |
        STAR CURVED_OPEN expr CURVED_CLOSE
        {
            $$ = new NDereferenceOperator(*$3);
        } |
        deref assignop expr
        {
            if ($1->cType == "expression-dereference") // We can't accept NAssignments as the deref in this case.
                $$ = new NAssignment(new NAssignmentDereference(((NDereferenceOperator*)$1)->expr), $2, *$3);
            else
                throw new CompilerException("Unable to apply dereferencing assignment operation to non-dereference operator based LHS.");
        } ;

用单个“deref”替换“expr”中的两个规则。

于 2012-04-09T05:32:48.957 回答