Посторонний ввод ANTLR на первой позиции не создает дерево - PullRequest
0 голосов
/ 29 декабря 2018

У меня проблема с посторонним вводом в моем файле примера.Я получил следующий лексер:

lexer grammar CtoLexer;

ENUM:               'enum';
NAMESPACE:          'namespace';
LBRACE:             '{';
RBRACE:             '}';
DOT:                '.';
VAR:                'o ';
IDENTIFIER:         LetterOrDigit+;

fragment LetterOrDigit
   : [a-zA-Z$_] | [0-9];

WS:                 [ \t\r\n\u000C]+ -> skip;

... и парсер:

parser grammar CtoParser;

options { tokenVocab=CtoLexer; }

modelUnit
   : namespaceDeclaration enumDeclaration* EOF;

namespaceDeclaration
   : NAMESPACE IDENTIFIER ('.' IDENTIFIER)*;

enumDeclaration
   : ENUM IDENTIFIER '{' enumConstant* '}';

enumConstant
   : VAR IDENTIFIER;

Это мой пример файла cto:

namespace org.basic.sample

enum FooType {
  o FOO
}

enum BarType {
  o BAR
}

enum BazType {
 o BAZ
}

Дерево для этогоПример файла выглядит следующим образом:

(modelUnit 
  (namespaceDeclaration namespace org . basic . sample) 
  (enumDeclaration enum FooType { (enumConstant o  FOO) }) 
  (enumDeclaration enum BarType { (enumConstant o  BAR) }) 
  (enumDeclaration enum BazType { (enumConstant o  BAZ) }) 
<EOF>)

Когда я меняю первое перечисление в образце на что-то другое, скажем, от enum до enumi, почти все дерево испорчено.Парсер распознает только пространство имен, а остальное кажется ИДЕНТИФИКАТОРОМ.

(modelUnit 
 (namespaceDeclaration namespace org . basic . sample) 
  enumi FooType { o  FOO } 
  enum BarType { o  BAR } 
  enum BazType { o  BAZ })

Однако, когда я делаю то же самое со вторым перечислением, как-то только это недействительное перечисление не распознается, а остальное в порядке.

(modelUnit 
 (namespaceDeclaration namespace org . basic . sample)
 (enumDeclaration enum FooType { (enumConstant o  FOO) }) 
 enumi BarType { o  BAR } 
 (enumDeclaration enum BazType { (enumConstant o  BAZ) }) <EOF>)

Что я могу сделать, чтобы первый ошибочный ввод был пропущен, а остальная часть была распознана?Я пробовал с новыми строковыми токенами, но это вызывает проблемы, когда я хочу ввести новое объявление после пространства имен.

1 Ответ

0 голосов
/ 30 декабря 2018

Это ограничение механизма прогнозирования, насколько я знаю.Я также видел, что в таких случаях, как этот запрос MySQL:

select * from sakila.actor where

, который помечает ключевое слово select как errorneous вместо отсутствующего выражения where.Здесь происходит то, что прогноз ALL (*) выглядит слишком далеко вниз по цепочке правил.Если есть ошибка, то она не позволяет проанализировать правильный ввод до этой ошибки, но иногда происходит сбой всего ввода.Я не нашел хорошего решения этой проблемы.Кажется, все зависит от грамматической структуры.

...