次のように、それぞれが別々の行にある一連の単純な英語のステートメントのような入力があるとします。
Alice checks
Bob bets 100
Charlie raises 100
Alice folds
この文法で構文解析してみましょう。
actions: action* EOF;
action: player=name (check | call | raise | fold) NEWLINE;
check: 'checks';
call: 'calls' amount;
raise: 'raises' amount;
fold: 'folds';
name: /* The subject of this question */;
amount: '$'? INT;
INT: ('0'..'9')+;
NEWLINE: '\r'? '\n';
異なる動詞の数は固定されていますが、興味深いのは、一致させようとしている名前にスペースが含まれている可能性があることです。動詞もその一部である可能性があります。したがって、次の入力が有効です。
Guy who always bets 100 checks
Guy who always checks bets 100
Guy who always calls folds
Guy who always folds raises 100
Guy who always checks and then raises bets by others calls $100
だから問題は、私たちが通常動詞として扱っているスペースや単語を食べるのに十分貪欲であるが、動詞が規則によって一致することができるように超貪欲ではないように定義するにはどうすればよいですか?name
action
このタスクを解決するための私の最初の試みは、次のようになりました。
name: WORD (S WORD)*;
WORD: ('a'..'z'|'A'..'Z'|'0'..'9')+; // Yes, 1234 is a WORD, too...
S: ' '; // We have to keep spaces in names
残念ながら、これは「常に賭ける男」とは一致しません。これはbets
、ではなく、ルールWORD
のリテラルによって定義された別のトークンであるためです。のようなルールを作成し、リテラルの代わりに他のルールを一致させることでそれbets
を回避したかったのですが、それが行き詰まりました。(私はすべての動詞を有効な代替としてリストして、の一部にすることができると思いますが、それは間違っていると感じます。)keyword[String word]
keyword["bets"]
name
さらに、すべてのname
sが使用される前に宣言されているため、sの解析を開始する前にそれらを読み取ることができますaction
。また、MAX_NAME_LENGTH文字より長くすることはできません。ここで何か役に立ちますか?
とにかく、私はそれを間違っているのかもしれません。ANTLRの達人、私はあなたから聞くことができますか?