避免使用不改变前瞻的通用前缀
Avoid common prefixes without change lookahead
我正在使用 JavaCC 制定识别语言的规范。我遇到的问题是 JavaCC 给了我一个警告,因为 public 是 Member() 声明的公共前缀。 Member() 可以有 Attributes() and/or Method() 但必须至少有一个 Method,顺序无关紧要。
JavaCC 给我的警告是:
第 66 行第 23 列的 (...)+ 构造中的选择冲突。
嵌套在构造内的扩展和构造后的扩展具有共同的前缀,其中之一是:"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() ")"
}
谢谢。
问题是这个正则表达式
(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())*
. 识别
- 使用前瞻抑制警告。你说你不想添加前瞻性,但为了完整起见,我会提到你可以将
(Method())+
更改为 (LOOKAHEAD(1) Method())+
。这不会改变解析器的行为,但会抑制警告。
- 重写语法。
违规行可以改写为
(Attribute())* Method() (Attribute() | Method())*
或
(Attribute())* (Method())+ [Attribute() (Attribute() | Method())*]
我正在使用 JavaCC 制定识别语言的规范。我遇到的问题是 JavaCC 给了我一个警告,因为 public 是 Member() 声明的公共前缀。 Member() 可以有 Attributes() and/or Method() 但必须至少有一个 Method,顺序无关紧要。
JavaCC 给我的警告是:
第 66 行第 23 列的 (...)+ 构造中的选择冲突。 嵌套在构造内的扩展和构造后的扩展具有共同的前缀,其中之一是:"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() ")"
}
谢谢。
问题是这个正则表达式
(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())*
. 识别
- 使用前瞻抑制警告。你说你不想添加前瞻性,但为了完整起见,我会提到你可以将
(Method())+
更改为(LOOKAHEAD(1) Method())+
。这不会改变解析器的行为,但会抑制警告。 - 重写语法。
违规行可以改写为
(Attribute())* Method() (Attribute() | Method())*
或
(Attribute())* (Method())+ [Attribute() (Attribute() | Method())*]