まず、ANTLRのレクサーは、上から下への入力をトークン化します。したがって、最初に定義されたトークンは、それよりも優先順位が高くなります。ルールに重複トークンがある場合は、ほとんどの文字に一致するルールが優先されます(貪欲な一致)。
パーサーの規則にも同じ原則があります。最初に定義されたルールも最初に一致します。たとえば、ルールfoo
で、サブルールa
は最初b
の前に試されます:
foo
: a
| b
;
注あなたのケースでは、2 NDルールがマッチした、しかし、そうしようとし、失敗していないこと末尾に改行がないため、エラーが発生します。
line 0:-1 mismatched input '<EOF>' expecting NEW_LINE
これはまったく一致しません。しかし、は、が奇数です。
first_rule
( "ここで最初のトークン")
any_left_over_tokens
( "改行")
any_left_over_tokens
:あなたはbacktrack=true
を設定しているので、それは、少なくともバックトラックと一致している必要があります最初の場所でfirst_rule
と一致しない場合(「ここでは第二のトークン」)
また、最初にsecond_rule
に一致するようにしてください。
述語を手動で行うときの簡単なデモ(のオプション{backtrack
を無効にする...
クラスでテストすることができ grammar T;
options {
output=AST;
//backtrack=true;
memoize=true;
}
rule_list_in_order
: ((first_rule)=> first_rule {System.out.println("first_rule=[" + $first_rule.text + "]");}
| (second_rule)=> second_rule {System.out.println("second_rule=[" + $second_rule.text + "]");}
| any_left_over_tokens {System.out.println("any_left_over_tokens=[" + $any_left_over_tokens.text + "]");}
)+
;
first_rule
: FIRST_TOKEN
;
second_rule
: FIRST_TOKEN NEW_LINE SECOND_TOKEN NEW_LINE
;
any_left_over_tokens
: NEW_LINE
| FIRST_TOKEN
| SECOND_TOKEN
;
FIRST_TOKEN : 'First token here';
SECOND_TOKEN : 'Second token here';
NEW_LINE : ('\r'?'\n');
WS : (' '|'\t'|'\u000C') {$channel=HIDDEN;};
:
期待出力生成 import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
String source = "First token here\nSecond token here";
ANTLRStringStream in = new ANTLRStringStream(source);
TLexer lexer = new TLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
TParser parser = new TParser(tokens);
parser.rule_list_in_order();
}
}
:それは問題ではないことを
first_rule=[First token here]
any_left_over_tokens=[
]
any_left_over_tokens=[Second token here]
注}部)は次のようになりますあなたが使用する場合:
rule_list_in_order
: ((first_rule)=> first_rule
| (second_rule)=> second_rule
| any_left_over_tokens
)+
;
または
rule_list_in_order
: ((second_rule)=> second_rule // <--+--- swapped
| (first_rule)=> first_rule // <-/
| any_left_over_tokens
)+
;
のいずれも、期待される出力を生成します。
私の推測では、あなたがバグを見つけた可能性があります。
あなたは決定的な回答が必要な場合に備えて、YoutはANTLRメーリングリストを試すことができます(ここでは頻繁にTerence Parrが頻繁に訪れます)。
幸運を祈る!
PS。私はANTLR v3.2でこれをテストしました
ありがとうBart - いつものように洞察力があります。参考のために、入力は「ここでは最初のトークン\ n 2番目のトークン\ n」となっていました。第2の\ nの不在はタイプオです。メーリングリストも試してみます。 –
@リチャード、ああ、私は(改行について)見る。はい、2番目のルール*が一致します。メモリがうまく機能している場合は、backtrack-optionを有効にして、パーサーができるだけ一致するようにしたので、1番目のサブルールに一致してから2番目のサブルールにバックトラッキングし、それにぴったり合っているので、それに固執しています(しかし、私はそれについて100%確信していません。あなたがメーリングリストに投稿しているなら、それも尋ねてください!:))。あなたはもちろん歓迎です! –