1

我使用python在ANTLR中创建了一个小语法(一种可以接受ID列表的数字列表的语法),但是当我输入一个字符串时December 12 1965,ANTLR将在文件上运行并显示没有错误使用以下代码(并且我使用的所有 python 代码都通过 @main 嵌入):

grammar ParserLang;

options {
    language=Python;
}

@header {
import sys
import antlr3

from ParserLangLexer import ParserLangLexer
}

@main { 
def main(argv, otherArg=None):
    char_stream = antlr3.ANTLRInputStream(open(sys.argv[1],'r'))
    lexer = ParserLangLexer(char_stream)

    tokens = CommonTokenStream(lexer)
    parser = ParserLangParser(tokens);

    rule   = parser.entry_rule()
}

program     : idList EOF
            | integerList EOF
            ;

idList      : ID whitespace idList 
            | ID
            ;

integerList : INTEGER whitespace integerList 
            | INTEGER
            ;

whitespace  : (WHITESPACE | COMMENT) +;

ID            : LETTER (DIGIT | LETTER)*;
INTEGER       : (NONZERO_DIGIT DIGIT*) | ZERO ;
WHITESPACE    : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+    { $channel = HIDDEN; } ;
COMMENT       : ('/*' .* '*/') | ('//' .* '\n') { $channel = HIDDEN; } ;

fragment ZERO            : '0' ;
fragment DIGIT         : '0' .. '9';
fragment NONZERO_DIGIT : '1' .. '9';
fragment LETTER        : 'a' .. 'z' | 'A' .. 'Z';

难道我做错了什么?

编辑:当我使用具有相同语法的 ANTLRWorks 输入时,会引发 NoViableAltException。如何通过代码获取该错误?

4

1 回答 1

2

我无法重现它。rule = parser.entry_rule()当我在修复语法(应该是:)中的错误后从您的输入生成词法分析器和解析器rule = parser.program()并解析输入"December 12 1965"(作为文件的输入或纯字符串)时,我收到以下错误:

line 1:0 no viable alternative at input u'December'

这可能看起来很奇怪,因为这可能是idList. 事实是,您的语法还包含一个错误和一件可以改进的小事:

  • WHITESPACE并且COMMENT被放置在HIDDEN通道上,因此在解析器规则中不可用(至少,在不改变解析器读取其令牌的通道的情况下......);
  • aCOMMENT在输入的末尾,即没有 a\n在末尾,将不会被正确标记。最好像这样定义单行注释:'//' ~('\r' | '\n')*. WHITESPACE毕竟,尾随换行符将被规则捕获。

由于该规则,解析器无法匹配 a idList(或 a integerList),因此whitespace会产生指向第一个标记 ( 'December') 的错误。

这是一个有效的语法(如预期的那样):

grammar ParserLang;

options {
    language=Python;
}

@header {
import sys
import antlr3

from ParserLangLexer import ParserLangLexer
}

@main { 
def main(argv, otherArg=None):
    lexer = ParserLangLexer(antlr3.ANTLRStringStream('December 12 1965'))
    parser = ParserLangParser(CommonTokenStream(lexer))
    parser.program()
}

program     : idList EOF
            | integerList EOF
            ;

idList      : ID+
            ;

integerList : INTEGER+
            ;

ID          : LETTER (DIGIT | LETTER)*;
INTEGER     : (NONZERO_DIGIT DIGIT*) | ZERO ;
WHITESPACE  : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ { $channel = HIDDEN; } ;
COMMENT     : ('/*' .* '*/' | '//' ~('\r' | '\n')*)   { $channel = HIDDEN; } ;

fragment ZERO          : '0' ;
fragment DIGIT         : '0' .. '9';
fragment NONZERO_DIGIT : '1' .. '9';
fragment LETTER        : 'a' .. 'z' | 'A' .. 'Z';

运行上述语法生成的解析器也会产生错误:

line 1:9 missing EOF at u'12'

但这是意料之中的:在 a 之后idList,解析器期望的是EOF,但它却遇到'12'了。

于 2012-04-11T17:41:53.690 回答