我有以下解析器语法(这是一个小样本):
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'的人。
答案 0 :(得分:0)
如果IDREF
的优先级高于ASSIGN_EQUAL
,ASSIGN_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'中的两个规则。