Прежде всего, лексер ANTLR будет токенизировать ввод сверху вниз.Таким образом, токены, определенные первыми, имеют более высокий приоритет, чем те, которые находятся под ним.А в случае, если у правила есть перекрывающиеся токены, правило, которое соответствует большинству символов, будет иметь приоритет (жадное совпадение).
Тот же принцип действует в правилах синтаксического анализатора.Правила, определенные первыми, также будут сопоставляться первыми.Например, в правиле foo
сначала будет проверено подправило a
до b
:
foo
: a
| b
;
Обратите внимание, что в вашем случае правило 2 nd нене соответствует, но пытается это сделать и завершается неудачей, потому что нет завершающего разрыва строки, что приводит к ошибке:
line 0:-1 mismatched input '<EOF>' expecting NEW_LINE
Итак, ничего не найдено вообще.Но , что странно.Поскольку вы установили backtrack=true
, он должен по крайней мере вернуться назад и соответствовать:
first_rule
(«Первый токен здесь») any_left_over_tokens
("разрыв строки") any_left_over_tokens
("Второй токен здесь")
, если не совпадают first_rule
во-первых и даже не пытаться сопоставить second_rule
для начала.
Быстрая демонстрация при выполнении предикатов вручную (и отключение backtrack
в опциях {...} section) будет выглядеть следующим образом:
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, если вы хотите получить точный ответ (Теренс Парр часто бывает там чаще, чем он здесь).
Удачи!
PS.Я проверил это с ANTLR v3.2