ANTLR: грамматика с прописными правилами не распознает ввод - PullRequest
0 голосов
/ 05 июня 2018

Я довольно новичок в ANTLR, и мне нужно объяснение его поведения при распознавании входной строки.Из того, что я понял, правила, начинающиеся с заглавной буквы, являются правилами лексера, а правила, начинающиеся с заглавной буквы, являются правилами синтаксического анализатора.
У меня есть следующий язык, и мне нужно написать грамматику соответственно:
language
Таким образом, L должен принимать все строки, состоящие из:

  • непустая строка с b и / или c
  • d
  • непустая строка с a и / илиc

Это первая грамматика, которую я написал, и у меня нет проблем с ней при распознавании ввода bbbcbcbcbcdaaacacacaaaa:

start   : (alfa 'd' beta);

alfa    : ('b'|'c') | ('b'|'c') alfa;
beta    : ('a'|'c') | ('a'|'c') beta;

WS      : (' '|'\n'|'\t'|'\r')->skip;

Но если я изменю ее какпосле этого та же строка больше не распознается (ниже вы можете увидеть результат отладчика ANTLRWorks):

enter image description here

start   : (alfa 'd' beta);

alfa    : ALFA_VALS | ALFA_VALS alfa;
beta    : BETA_VALS | BETA_VALS beta;

ALFA_VALS: ('b'|'c');
BETA_VALS: ('a'|'c');
WS      : (' '|'\n'|'\t'|'\r')->skip;

Кроме того, если яизмените ALFA_VALS и BETA_VALS на alfa_vals и beta_vals соответственно, проблем не возникает.

Может ли кто-нибудь дать мне объяснение этому поведению?Потому что я не смог найти конкретный способ решения этой проблемы.
Большое вам спасибо!

Ответы [ 2 ]

0 голосов
/ 06 июня 2018

Могу ли я предложить немного другой подход?Ваше правильное рекурсивное определение довольно нетипично для ANTLR (хотя очень часто используется в синтаксических анализаторах снизу вверх).Вместо этого используйте более простые выражения, определенные на вашем языке:

grammar Example;

start   : (α D β) EOF;

α: (B | C)+;
β: (A | C)+;

A: 'a';
B: 'b';
C: 'c';
D: 'd';

WS: (' '|'\n'|'\t'|'\r') -> skip;

, что дает вам более простое и естественное дерево разбора:

enter image description here

0 голосов
/ 05 июня 2018

Лексер ANTLR соответствует самой длинной возможной подпоследовательности ввода, или, если он может совпадать с одним и тем же вводом, используя несколько правил лексера, он использует первое соответствующее правило.

Лексер не знает контекста и нетанализирует состояние и принимает решение только на основе символов на входе.

Если вы определите ALFA_VALS и BETA_VALS в лексере таким образом, вход 'c' будет всегда совпадать какALFA_VALS токен.

...