Antlr Отсутствует токен - PullRequest
       15

Antlr Отсутствует токен

2 голосов
/ 21 ноября 2011

Я использую antlr для генерации моего анализатора, но я хочу переопределить некоторые сообщения об ошибках.В настоящий момент, если я даю неправильный синтаксис, например, отсутствующий токен, antlr выдает ошибку «строка 1:11 отсутствует TYPE в '."выводимый.Это не так, как я изначально думал, в методе reportError ().Кто-нибудь знает, где генерируется сообщение?

Спасибо!

1 Ответ

3 голосов
/ 21 ноября 2011

A MissingTokenException проходит через reportError(...).Допустим, вы хотите проанализировать назначения, используя следующую грамматику:

grammar T;

parse      : assignment EOF;
assignment : Id '=' Number ';';
Number     : '0'..'9'+ ('.' '0'..'9'+)?;
Id         : ('a'..'z' | 'A'..'Z')+;
Space      : ' ' {skip();};

Теперь просто переопределите метод reportError(...) следующим образом:

grammar T;

@parser::members {
  @Override
  public void reportError(RecognitionException e) {
    System.out.println("CUSTOM ERROR...\n" + e);
  }
}

parse      : assignment EOF;
assignment : Id '=' Number ';';
Number     : '0'..'9'+ ('.' '0'..'9'+)?;
Id         : ('a'..'z' | 'A'..'Z')+;
Space      : ' ' {skip();};

, а затем попытайтесь проанализировать, скажем,"= 123;" (отсутствует Id):

java -cp antlr-3.3.jar org.antlr.Tool T.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar Main "= 123;"

CUSTOM ERROR...
MissingTokenException(inserted [@-1,0:0='<missing Id>',<4>,1:0] at =)

Как видите, пользовательское сообщение об ошибке выводится на консоль.

EDIT

Ипредупреждение типа «нет приемлемой альтернативы ...» - проблема в лексере, а не в парсере.Это происходит, когда лексер встречает символ, который вы не учли в своей грамматике (или, по крайней мере, не как правильный токен).

Допустим, вы анализируете ввод a = 123: (обратите внимание на :в конце вместо ;).Теперь лексер выдаст предупреждение «нет жизнеспособной альтернативы ...», потому что я не определил токен для этого :.

. Простое решение для учета таких ошибок - добавить «catch-catch».правило "all" в конце вашей грамматики лексера, которое будет соответствовать любому символу, который не соответствует ни одному правилу лексера перед ним.Всякий раз, когда такое правило «ловить все» совпадает, вы просто выбрасываете исключение (или делаете что-то еще, конечно!) В блоке @after{...} этого правила.

Вот демонстрационная версия:

grammar T;

@parser::members {
  @Override
  public void reportError(RecognitionException e) {
    System.out.println("CUSTOM ERROR...\n" + e);
  }
}

parse      : assignment EOF;
assignment : Id '=' Number ';';
Number     : '0'..'9'+ ('.' '0'..'9'+)?;
Id         : ('a'..'z' | 'A'..'Z')+;
Space      : ' ' {skip();};

FallThrough
@after{
  throw new RuntimeException(String.format(
      "Encountered an illegal char on line \%d, column \%d: '\%s'", 
      getLine(), getCharPositionInLine(), getText()
    )
  );
}
  :  . // match any char not matched by Number, Id or Space
  ;

Если вы сейчас проанализируете a = 123:, вы увидите на консоли следующее:

Exception in thread "main" java.lang.RuntimeException: 
    Encountered an illegal char on line 1, column 8: ':'
    ...
...