У меня есть язык, где пробелы незначительны, поэтому я его пропускаю.Вот подмножество грамматики, которую я имею до сих пор:
start: expr <EOF>;
expr
: atom
| expr '|' expr
| expr expr+
| '{' expr '}'
;
atom
: ATOM_TOKEN
;
fragment LETTER: [a-zA-Z];
fragment DIGIT: [0-9];
ATOM_TOKEN: (LETTER | DIGIT)+;
WS: [ \r\n\t]+ -> skip;
При выполнении на следующем входе (обратите внимание на пробел и его отсутствие) он правильно создает желаемое ожидаемое дерево разбора:
{hello42 | hi world}|{good bye} red blue green
Теперь моя проблема в том, что в идеале я хотел бы сделать atom
вложенным правилом, чтобы я мог выбирать характерные фигуры.
Вот пример грамматики:
atom: atomToken+;
atomToken
: LETTERS
| DIGITS
;
LETTERS: LETTER+;
DIGITS: DIGIT+;
и результат выполнения he11o
через нее (примечания 1 вместо L):
Проблема с этим подходом состоит в том, что поскольку пробелы игнорируются, что-то вроде he11o world
теперь будет анализироваться как один atom
.
Есть ли что-то очевидное, что я упускаю?Из моего исследования возникла пара возможностей.
- Напишите вторичную грамматику, чтобы использовать ее, когда мне действительно нужно извлечь куски
atom
.Это одно из самых простых решений. - Реализация какого-либо токена-инъекции путем создания подкласса сгенерированного Lexer.Это кажется очень странным, и я хотел бы избежать этого, если нет лучшего варианта.
- Делать что-то с лексическими режимами или каналами, чтобы пропуски пропускались только условно?Я почти уверен, что это не сработает, поскольку контекст для запуска этого будет исходить от синтаксического анализатора, и, насколько я знаю, вы не можете изменить поведение лексера из правил синтаксического анализатора.
- Не пропускайте пробелыи вместо этого засорять основную грамматику всеми возможными пробелами.
Любая помощь приветствуется.