1

私は Antlr 3.2 を使用していますが、コメント行を無視する文法を書くのに苦労しています。具体的には、コメント行が入力の最後の行であり、その後に改行がない場合、エラーが発生します。

私の入力は実質的にアセンブリ言語であり、コメントは行のどこからでもセミコロンで始まり、行末まで続きます。それ以外はすべてコマンドとして解析されます。

問題を示す私の文法の短縮バージョンは次のとおりです。

grammar Test;

options {
    language = Java;
    output = AST;
    ASTLabelType = CommonTree;
}

@header {
    package test;
}

@lexer::header {
    package test;
}

rule
    :   instruction+ EOF!
    ;

instruction
    :   'SET' NEWLINE!*
    ;

COMMENT
    :   ';' .* NEWLINE+ { $channel=HIDDEN; }
    ;

NEWLINE
    :  '\r'? '\n'
    ;

WS
    :   (' ' | '\r' | '\n' | '\t' | '\f')+ { $channel = HIDDEN; }
    ;

次のような入力を使用する場合:

; comment line 1 with blank line after it

SET ; comment after command
; comment line again

このことわざを解析するとエラーが発生しますline 4:11 required (...)+ loop did not match anything at character '<EOF>'

入力の最後の行に改行を追加すると、コメントの削除によって改行が一致し、EOF がルールの最後に一致するため、正常に機能します。

最終行のコメントを無視してエラーにならないようにするにはどうすればよいでしょうか? 元の入力にハッキングするために何も追加したくないのですが、コメント行を読むためのよりクリーンな方法はありますか? NEWLINE|EOF のあらゆる種類の組み合わせを試しましたが、エラーが解消されません。

4

1 に答える 1

2

このような何かがそれを行う必要があります:

COMMENT
    :   ';' ~('\r' | '\n')* { $channel=HIDDEN; }
    ;

COMMENT最後に改行を入れる可能性がある場合は、次のようにします。

COMMENT
    :   ';' ~('\r' | '\n')* NEWLINE? { $channel=HIDDEN; }
    ;

ただし、2 つのルールNEWLINEWS:

NEWLINE
    :  '\r'? '\n'
    ;

WS
    :   (' ' | '\r' | '\n' | '\t' | '\f')+ { $channel = HIDDEN; }
    ;

は危険です: ANTLR は次のように機能します: 可能な限り一致しようとするため、最も多くの "勝利" に一致するルールが適用されます。2 つ (またはそれ以上) のルールが同じ量の文字に一致する場合、最初に定義されたルールが「勝ち」ます。

言い換えると、レクサーが のような入力を見た場合"\n"、 aNEWLINEが作成されます。しかし、レクサーが" \n"(スペースの後に が続く"\n") を認識した場合、WSトークンが作成されます (そしてHIDDENチャネルに配置されます)。

あなたの言語で改行が本当に重要かどうかわかりません(アセンブリ言語のフレーバーではありません、AFAIK)ので、単純にNEWLINEルールを削除してください。重要な場合は文字\rとルール\nの両方を削除します。WS

于 2012-05-08T17:26:10.030 に答える