2016-09-16 7 views
2

Я пытаюсь разработать новый язык с Antlr. Вот мой файл грамматики:Antlr4 как обнаружить непризнанный токен и данное предложение недопустимо

grammar test; 

program : vr'.' to'.' e 
     ; 
e: be 
| be'.' top'.' be 
; 
be: 'fg' 
    | 'fs' 
    | 'mc' 
    ; 
to: 'n' 
    | 'a' 
    | 'ev' 
    ; 
vr: 'er' 
    | 'fp' 
    ; 
top: 'b' 
    | 'af' 
    ; 
Whitespace : [ \t\r\n]+ ->skip 
      ; 

Main.java

String expression = "fp.n.fss"; 
//String expression = "fp.n.fs.fs"; 
ANTLRInputStream input = new ANTLRInputStream(expression); 
testLexer lexer = new testLexer(input); 
CommonTokenStream tokens = new CommonTokenStream(lexer); 
testParser parser = new testParser(tokens); 
//remove listener and add listener does not work 
ParseTree parseTree = parser.program(); 

Все хорошо для действительных предложений. Но я хочу поймать нераспознанные токены и недействительные предложения, чтобы возвращать содержательные сообщения. Вот два теста для моей проблемы.

fp.n.fss => anltr gives this error token recognition error at: 's' but i could not handle this error. There are same example error handler class which use BaseErrorListener but in my case it does not work.
fp.n.fs.fs => this sentence is invalid for my grammar but i could not catch. How can i catch invalidations like this sentence?

ответ

2

Во-первых, добро пожаловать в SO, а также в раздел ANTLR! Обработка ошибок, по-видимому, является одной из тех тем, о которых часто спрашивают, здесь очень хороший поток об обработке ошибок в Java/ANTLR4.

Вы, скорее всего, хотели расширить функциональность функции defaultErrorStrategy, чтобы обрабатывать конкретные проблемы и обрабатывать их по-другому, просто печатая ошибку распознавания маркера ошибки 1:12 по адресу: 's'.

Для этого вы можете реализовать свою собственную версию класса стратегии ошибки по умолчанию:

Parser parser = new testParser(tokens); 
      parser.setErrorHandler(new DefaultErrorStrategy() 
    { 

     @Override 
     public void recover(Parser recognizer, RecognitionException e) { 
      for (ParserRuleContext context = recognizer.getContext(); context != null; context = context.getParent()) { 
       context.exception = e; 
      } 

      throw new ParseCancellationException(e); 
     } 


     @Override 
     public Token recoverInline(Parser recognizer) 
      throws RecognitionException 
     { 
      InputMismatchException e = new InputMismatchException(recognizer); 
      for (ParserRuleContext context = recognizer.getContext(); context != null; context = context.getParent()) { 
       context.exception = e; 
      } 

      throw new ParseCancellationException(e); 
     } 
    }); 

parser.program(); //back to first rule in your grammar 

Я хотел бы также рекомендовать разделив парсер и лексический грамматик вверх, если не для удобства чтения, но и потому, что многие инструменты используемый для анализа файла .g4 (особенно для ANTLRWORKS 2), будет жаловаться на объявления о невязке.

Для примера он может быть изменен со следующей структурой:

grammar test; 

program : vr DOT to DOT e 
     ; 
e: be 
| be DOT top DOT be 
; 
be: FG 
    | FS 
    | MC 
    ; 
to: N 
    | A 
    | EV 
    ; 
vr: ER 
    | FP 
    ; 
top: B 
    | AF 
    ; 
Whitespace : [ \t\r\n]+ ->skip 
      ; 

DOT : '.' 
    ; 

A: 'A'|'a' 
; 

AF: 'AF'|'af' 
; 
N: 'N'|'n' 
; 
MC: 'MC'|'mc' 
; 
EV:'EV'|'ev' 
; 
FS: 'FS'|'fs' 
; 
FP: 'FP'|'fp' 
; 
FG: 'FG'|'fg' 
; 
ER: 'ER'|'er' 
; 
B: 'B'|'b' 
; 

Вы также можете найти все доступные методы для defaultErrorStrategy класса here и добавляя эти методы к вашей ручке реализации «новая» стратегия ошибки какие бы исключения вы ни требовали.

Надеюсь, это поможет и удачи в вашем проекте!

+0

Прежде всего спасибо за помощь. Но когда я добавляю ваши решения defaulterrorstratgy, все еще существует ошибка распознавания токенов при: 's'. Также методы reportInputMismatch и reportMissingToken не работают для моего случая. Есть ли какие-либо шаги, чтобы избавиться от этой ошибки и напечатать значимые сообщения об ошибках? – Yunus

+1

@yunsk Вы также можете добавить и исправить ошибку в lexer! Эта стратегия ошибок будет обрабатывать ошибки «непризнанных маркеров». Или вы можете добавить и «Ошибка маркера» в конце определения lexer так: ErrorCharacter:. ; Эффект заключается в том, что все не распознанные токены будут попадать в токен, отправить в синтаксический анализатор и вызвать стратегию ошибок в синтаксическом анализаторе. – FDeitelhoff

+0

@FDeitelhoff test case: fp.n.fs.fs результат ниже введите программу, LT (1) = fp потребляют [@ 0,0: 12 = 'fp', <4>, 1: 0] программа правил потребляют [@ 1,13: 13 = '.', <6>, 1: 13] правило потребляют [@ 2,14: 18 = 'n', <5>, 1: 14] правило потребляют [@ 3,19: 19 = '.', <6>, 1: 19] правило потреблять [@ 4,20: 27 = 'fs', <1>, 1: 20] программа управления программа выхода, LT (1) =. Есть ли проблема с моей грамматикой? Потому что кажется, что парсер принимает ввод, но это предложение недействительно для моего языка. – Yunus

 Смежные вопросы

  • Нет связанных вопросов^_^