Bison解析器不会预先考虑令牌

时间:2012-04-09 00:03:35

标签: parsing bison lookahead

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

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 ...”是否匹配。据我所知,Bison应该做到这一点。我最接近的猜测是%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'的人。

2 个答案:

答案 0 :(得分:0)

如果IDREF的优先级高于ASSIGN_EQUALASSIGN_ADD等,则会发生这种情况。具体来说,在这种情况下,使用原始解析器(在优先级适用之前),你有转移/减少expr: STAR expr规则与各种ASSIGN_ XXX令牌之间的冲突。您已经解决所有冲突的优先规则有利于reduce。

状态中的assignop是goto,而不是shift或reduce,因此根本不会进入前瞻或令牌处理 - 只有在某个令牌移位后才会出现,然后才会减少到有问题的非终端。

答案 1 :(得分: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'中的两个规则。