【问题标题】:Bison parser won't look-ahead for tokenBison 解析器不会提前获取令牌
【发布时间】:2012-04-09 00:03:34
【问题描述】:

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

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 文件中规则的顺序不会影响它选择哪一个;我尝试过重新排序标准'STAR expr'之上的assignop)。

【问题讨论】:

    标签: parsing bison lookahead


    【解决方案1】:

    如果IDREF 的优先级高于ASSIGN_EQUALASSIGN_ADD 等,就会发生这种情况。具体来说,在这种情况下使用原始解析器(在应用优先级之前),@987654324 之间存在移位/减少冲突@rule 和各种 ASSIGN_XXX 令牌。您拥有的优先规则解决了所有有利于减少的冲突。

    状态中的assignop 是一个 goto,而不是 shift 或 reduce,因此根本不进入前瞻或令牌处理 - goto 仅在某些令牌已移动然后随后减少到有问题的非终端。

    【讨论】:

    • 糟糕!我以为我已经删除了这个问题,因为我已经解决了。我现在最好添加我的答案...
    【解决方案2】:

    我最终通过创建另一个规则“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”中的两个规则。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多