我最近开始使用 javacc 使用语法分析器,其中一个字段是选项之一...我有如下代码:
options
{
LOOKAHEAD=1;
}
PARSER_BEGIN(Calculator)
public class Calculator
{
...
}
PARSER_END(Calculator)
LOOKAHEAD 选项到底是什么意思?谢谢
JavaCC 创建递归下降解析器。这种类型的解析器通过查看下一个符号来决定选择哪个规则。默认情况下,它只查看下一个符号(lookahead=1)。但是您可以将解析器配置为不仅查看下一个符号,还查看接下来的 N 个符号。如果将前瞻设置为 2,生成的解析器将查看接下来的两个符号来决定选择哪个规则。这样,您可以更自然地定义您的语法,但要以性能为代价。前瞻越大,解析器要做的事情就越多。
如果将一般前瞻设置为更大的数字,则解析器对于所有输入(对于非平凡语法)都会变慢。如果您想让解析器默认使用lookahead=1,并且仅在特定情况下使用更大的lookahead,则可以在本地使用lookahead。
http://www.engr.mun.ca/~theo/JavaCC-FAQ/javacc-faq-moz.htm#tth_sEc4.5
例如,lookahead=1 的解析器无法决定采用哪条规则(1 或 2),但lookahead=2 可以:
void rule0() : {} {
<ID> rule1()
| <ID> rule2()
}
您可以更改语法的定义以获得相同的结果,但使用lookahead=1:
void rule0() : {} {
<ID> ( rule1() | rule2() )
}
见http://en.wikipedia.org/wiki/Lookahead#Lookahead_in_parsing
通常,解析器只查看下一个标记来确定要应用的生产规则。但是,在某些情况下,这还不足以做出选择。例如,给定两个生产规则:
p0: foo -> identifier "=" expr
p1: bar -> identifier "(" arglist ")"
如果下一个标记是类型,identifier
那么解析器无法确定它是否应该使用foo
orbar
产生式。JavaCC 然后会给出一个错误,说它需要使用更多的前瞻。将前瞻更改为 2 意味着允许解析器查看接下来的两个标记,在这种情况下,这足以在产生式之间进行选择。
正如史蒂夫指出的那样,这是在 javacc 文档中:https ://javacc.org/tutorials/lookahead
LOOKAHEAD 值告诉生成的解析器有多少未处理的(即未来的)令牌用于决定要转换到什么状态。在严格约束的语言中,只需要一个前瞻标记。语言越模糊,需要越多的前瞻标记来确定要进行哪种状态转换。
我认为这在 javacc(1) 教程中有介绍。