1

Python を使用して ANTLR で小さな文法を作成しました (番号のリストまたは ID のリストのいずれかを受け入れることができる文法) December 12 1965。次のコードで(そして、私が使用しているすべての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. 実際、あなたの文法にはもう 1 つの誤りと、改善できる小さな点が含まれています。

  • WHITESPACEおよびチャネルにCOMMENT配置されるHIDDENため、パーサールールでは使用できません (少なくとも、パーサーがトークンを読み取るチャネルを変更しない限り...)。
  • COMMENT入力の末尾に a がある、つまり末尾に aが\nない場合、適切にトークン化されません。次のように 1 行のコメントを定義することをお勧めします'//' ~('\r' | '\n')*。結局、末尾の改行はWHITESPACEルールによってキャプチャされます。

ルールにより、パーサーは an idList(またはintegerListそのことについては a) と一致できないため、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'

しかし、それは予想されます: の後idListに、パーサーは を期待しますEOFが、代わりに遭遇し'12'ます。

于 2012-04-11T17:41:53.690 に答える