まず第一に、ANTLRのレクサーは入力を上から下にトークン化します。したがって、最初に定義されたトークンは、その下のトークンよりも優先されます。また、ルールに重複するトークンがある場合、ほとんどの文字に一致するルールが優先されます(欲張り一致)。
同じ原則がパーサールールにも当てはまります。最初に定義されたルールも最初に照合されます。たとえば、ルールfoo
では、サブルールa
は最初に次の前に試行されb
ます。
foo
: a
| b
;
あなたの場合、2番目のルールは一致していませんが、一致しようとしますが、末尾の改行がないために失敗し、エラーが発生することに注意してください。
line 0:-1 mismatched input '<EOF>' expecting NEW_LINE
したがって、何も一致しません。しかし、それは奇妙です。を設定したのでbacktrack=true
、少なくともバックトラックして一致する必要があります。
first_rule
(「ここに最初のトークン」)
any_left_over_tokens
(「改行」)
any_left_over_tokens
(「ここに2番目のトークン」)
そもそも一致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
)+
;
、両方とも期待される出力を生成します。
だから、私の推測では、あなたはバグを見つけたかもしれません。
決定的な答えが必要な場合は、ANTLRメーリングリストを試すことができます(Terence Parrは、ここよりも頻繁にそこに頻繁にアクセスします)。
幸運を!
PS。私はこれをANTLRv3.2でテストしました