2

Python 3 の AST ダンプ形式を解析して、より簡単に操作できる AST 形式に変換できる文法を構築する際に問題が発生しています。そのために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')), キーワード(引数='ランク', 値=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 つだけ考えられます。複数のキーワード ステートメントを検出するために使用したパターンは、他のタイプのステートメントでも機能するため、文法のあいまいさが原因で、何かが正しくトークン化されていません。しかし、そのあいまいさが実際に文法のどこにあるのか、私は完全に立ち往生しています。

また、一般的に文法を改善する方法に関する一般的な改善のヒントをいただければ幸いです。

4

1 に答える 1

1

ルールを追加する場合:

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

, keyword単純に 0 個以上のトークンに一致し、これらのトークンのタイプとテキストを出力すると、レクサーが例からの入力を処理できないことがわかります。

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

したがって、パーサー ルールの 1 つに問題はありませんが、字句レベルで問題が発生します。

パーサーからすべてのリテラル トークンを削除し、それらのレクサー ルールを作成することをお勧めします。parse次に、上で投稿したように、レクサーをテストして適切なトークンが作成されているかどうかを確認できる単一のルールを追加します。適切なトークンが作成されたら、パーサー ルールを記述します。

ここでの問題は、トークンを持っていないという事実と', keyword'、レクサーが「見る」と、もちろん失敗', k'するトークンを作成しようとするという事実であると確信しています。', kwargs'したがって、トークンにコンマとスペースを含めに、それらを独自のトークンにすることもお勧めします。

また、次のような書き換えルールは必要ありません。

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

何にも一致しない可能性があります。その場合、ANTLR は AST の作成中に例外をスローします。常に書き換えルールが何かを生成するようにします:

...

tokens {
  ...
  STMTLST;
  ...
}

...

stmtlist:       ((', '?) stmt)* -> ^(STMTLST stmt*)
        ;
于 2012-03-25T11:45:55.027 に答える