javacc' LOOKAHEAD( AllSymbols() ) AllSymbols() 未被选择,唯一被正确解析
javacc' LOOKAHEAD( AllSymbols() ) AllSymbols() not chosen, sole to be parsed correctly
紧要关头,语法如下:
Phi ::= Phi_sub ( ("&&" | "||") Phi_sub )*
Phi_sub ::= "(" Phi ")" | ...
Psi ::= Psi_sub ( ("&&" | "||") Psi_sub )*
Psi_sub ::= "(" Psi ")" | ...
Xi ::= LOOKAHEAD( Phi ) Phi | LOOKAHEAD( Psi ) Psi
如您所见,Xi 产生式通常需要无限前瞻,因为解析器需要区分以下情况:
((Phi_sub && Phi_sub) || Phi_sub)
对比 ((Psi_sub && Psi_sub) || Psi_sub)
即任意数量的前缀 (
.
我认为,像上面那样进行前瞻会起作用,但事实并非如此。例如,选择 Phi,即使 Xi 没有扩展到 Phi,而是扩展到 Psi。这可以很容易地在某个流 S 上检查,方法是在解析后立即用调试器调用 Phi,在 Xi 中决定选择 Phi,并且即将调用 Phi。在这种情况下,调试器显示对 Psi 的适当扩展,同时允许解析器仅按需要调用 Phi 会导致解析异常。
另一种测试方法是交换 Phi 和 Psi:
Xi ::= LOOKAHEAD( Psi ) Psi | LOOKAHEAD( Phi ) Phi
这将使解析器正确解析特定的 S,因此似乎只是选择了 Xi 中的第一个分支,无论它是否有效。
我想我的一些基本假设是错误的,但不知道它会是什么。如果没有其他因素,如被忽略的内部前瞻,上述一般情况下应该工作吗?
你的假设没有错。你正在尝试做的事情应该有效。它应该出于您认为它应该起作用的原因起作用。
这是一个用 JavaCC 编写的完整示例。
void Start() : {} { Xi() <EOF> }
void Xi() : {} {
LOOKAHEAD( Phi() ) Phi() { System.out.println( "Phi" ) ; }
| LOOKAHEAD( Psi() ) Psi() { System.out.println( "Psi" ) ; }
}
void Phi() : {} { Phi_sub() ( ("&&" | "||") Phi_sub() )*}
void Phi_sub() : {} { "(" Phi() ")" | "Phi_sub" }
void Psi() : {} { Psi_sub() ( ("&&" | "||") Psi_sub() )* }
void Psi_sub() : {} { "(" Psi() ")" | "Psi_sub" }
下面是一些示例输出:
Input is : <<Phi_sub>>
Phi
Input is : <<Psi_sub>>
Psi
Input is : <<((Phi_sub && Phi_sub) || Phi_sub)>>
Phi
Input is : <<((Psi_sub && Psi_sub) || Psi_sub)>>
Psi
您遇到的问题在于问题中未显示的内容。
顺便说一下,在每个备选方案之前都加上前瞻规范是个坏主意。
void X() : {} { LOOKAHEAD(Y()) Y() | LOOKAHEAD(Z()) Z() }
大致相当于
void X() : {} { LOOKAHEAD(Y()) Y() | LOOKAHEAD(Z()) Z() | fail with a stupid error message }
比如这里还有一个运行上面的语法
Input is : <<((Psi_sub && Psi_sub) || Phi_sub)>>
NOK.
Encountered "" at line 1, column 1.
Was expecting one of:
所有前瞻失败后,解析器将留下一组空的期望!
如果将 Xi
更改为
void Xi() : {} {
LOOKAHEAD( Phi() ) Phi() { System.out.println( "Phi" ) ; }
| Psi() { System.out.println( "Psi" ) ; }
}
您会收到稍微好一点的错误消息
Input is : <<((Psi_sub && Psi_sub) || Phi_sub)>>
NOK.
Encountered " "Phi_sub" "Phi_sub "" at line 1, column 26.
Was expecting one of:
"(" ...
"Psi_sub" ...
您还可以自定义错误消息
void Xi() : {} {
LOOKAHEAD( Phi() ) Phi() { System.out.println( "Phi" ) ; }
| LOOKAHEAD( Psi() ) Psi() { System.out.println( "Psi" ) ; }
| { throw new ParseException( "Expected either a Phi or a Psi at line "
+ getToken(1).beginLine
+ ", column " + getToken(1).beginColumn + "." ) ;
}
}
紧要关头,语法如下:
Phi ::= Phi_sub ( ("&&" | "||") Phi_sub )*
Phi_sub ::= "(" Phi ")" | ...
Psi ::= Psi_sub ( ("&&" | "||") Psi_sub )*
Psi_sub ::= "(" Psi ")" | ...
Xi ::= LOOKAHEAD( Phi ) Phi | LOOKAHEAD( Psi ) Psi
如您所见,Xi 产生式通常需要无限前瞻,因为解析器需要区分以下情况:
((Phi_sub && Phi_sub) || Phi_sub)
对比 ((Psi_sub && Psi_sub) || Psi_sub)
即任意数量的前缀 (
.
我认为,像上面那样进行前瞻会起作用,但事实并非如此。例如,选择 Phi,即使 Xi 没有扩展到 Phi,而是扩展到 Psi。这可以很容易地在某个流 S 上检查,方法是在解析后立即用调试器调用 Phi,在 Xi 中决定选择 Phi,并且即将调用 Phi。在这种情况下,调试器显示对 Psi 的适当扩展,同时允许解析器仅按需要调用 Phi 会导致解析异常。
另一种测试方法是交换 Phi 和 Psi:
Xi ::= LOOKAHEAD( Psi ) Psi | LOOKAHEAD( Phi ) Phi
这将使解析器正确解析特定的 S,因此似乎只是选择了 Xi 中的第一个分支,无论它是否有效。
我想我的一些基本假设是错误的,但不知道它会是什么。如果没有其他因素,如被忽略的内部前瞻,上述一般情况下应该工作吗?
你的假设没有错。你正在尝试做的事情应该有效。它应该出于您认为它应该起作用的原因起作用。
这是一个用 JavaCC 编写的完整示例。
void Start() : {} { Xi() <EOF> }
void Xi() : {} {
LOOKAHEAD( Phi() ) Phi() { System.out.println( "Phi" ) ; }
| LOOKAHEAD( Psi() ) Psi() { System.out.println( "Psi" ) ; }
}
void Phi() : {} { Phi_sub() ( ("&&" | "||") Phi_sub() )*}
void Phi_sub() : {} { "(" Phi() ")" | "Phi_sub" }
void Psi() : {} { Psi_sub() ( ("&&" | "||") Psi_sub() )* }
void Psi_sub() : {} { "(" Psi() ")" | "Psi_sub" }
下面是一些示例输出:
Input is : <<Phi_sub>>
Phi
Input is : <<Psi_sub>>
Psi
Input is : <<((Phi_sub && Phi_sub) || Phi_sub)>>
Phi
Input is : <<((Psi_sub && Psi_sub) || Psi_sub)>>
Psi
您遇到的问题在于问题中未显示的内容。
顺便说一下,在每个备选方案之前都加上前瞻规范是个坏主意。
void X() : {} { LOOKAHEAD(Y()) Y() | LOOKAHEAD(Z()) Z() }
大致相当于
void X() : {} { LOOKAHEAD(Y()) Y() | LOOKAHEAD(Z()) Z() | fail with a stupid error message }
比如这里还有一个运行上面的语法
Input is : <<((Psi_sub && Psi_sub) || Phi_sub)>>
NOK.
Encountered "" at line 1, column 1.
Was expecting one of:
所有前瞻失败后,解析器将留下一组空的期望!
如果将 Xi
更改为
void Xi() : {} {
LOOKAHEAD( Phi() ) Phi() { System.out.println( "Phi" ) ; }
| Psi() { System.out.println( "Psi" ) ; }
}
您会收到稍微好一点的错误消息
Input is : <<((Psi_sub && Psi_sub) || Phi_sub)>>
NOK.
Encountered " "Phi_sub" "Phi_sub "" at line 1, column 26.
Was expecting one of:
"(" ...
"Psi_sub" ...
您还可以自定义错误消息
void Xi() : {} {
LOOKAHEAD( Phi() ) Phi() { System.out.println( "Phi" ) ; }
| LOOKAHEAD( Psi() ) Psi() { System.out.println( "Psi" ) ; }
| { throw new ParseException( "Expected either a Phi or a Psi at line "
+ getToken(1).beginLine
+ ", column " + getToken(1).beginColumn + "." ) ;
}
}