避免使用常见前缀而不做更改前瞻

时间:2015-06-19 10:29:33

标签: javacc

我正在使用JavaCC制作规范以识别语言。我遇到的问题是JavaCC给了我一个警告,因为public是Member()声明的公共前缀。 Member()可以有Attributes()和/或Method()但必须至少有一个Method,顺序无关紧要。

JavaCC给我的警告是:

第66行第26行的(......)+构造中的选择冲突。 嵌套在构造和扩展之后的构造具有共同的前缀,其中之一是:“public”。考虑使用2或更多的前瞻来进行嵌套扩展。

第66行是Member()的唯一一行。此外,我需要这样做没有变化前瞻值

以下是代码:

void Member() : {}
    {
        (Attribute())* (Method())+ (Attribute() | Method())*
    }

void Attribute() : {}
    {
        "private" Type() <Id> [":=" Expr()]";"
    }

void Method() : {}
    {
        MethodHead() MethodBody()
    }

void MethodHead() : {}
    {
        ("public")? (<Id> | Type() | "void") <Id> "(" Parameter() ")"
    }

感谢。

1 个答案:

答案 0 :(得分:0)

问题在于这个正则表达式

 (Method())+ (Attribute() | Method())*

含糊不清。设M的缩写方法和A的属性。如果输入是MAM,则没有问题。 (Method())+匹配前M个,(Attribute() | Method())*匹配剩余的AM。但如果输入是MMA,那么除法应该在哪里? (Method())+匹配M且(Attribute() | Method())*匹配MA或(Method())+匹配MM和(Attribute() | Method())*匹配A.两种解析都是可能的。 JavaCC并不知道你想要哪个解析,所以它会抱怨。

你能做什么:

  • 无。忽略警告。默认行为是(Method())+将识别尽可能多的方法,(Attribute() | Method())*只能识别第一个属性后的方法。
  • 使用lookahead抑制警告。您说您不想添加前瞻,但为了完整起见,我提到您可以将(Method())+更改为(LOOKAHEAD(1) Method())+。这不会改变解析器的行为,但会抑制警告。
  • 重写语法。

违规行可以重写为

(Attribute())* Method() (Attribute() | Method())*

(Attribute())* (Method())+ [Attribute() (Attribute() | Method())*]