ANTLR v3 NoViableAltException未显示

ANTLR v3 NoViableAltException未显示,exception,antlr,Exception,Antlr,考虑以下我的语法摘录: definition : '(' 'define' ( '(' variable def_formals ')' body ')' | variable expression ')' ) ; def_formals : variable* ('.' variable)? ; body : ((d

考虑以下我的语法摘录:

definition
    :   '(' 'define' 
                   ( '(' variable def_formals ')' body ')'
                   | variable expression ')'
                   )    
    ;

def_formals
    :   variable* ('.' variable)?
    ;

body
    :   ((definition)=> definition)* expression+
    ;
变量是标识符,表达式是scheme的一些表达式(如文本或lambda表达式)。完整的语法可以在我的其他一些问题中找到

所以我测试了整个过程,提出了一个关于NoViableException的问题

到目前为止,一切正常运行的东西都正常运行。 比如说

(define x 5)
(define x 5))
(define x)
是公认的

现在我正在测试解析器不应该识别的内容

比如说

(define x 5)
(define x 5))
(define x)
在行尾报告额外的“)”

但是当我把东西漏掉的时候,比如说

(define x 5)
(define x 5))
(define x)

解析器一点也不抱怨。当我检查解释器时,NoviableException正确显示。但是我不知道如何在外部程序(比如java测试类)中显示这个错误

我试图让解析器在他看到的第一个语法错误上崩溃,就像Terrence Parr的书(第252页)中描述的那样,但这也没有帮助。 我也试过类似的东西

    private List<String> errors = new LinkedList<String>();
    public void displayRecognitionError(String[] tokenNames,
                                       RecognitionException e) {
        String hdr = getErrorHeader(e);
        String msg = getErrorMessage(e, tokenNames);
        errors.add(hdr + " " + msg);
    }
    public List<String> getErrors() {
        return errors;
    }

(我必须替换“有很多方法可以改进错误报告。快速修复方法是重写解析器类中的
emitterrormessage(String message)
,并简单地抛出一个包含所提供消息的异常:

语法T;
@成员{
@凌驾
public void emitErrorMessage(字符串消息){
抛出新的运行时异常(消息);
}
}
定义
:'('define'('variable def形式')'body')'
|变量表达式“')”
)    
;
定义形式
:变量*('.'变量)?
;
身体
:((定义)=>定义)*表达式+
;
表达
:INT
;
变量
:ID
;
ID:'a'..'z'+;
INT:'0'…'9';
空格:'{skip();};
您可以使用类对其进行测试:

import org.antlr.runtime.*;
公共班机{
公共静态void main(字符串[]args){
字符串[]测试={
“(定义x5)”,
“(定义x 5))”,
“(定义x)”,
(定义)
};
for(字符串输入:测试){
TLexer lexer=新的TLexer(新的AntlStringStream(输入));
TParser parser=newtparser(newcommontokenstream(lexer));
System.out.println(“\n参数:“+输入”);
试一试{
parser.definition();
}捕获(例外e){
System.out.println(“异常->”+e.getMessage());
}
}
}
}
运行上述类后,您将看到以下内容:

bart@hades:~/Programming/ANTLR/Demos/T$java-cp ANTLR-3.3.jar org.ANTLR.Tool T.g
bart@hades:~/Programming/ANTLR/Demos/T$javac-cp ANTLR-3.3.jar*.java
bart@hades:~/Programming/ANTLR/Demos/T$java-cp.:ANTLR-3.3.jar Main
解析:(定义x5)
解析:(定义x5))
解析:(定义x)
异常->第1:9行“')处缺少整数
解析:(定义)
异常->第1:7行输入“')处无可行的备选方案
如您所见,输入
(define x 5))
不会产生异常!这是因为lexer没有问题(它们都是有效的标记),解析器只需接受
定义
规则:

定义
:'('define'('variable def形式')'body')'
|变量表达式“')”
)    
;
如果您希望由于悬空的
”)“
”而出现错误,那么您需要在规则末尾添加
EOF
标记:

定义
:'('define'('variable def形式')'body')'
|变量表达式“')”
)
EOF
;

我用你的例子重现了这一点,但当我试图将其分配给我的语法时,同样没有发生任何事情。我发布了整个语法,正如上面所示。我试图追踪它,并在他输入规则和离开规则时添加了一些打印输出。我得到的结果是:他输入了规则,但他没有离开它。有什么可能吗在我的语法中,(define x)没有错,因为他认为这是一个宏(rule macro_use),甚至(define)符合规则。无论如何,谢谢!@Sebastian,我没有时间研究你的整个语法。但是你的问题解决了,我在你最后的评论中看到了?正确,但是你的回答很有帮助,因为现在我对antlr中的错误报告机制有了更好的理解。