ANTLR4 JavaScript-парсер: как отловить ошибку при разборе - PullRequest
0 голосов
/ 05 мая 2018

У меня есть грамматика в ANTLR4, вокруг которой я пишу приложение. Ниже приведен фрагмент соответствующей грамматики:

grammar SomeGrammar;
// ... a bunch of other parse rules
operand
   : id | literal ;
id
   : ID ;
literal
   : LITERAL ;
// A bunch of other lexer rules
LITERAL       : NUMBER | BOOLEAN | STRING;
NUMBER        : INTEGER | FLOAT ;
INTEGER       : [0-9]+ ;
FLOAT         : INTEGER '.' INTEGER | '.' INTEGER ;
BOOLEAN       : 'TRUE' | 'FALSE' ;
ID            : [A-Za-z]+[A-Za-z0-9_]* ;
STRING        : '"' .*? '"' ;

Я генерирую antlr4 JavaScript Lexer и Parser следующим образом:

$ antlr4 -o . -Dlanguage=JavaScript -listener -visitor

и затем я перегружаю прототип exitLiteral (), чтобы проверить, является ли операнд литералом. Проблема в том, что если я пройду

a

it (force) анализирует его до литерала и выдает ошибку (например, ниже показано grun):

$ grun YARL literal -gui -tree
a
line 1:0 mismatched input 'a' expecting LITERAL
(literal a)

Та же ошибка, когда я использую парсер JavaScript, который я перегрузил следующим образом:

SomeGrammarLiteralPrinter.prototype.exitLiteral = function (ctx) {
    debug ("Literal is " + ctx.getText ()); // Literal is a
    };

Я бы хотел уловить ошибку, чтобы я мог решить, что это ID, а не LITERAL. Как мне это сделать?

Любая помощь приветствуется.

1 Ответ

0 голосов
/ 05 мая 2018

Лучшее решение - настроить грамматику так, чтобы она точно описывала предполагаемый синтаксис для начала:

startRule : ruleA ruleB EOF ;
ruleA     : something operand anotherthing ;
ruleB     : id assign literal  ;

operand   : ID | LITERAL ;
id        : ID ;
literal   : LITERAL ;

Анализатор выполняет оценку правил синтаксического анализа сверху вниз, начиная с startRule. Таким образом, синтаксический анализатор будет оценивать перечисленные элементы startRule по порядку, последовательно опускаясь по названным подправилам (и только этим подправилам). Следовательно, ruleA не встретит / не рассмотрит правила id и literal.

В этом ограниченном примере нет конфликта в, казалось бы, перекрывающихся определениях правил operand, id и literal.

Обновление

Класс OperandContext будет содержать ID() и LITERAL() методы, возвращающие TerminalNode. Тот, который не возвращает ноль, представляет символ, который был фактически сопоставлен в этом конкретном контексте. Посмотрите на сгенерированный код.

...