我目前使用JavaCC实现JavaScript / ECMAScript 5.1解析器。我最近learned关于LOOKAHEAD
,在这里很方便,因为语法不是完全LL(1)。
我在ECMAScript语法中看到的一件事是“负超前检查”,如以下ExpressionStatement
生产中所示:
ExpressionStatement :
[lookahead ∉ {{, function}] Expression ;
所以我可能需要
LOOKAHEAD(!("{" | "function"))
之类的东西,但是它不能在这种语法下工作。我的问题是,如何在JavaCC中实现此“负
LOOKAHEAD
”?阅读LOOKAHEAD MiniTutorial之后,我认为可能需要像
getToken(1).kind != FUNCTION
这样的表达式,但是我不太确定。 最佳答案
对于您提供的示例,我希望使用句法向前看,从某种意义上说,这一定是“积极的”。
ExpressionStatement的产生不是解决问题的地方,因为别无选择。
void ExpressionStatement() : {} { Expression() ";" }
如果在表达式语句和块之间或者在表达式语句和函数声明(或两者)之间进行选择,就会出现问题。
例如。在声明中,您会发现
void Statement() :{} {
...
|
Block()
|
ExpressionStatement()
| ...
}
发出警告,因为两个选择都可以以“ {”开头。您有两个选择。一种是忽略警告。只要Block排名第一,就将是第一选择,并且一切都会好起来。第二种选择是使用超前规范抑制警告。像这样:
void Statement() :{} {
...
|
LOOKAHEAD("{") Block()
|
ExpressionStatement()
| ...
}
从某种意义上说,语法向前看是积极的-“如果X则采用此替代方法”。
如果您确实想要否定的符号,即“如果不是X,请采用其他替代方法”,请注意它必须是语义的。
在声明的情况下,您可以写
void Statement() :{} {
...
|
LOOKAHEAD({!(getToken(1)==LBRACE)}) ExpressionStatement()
|
Block()
}
我确保这是最后两种选择,因为否则您需要在阻止ExpressionStatement()的一组令牌中包括更多令牌,例如如果下一个标记是“ if”,“ while”或“ for”等,则不应选择该标记。
总体而言,最好在可能的情况下使用语法超前。通常更直接,更难弄乱。