Я создаю интерпретатор в Java, используя ANTLR.У меня есть грамматика, которой я давно пользуюсь, и я построил много кода вокруг классов, сгенерированных из этой грамматики.
В грамматике 'false' определяется как литерал, а также есть определение имени переменной, которое позволяет строить имена переменных из цифр, чисел, подчеркиваний и точек (см. Определение ниже).
Проблема в том, когда я использую 'false' в качестве имени переменной.varName.nestedVar.false
.Правило, которое помечает false
как falseLiteral, имеет приоритет.
Я пытался играть с пробелами, используя все, что нашел в Интернете.Решение, когда я удаляю WHITESPACE : [ \t\r\n] -> channel (HIDDEN);
и использую явные WS * или WS + в каждом правиле, будет работать для синтаксического анализатора, но мне придется корректировать много кода в посетителях AST.Я пытаюсь сказать правилу boolLiteral, что перед фактическим литералом должно быть некоторое пространство, например WHITESPACE * trueLiteral, но это не работает, когда пробелы отправляются на канал HIDDEN.И снова отключите его вообще = много переписывания кода.(Поскольку я часто полагаюсь на порядок токенов.) Я также пытался изменить порядок нетерминалов в буквальном правиле, но это никак не повлияло.
...
literal:
boolLiteral
| doubleLiteral
| longLiteral
| stringLiteral
| nullLiteral
| varExpression
;
boolLiteral:
trueLiteral | falseLiteral
;
trueLiteral:
TRUE
;
falseLiteral:
FALSE
;
varExpression:
name=qualifiedName ...
;
...
qualifiedName:
ID ('.' (ID | INT))*
...
TRUE : [Tt] [Rr] [Uu] [Ee];
FALSE : [Ff] [Aa] [Ll] [Ss] [Ee];
ID : (LETTER | '_') (LETTER | DIGIT | '_')* ;
INT : DIGIT+ ;
POINT : '.' ;
...
WHITESPACE : [ \t\r\n] -> channel (HIDDEN);
Лучше всего было переместить определение квалифицированного имени вПриманка лексера
qualifiedName:
QUAL_NAME
;
QUAL_NAME: ID ('.' (ID | INT))* ;
Тогда это работает для
varName.false AND false
varName.whatever.ntimes AND false
Результат верен -> varExpression-> quilafiedName с левой стороны и boolLiteral -> falseLiteral с правой стороны,Но с этим определением это не работает, и я действительно не знаю, почему
varName AND false
Квалифицированное имя без.возвращает
line 1:8 no viable alternative at input 'varName AND'
Ожидаемым решением будет включение / отключение эфира пробелами -> канал {hiddne} только для определенных правил
Скажите правилу boolLiteral, что оно НЕ МОЖЕТ начинаться с точки, что-то вроде ~ТОЧКА falseLiteral, но я тоже это попробовал, но безуспешно.
Или получите квалифицированное имя, работающее без точки, когда правило перемещено в правило лексера.
Спасибо.