9

私は最近、javacc を使用して文法アナライザーをいじり始めました。フィールドの 1 つはオプション 1 です...次のようなコードがあります。

options
{
  LOOKAHEAD=1;
}
PARSER_BEGIN(Calculator)

public class Calculator
{
 ...
}
PARSER_END(Calculator)

LOOKAHEAD オプションとは正確にはどういう意味ですか? ありがとう

4

3 に答える 3

8

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() )
}
于 2010-02-20T16:59:32.213 に答える
7

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

于 2010-02-20T16:57:06.023 に答える
2

LOOKAHEAD 値は、生成されたパーサーに、どの状態に遷移するかを決定するために使用する未処理の (つまり、将来の) トークンの数を伝えます。厳密に制約された言語では、先読みトークンは 1 つだけ必要です。言語があいまいであるほど、どの状態遷移を行うかを決定するために、より多くの先読みトークンが必要になります。

これは javacc(1) チュートリアルでカバーされていると思います。

于 2010-02-20T16:59:13.493 に答える