Грамматика ANTLR: логический литерал, который может встречаться как квалифицированное имя переменной, игнорируя пробел - PullRequest
1 голос
/ 28 марта 2019

Я создаю интерпретатор в 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, но я тоже это попробовал, но безуспешно.

Или получите квалифицированное имя, работающее без точки, когда правило перемещено в правило лексера.

Спасибо.

1 Ответ

0 голосов
/ 28 марта 2019

Вы можете сделать что-то вроде этого:

qualifiedName
 : ID ('.' (anyId | INT))*
 ;

anyId
 : ID
 | TRUE
 | FALSE
 ;
...