私は最近、javacc を使用して文法アナライザーをいじり始めました。フィールドの 1 つはオプション 1 です...次のようなコードがあります。
options
{
LOOKAHEAD=1;
}
PARSER_BEGIN(Calculator)
public class Calculator
{
...
}
PARSER_END(Calculator)
LOOKAHEAD オプションとは正確にはどういう意味ですか? ありがとう
JavaCC は、再帰降下パーサーを作成します。このタイプのパーサーは、次のシンボルを見て、選択するルールを決定します。デフォルトでは、次のシンボルのみを調べます (lookahead=1)。ただし、次だけでなく、次の N 個のシンボルも調べるようにパーサーを構成できます。先読みを 2 に設定すると、生成されたパーサーは次の 2 つのシンボルを調べて、選択するルールを決定します。このようにして、文法をより自然に定義できますが、パフォーマンスが犠牲になります。先読みが大きければ大きいほど、パーサーはより多くのことをしなければなりません。
一般的な先読みをより大きな数値に設定すると、パーサーはすべての入力に対して遅くなります (重要な文法の場合)。パーサーにデフォルトで lookahead=1 を許可し、特定の状況でのみより大きな先読みを使用する場合は、ローカルで先読みを使用できます。
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を参照してください。
通常、パーサーは次のトークンのみを調べて、適用するプロダクション ルールを決定します。ただし、場合によっては、選択を行うのに十分ではありません。たとえば、次の 2 つのプロダクション ルールがあるとします。
p0: foo -> identifier "=" expr
p1: bar -> identifier "(" arglist ")"
次のトークンがタイプのidentifier
場合、パーサーは、foo
またはbar
プロダクションを使用する必要があるかどうかを判断できません。JavaCC は、さらに先読みを使用する必要があることを示すエラーを返します。先読みを 2 に変更するということは、パーサーが次の 2 つのトークンを参照できることを意味します。
Steve が指摘したように、これは javacc ドキュメントにあります: https://javacc.org/tutorials/lookahead
LOOKAHEAD 値は、生成されたパーサーに、どの状態に遷移するかを決定するために使用する未処理の (つまり、将来の) トークンの数を伝えます。厳密に制約された言語では、先読みトークンは 1 つだけ必要です。言語があいまいであるほど、どの状態遷移を行うかを決定するために、より多くの先読みトークンが必要になります。
これは javacc(1) チュートリアルでカバーされていると思います。