前段时间我正在努力为XPath步骤编写JavaCC模板,以便它支持全步骤定义和省略轴名称的定义(在这种情况下,轴名称将默认为child)。我发布了a question on SO并得到了Theodore Norvell的工作答案。
现在我正在尝试扩展模板,以便除了之前的两种可能性之外,解析器还支持使用“@”符号作为属性轴的快捷方式。
以下代码段不起作用:
Step Step() :
{
Token t;
Step step;
Axis axis;
NodeTest nodeTest;
Expression predicate;
}
{
{ axis = Axis.child; }
(
<AT>
{ axis = Axis.attribute; }
|
LOOKAHEAD( <IDENTIFIER> <DOUBLE_COLON> )
t = <IDENTIFIER>
{ axis = Axis.valueOf(t.image); }
<DOUBLE_COLON>
)?
t = <IDENTIFIER>
{ nodeTest = new NodeNameTest(t.image); }
{ step = new Step(axis, nodeTest); }
(
<OPEN_PAR>
predicate = Expression()
{ step.addPredicate(predicate); }
<CLOSE_PAR>
)*
{ return step; }
}
相反,它会发出以下警告消息:
Choice conflict in [...] construct at line 162, column 9.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: <IDENTIFIER>
Consider using a lookahead of 2 or more for nested expansion.
我已尝试以各种方式设置LOOKAHEAD参数,但唯一有效的方法是将其全局设置为2.我宁愿在本地更改它。
我该怎么做?为什么这个问题中显示的片段不起作用?
答案 0 :(得分:1)
试试这个
(
<AT>
{ axis = Axis.attribute; }
|
LOOKAHEAD( <IDENTIFIER> <DOUBLE_COLON> )
t = <IDENTIFIER>
{ axis = Axis.valueOf(t.image); }
<DOUBLE_COLON>
|
{}
)
- 编辑 -
我忘了回答第二个问题:“为什么给定的代码片段不起作用?”
您只能应用于交替的前瞻规范。我很惊讶JavaCC没有给你一个警告,因为LOOKAHEAD是最后的选择,因此没用。当解析器到达LOOKAHEAD时,它已经决定(基于下一个标记是标识符)来处理(...)?
内的部分。因此另一个解决方案是
( LOOKAHEAD( <AT> | <IDENTIFIER> <DOUBLE_COLON> )
(<AT> {...} | <IDENTIFIER> {...} <DOUBLE_COLON> )
)?