Java 运行时出现ANTLR v3.5解析器错误

Java 运行时出现ANTLR v3.5解析器错误,java,parsing,antlr3,Java,Parsing,Antlr3,所以我的语法有一些问题,我就是想不出来。我不确定到底是什么问题,也不知道问题在哪里,但我会尽力解释到底发生了什么 作为一点背景知识,为了让语法更有意义,这里的目标是获取一个用伪abc表示法编写的输入程序,并使用java库jMusic进行回放 另外,值得注意的是,我使用的是自定义AST代码,而不是ANTLR的内置AST生成器 当解析“header”中的“fields”时,问题似乎首先出现,但我也尝试从语法中完全删除header,以尝试缩小问题可能出现的范围,但在尝试解析“notes”时,我遇到了类

所以我的语法有一些问题,我就是想不出来。我不确定到底是什么问题,也不知道问题在哪里,但我会尽力解释到底发生了什么

作为一点背景知识,为了让语法更有意义,这里的目标是获取一个用伪abc表示法编写的输入程序,并使用java库jMusic进行回放

另外,值得注意的是,我使用的是自定义AST代码,而不是ANTLR的内置AST生成器

当解析“header”中的“fields”时,问题似乎首先出现,但我也尝试从语法中完全删除header,以尝试缩小问题可能出现的范围,但在尝试解析“notes”时,我遇到了类似的问题,因此我感觉这里有一个更普遍的问题

这是我的语法:

grammar simpleABC;

// grammar rules

options{
    backtrack = true;
}

@members{
    // override the default error reporting functions
    public void reportError(RecognitionException e) {
        // call the Parser member function to report the error
        displayRecognitionError(this.getTokenNames(), e);
        // exit with error
        System.exit(1);
    }
}

program returns [AST ast]
    :   { $ast = new Program(); }
        (header {$ast.addAST($header.ast);})
        (score {$ast.addAST($score.ast);})
    ;

header returns [Header ast]
    :   'header' '{'
            (field {$ast.addAST($field.ast);})+
        '}'
    ;

field returns [Field ast]
    :   'X:' x=NUM                      { $ast = (new ReferenceNumber($x.text)); }
    |   'T:' t=STRING                   { $ast = (new Title($t.text)); }
    |   'C:' c=STRING                   { $ast = (new Composer($c.text)); }
    |   'M:' (b=NUM '/' l=NUM)          { $ast = (new Meter($b.text, $l.text)); }
    |   'M:' 'C'                        { $ast = (new Meter("4", "4")); }
    |   'K:' k=PITCH                    { $ast = (new Key($k.text)); }
    |   'L:' l=NUM                      { $ast = (new Length($l.text)); }
    |   'L:' '/' l=NUM                  { $ast = (new Length("/" + $l.text)); }
    |   'tempo:' tempo=NUM              { $ast = (new Tempo($tempo.text)); }
    ;

score returns [Score ast]
    :   'score' '{'
            (part {$ast.addAST($part.ast);})+
        '}'
    ;

part returns [Part ast]
    :   instrument=STRING id=VAR '{' {$ast = new Part($instrument.text, $id.text);}
            (phrase {$ast.addAST($phrase.ast);})+
        '}'
    ;

phrase returns [Phrase ast]
    :   '|'  (b1=bar {$ast.addAST($b1.ast);} '|')+                                                  // typical bar
/*  |   '|:' (b2=bar {$ast.addAST($b2.ast);} '|')+ (b3=bar {$ast.addAST($b3.ast);} ':|')            // single repeat
    |   '|:' (b4=bar {$ast.addAST($b4.ast);} '|')+                                                  // multi-ending repeat
            '1' (b5=bar {$ast.addAST($b5.ast);} )+ ':|'                                                 // 1st ending
            '2' (b6=bar {$ast.addAST($b6.ast);} )+                                                      // 2nd ending

    TODO: fix repeats
*/
    ;

bar returns [Bar ast]
    :   (note {$ast.addAST($note.ast);})+
    ;

note returns [Note ast]
    :   pitch=PITCH length=NUM  { $ast = new Note($pitch.text, $length.text); }
    |   pitch=PITCH             { $ast = new Note($pitch.text); }
    ;

// lexical analysis stuff   

NUM     :   ('0'..'9')+
        ;
VAR     :   ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
        ;
PITCH   :   (('A'..'G') | ('a'..'g'))   (',' | '\'')?
        ;
COMMENT :   '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
        ;
WS      :   ( ' ' | '\t' | '\r' | '\n' ) {$channel=HIDDEN;}
        ;
STRING  :   '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
        ;

fragment
ESC_SEQ :       '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
        ;
下面是我一直在使用的一个简单输入程序:

header {
    X:1
    T:"Notes"
    M:C
    K:C
    L:1/4
}
score {
    PIANO pianoPart {
        |C, D, E, F,|G, A, B, C|D E F G|A B c d| e f g a|b c' d' e'|f' g' a' b'|
    }
}
运行此代码时,出现以下错误:

Exception in thread "main" java.lang.NullPointerException
    at simpleABCParser.header(simpleABCParser.java:151)
    at simpleABCParser.program(simpleABCParser.java:87)
    at simpleABCParser.main(simpleABC.java:32)
好的,它告诉我解析器中有一个空指针异常。下面看一下这个空指针发生的位置

// $ANTLR start "header"
// simpleABC.g:25:1: header returns [Header ast] : 'header' '{' ( field )+ '}' ;

public final Header header() throws RecognitionException {
        Header ast = null;


        Field field3 =null;

        try {
            // simpleABC.g:26:2: ( 'header' '{' ( field )+ '}' )
            // simpleABC.g:26:4: 'header' '{' ( field )+ '}'
            {
            match(input,19,FOLLOW_19_in_header67); if (state.failed) return ast;
            match(input,22,FOLLOW_22_in_header69); if (state.failed) return ast;
            // simpleABC.g:27:4: ( field )+
            int cnt1=0;
            loop1:
            while (true) {
                int alt1=2;
                int LA1_0 = input.LA(1);
                if ( ((LA1_0 >= 13 && LA1_0 <= 18)||LA1_0==21) ) {
                    alt1=1;
                }

                switch (alt1) {
                case 1 :
                    // simpleABC.g:27:5: field
                    {
                    pushFollow(FOLLOW_field_in_header75);
                    field3=field();
                    state._fsp--;
                    if (state.failed) return ast;
                    if ( state.backtracking==0 ) {ast.addAST(field3);}
                    }
                    break;

                default :
                    if ( cnt1 >= 1 ) break loop1;
                    if (state.backtracking>0) {state.failed=true; return ast;}
                    EarlyExitException eee = new EarlyExitException(1, input);
                    throw eee;
                }
                cnt1++;
            }

            match(input,24,FOLLOW_24_in_header83); if (state.failed) return ast;
            }

        }
        catch (RecognitionException re) {
            reportError(re);
            recover(input,re);
        }
        finally {
            // do for sure before leaving
        }
        return ast;
    }

// $ANTLR end "header"
在我看来,第二个switch case语句中的
match()
函数返回null,我认为这意味着它没有将输入标记与预期标记进行匹配。下一个代码段位于上面的
字段()
函数中,但为了防止您不想筛选所有这些内容,下面是我要讨论的代码段:

switch (alt2) {
                case 1 :
                    // simpleABC.g:32:4: 'X:' x= NUM
                    {
                    match(input,18,FOLLOW_18_in_field99); if (state.failed) return ast;
                    x=(Token)match(input,NUM,FOLLOW_NUM_in_field103); if (state.failed) return ast;
                    if ( state.backtracking==0 ) { ast = (new ReferenceNumber((x!=null?x.getText():null))); }
                    }
                    break;
所以我想我已经尽可能地追溯到了这一点,而没有深入到ANTLR。对我来说,证据表明语法有问题。我已经检查了很多次,并试图隔离这个问题,但我没有任何运气


这一定是一些我刚刚错过的非常愚蠢的东西,或者是一些我目前对ANTLR无法理解的东西,所以欢迎提供任何建议、猜测或解决方案。如果您希望我提供任何其他信息,请告诉我,并感谢您通过此帖子发布的任何人。哈哈。

因此,我成功地解决了我遇到的问题,不再得到我指出的错误。问题是,我向AST对象添加了一些东西,这些东西是我在解析器规则中返回的,而没有首先初始化它们。例如,“header”应该以以下行开头:{$ast=newheader();},然后再尝试向header添加任何“fields”。这个问题解决了,但现在我有了一个新的问题,关于“音高”词法规则。它告诉我与字符“C”不匹配,这需要一个音高。有什么想法吗?
switch (alt2) {
                case 1 :
                    // simpleABC.g:32:4: 'X:' x= NUM
                    {
                    match(input,18,FOLLOW_18_in_field99); if (state.failed) return ast;
                    x=(Token)match(input,NUM,FOLLOW_NUM_in_field103); if (state.failed) return ast;
                    if ( state.backtracking==0 ) { ast = (new ReferenceNumber((x!=null?x.getText():null))); }
                    }
                    break;