在antlr3中从语法向java抛出错误

时间:2017-02-28 04:12:29

标签: java antlr3 throw

如何将语法文件中的自定义错误消息抛出到java类(定义了解析和lexing)?

< ---------- Parser Grammar ----------->

parser grammar EParser;

@members {

public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
        String hdr = getErrorHeader(e);
        String msg = getErrorMessage(e, tokenNames);
        System.out.println("hdr and msg...."+hdr+">>>>>>"+msg);
        throw new RuntimeException(hdr + ":" + msg);
    }
}

prog
    : stat+ 
    ;

stat
    : expr SEMI
      | ID EQU expr SEMI
    ;

expr
    : multExpr ((PRM) multExpr)*
    ;

multExpr
    : atom (MUL atom)*
    ;   

atom
    :INT| OPEN expr CLS
    ;

< ------------------- Java代码--------------->

import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;

public class TestE {
public static void main(String[] args) throws Exception {
ELexer lexer = new ELexer(new ANTLRStringStream("a=9+8;"));
EParser parser = new EParser(new CommonTokenStream(lexer));
try
{
parser.prog();
System.out.println("Parsing successfully...");
}
catch (Exception e) 
{
    System.out.println("Other exception : " + e.toString());
}    
}
}

< ------------------ Lexer语法-------------->

lexer grammar ELexer;
tokens
{
    ID;
    INT;
    WS;
    EQU;
    PRM;
    OPEN;
    CLS;
    SEMI;
    MUL;
}
@members {
Stack<String> paraphrase = new Stack<String>();
}
ID :('a'..'z'|'A'..'Z')+ ;
INT : '0'..'9'+ ;
EQU:'=';
PRM:'+'|'-';
OPEN:'(';
SEMI:';';
CLS :')';
MUL:'*';
WS : (' '|'\t'|'\n'|'\r')+ {skip();} ;

此处我的输入为a=9+8

当我想念8时,它必须将错误消息指定为“期望整数”,当我想念;时,它必须说“缺少分号”。

像这样我必须生成错误消息(我不想要由antlr生成的默认错误消息,我需要自己的错误消息)。

我怎样才能做到这一点?我是否必须在语法文件中写入错误消息?还是java代码?

2 个答案:

答案 0 :(得分:1)

您不需要在语法中输入自定义错误。而是安装自定义错误处理程序并在那里处理异常。我写了fairly complete error handling(但是,对于ANTLR3 C目标)。它可能会为您提供一些提示,您可以使用它来构建自己的错误消息。

答案 1 :(得分:0)

对于Java目标,您可能希望覆盖以下一种或多种方法:

  • org.antlr.runtime.BaseRecognizer.getErrorHeader()
    • 创建错误标题(输入中发生错误的位置)
  • org.antlr.runtime.BaseRecognizer.getErrorMessage()
    • 创建错误消息本身(发生了什么)
  • org.antlr.runtime.BaseRecognizer.emitErrorMessage()
    • 显示错误(默认情况下在错误输出/控制台上)
  • org.antlr.runtime.BaseRecognizer.displayRecognitionError()

    • 将它们粘合在一起:

      public void displayRecognitionError(String[] tokenNames,
                                          RecognitionException e)
      {
          String hdr = getErrorHeader(e);
          String msg = getErrorMessage(e, tokenNames);
          emitErrorMessage(hdr+" "+msg);
      }
      

您可以像使用@members一样在语法的displayRecognitionError()部分覆盖它们,或者如果它的代码更长,则可以更方便地继承{{1}并将org.antlr.runtime.Parser放入语法的superClass = MyParser;部分(请注意,对于词法错误也是这样做的,您必须创建{{1}的子类也适合使用词法分析器。)