0

不久前,我正在努力为 XPath 步骤编写 JavaCC 模板,以便它支持完整的步骤定义和省略轴名称的定义(在这种情况下,轴名称将默认为 child)。我在 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。不过我更喜欢在本地更改它。

我怎么做?为什么这个问题中显示的代码段不起作用?

4

1 回答 1

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> )
)?
于 2013-06-25T10:40:07.657 回答