我在ANTLR中使用python创建了一个小语法(一种语法可以接受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。如何通过代码获取该错误?
答案 0 :(得分: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
频道,因此在解析器规则中不可用(至少,不会更改解析器读取其令牌的频道)。 ..); COMMENT
,即最后没有\n
,将无法正确标记。最好像这样定义单行注释:'//' ~('\r' | '\n')*
。毕竟,WHITESPACE
规则将捕获尾随换行符。由于idList
规则导致解析器无法与integerList
(或whitespace
匹配),因此会产生指向第一个令牌的错误({{1 }})。
这是一个有效的语法(正如预期的那样):
'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'
之后,解析器需要idList
,但它会遇到EOF
。