2012-03-25 24 views
2

Python 3のASTダンプ形式を解析し、それを簡単に処理できるAST形式に変換できる文法を構築する際に問題が発生します。私はそうするためにANTLR文法を書くことにしましたが、何らかの理由でキーワードブロックのみを処理している問題があります(キーワードブロックのみ)。示されるように、私は、キーワード文法を単離した:可能なANTLR文法の曖昧さの解消(および一般的な改善のヒント)

grammar kwds; 
options {output=AST;} 

keywords: 'keywords=['((', '?)keyword)*']' -> keyword* 
    ; 

keyword : 'keyword(arg='STRING', value='str')' 
    ; 
str : 'Str(s='STRING')' -> STRING 
    ; 

STRING 
    : '\'' (ESC_SEQ | ~('\\'|'\''))* '\'' 
    ; 

fragment 
ESC_SEQ 
    : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\') 
    | UNICODE_ESC 
    | OCTAL_ESC 
    ; 

EMPTYBRACKETS 
    : '[]'; 

fragment 
OCTAL_ESC 
    : '\\' ('0'..'3') ('0'..'7') ('0'..'7') 
    | '\\' ('0'..'7') ('0'..'7') 
    | '\\' ('0'..'7') 
    ; 

fragment 
UNICODE_ESC 
    : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT 
    ; 

fragment 
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ; 

。これは、キーワードルールに示すフォーマットで、キーワード(カンマ区切り0以上)のリストを受け入れるように設計されています。

あなたは上記の文法に、次の(有効な)入力を与えると、

キーワード= [キーワード(引数= '名前'、値=のStr(S = 'UGA'))、キーワード(引数= 'rank'、value = Str(s = '2'))]

文法はこれを正しく認識します。

しかし、私が書いた "完全な" Python 3 AST形式の文法(スペース節約の目的でhttp://pastebin.com/ETrSVXvfにあり、上記の2つのルールはそれぞれ106行目と109行目にあります)を使用します。まったく同じ文法規則、トークンストリームは、キーワードルールに対して解析する際に、次の出力を生成し、上記のサンプルからの最初のキーワードマッチを解析後にオフにいくつかの文字のようだ:

sample3.txt line 1:52 mismatched character 'e' expecting 'w' 
sample3.txt line 1:53 no viable alternative at character 'y' 
sample3.txt line 1:54 no viable alternative at character 'w' 
sample3.txt line 1:55 no viable alternative at character 'o' 
sample3.txt line 1:56 no viable alternative at character 'r' 
sample3.txt line 1:57 no viable alternative at character 'd' 
sample3.txt line 1:58 no viable alternative at character '(' 
sample3.txt line 1:59 missing ENDBR at 'arg=' 

私は考えることができます1つの可能性があります:文法のあいまいさのために何かが正しくトークン化されていません。なぜなら、私が複数のキーワード文を検出するために使用したパターンは、他のtステートメントのype。しかし、私は完全にそのあいまいさが実際に文法のどこにあるかについて固執しています。

また、どのように一般的な文法を向上させることができるかについての一般的な改善のヒントをいただければ幸いです。

答えて

1

ルールを追加した場合:

parse 
: (t=. {System.out.printf("type=\%-20s text='\%s'\n", tokenNames[$t.type], $t.text);})* EOF 
; 

単にゼロ以上のトークンと一致し、これらのトークンの種類やテキストを出力し、あなたはレクサーはあなたの例からの入力, keywordには対応できないことがわかります:

keywords=[keyword(arg='name', value=Str(s='UGA')), keyword(arg='rank', value=Str(s='2'))] 
               ^^^^^^^^^ 

は、だからあなたのパーサールールの一つには問題はありませんが、物事は字句レベルで間違って行きます。

あなたのパーサからすべてのリテラルトークンを削除し、それらのためのレクサールールを作成することをお勧めします。次に、上記のように1つのparseルールを追加して、レクサーをテストして適切なトークンが作成されているかどうかを調べることができます。適切なトークンが作成されたら、パーサルールを記述します。レクサーは', k'を「見る」一度

が、私はここでの問題は、あなたが', keyword'トークンとそれを持っていないという事実であるかなり確信している、それは当然のことながら、失敗し', kwargs'トークンを作成しようとします。だからでないことをお勧めします。にはカンマとスペースがトークンに含まれていますが、トークンにすることをお勧めします。潜在的には何も一致しないことができ

stmtlist:  ((', '?) stmt)* -> stmt* 
     ; 

また、あなたはこのような書き換えルールを持っている必要はありません。その場合、ANTLはASTの作成中に例外をスローします。常に書き換えルールを作成する何か

... 

tokens { 
    ... 
    STMTLST; 
    ... 
} 

... 

stmtlist:  ((', '?) stmt)* -> ^(STMTLST stmt*) 
     ; 
+0

Aha、わかります。それは、レクサーが '、k'を混乱させることになります。これは、他の人がどのように消費されたかを説明するものでもありません。また、書き換えルールに関するヒントをありがとう! – wibarr

+0

@ Webs961、よろしくお願いします。 –

関連する問題