2012-04-11 64 views
1

我使用python(一種可以接受ID列表中的數字列表的語法)在ANTLR中創建了一個小文法,但是當我輸入字符串(如December 12 1965)時,ANTLR將在該文件上運行並顯示爲什麼我的antlr語法似乎正確地解析了這個輸入?

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'; 

上午我做錯了什麼:我用下面的代碼(和所有我使用通過@main被嵌入的Python代碼的)沒有錯誤?

編輯:當我使用相同語法的輸入ANTLRWorks,引發NoViableAltException。如何通過代碼獲取該錯誤?

回答

2

我無法複製它。在修復語法錯誤(rule = parser.entry_rule()應該是:rule = parser.program())並解析輸入"December 12 1965"(作爲文件的輸入或純文本字符串)後,當我從輸入生成詞法分析器和分析器時,出現以下錯誤:

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

這似乎很奇怪,因爲這可能是idList的開始。事實是,你的語法包含一個以上的錯誤和可以改進的一個小東西:

  • WHITESPACECOMMENT放置在HIDDEN通道,並在語法規則,以不使用(至少,如果不改變解析器從中讀取其令牌的通道...);
  • a COMMENT在輸入結束時,即末尾沒有\n,將不會正確標記。更好地定義這樣的單行註釋:'//' ~('\r' | '\n')*。畢竟,尾部換行符將被WHITESPACE規則捕獲。

因爲分析器無法匹配,因爲whitespace規則的idList(或就此而言一個integerList),一個錯誤產生在非常第一令牌('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,但它會遇到'12'

相關問題