2

文法:

grammar test;

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

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

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

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

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
    ;

start 
    :   STRING EOF;

ウィザードで生成された文法です。ルール「開始」を追加しました。

インタープリターでの入力:

"abc"

コンソールの結果:

[19:09:54] Interpreting...
[19:09:54] problem matching token at 1:2 MismatchedTokenException(97!=34)
[19:09:54] problem matching token at 1:3 NoViableAltException('b'@[1:1: Tokens : ( WS | STRING );])
[19:09:54] problem matching token at 1:4 NoViableAltException('c'@[1:1: Tokens : ( WS | STRING );])
[19:09:54] problem matching token at 1:5 NoViableAltException(''@[()* loopback of 11:12: ( ESC_SEQ | ~ ( '\\' | '"' ) )*])

スクリーンショット: http://habreffect.ru/files/200/4cac2487f/antlr.png

ANTLRWorks v1.4 ANTLR v3.2 のコンソールからも試してみましたが、同じ結果でした。

「abc」の代わりに「\nabc」と入力すると、問題なく動作します。STRING ルールで ESC_SEQ を右に配置すると、「abc」は機能しますが、「\nabc」は失敗します。

4

1 に答える 1

2

これは ANTLRWorks 1.4 のバグのようです。ATLRWorks 1.3 (またはそれ以前) で試すことができます。おそらく、そのバージョンは適切に動作します (v1.4 のみで簡単に確認しました!)。

コンソールから、例の文字列 ("abc""\nabc") の両方が問題なく解析されています。これが私のテストリグと対応する出力です:

grammar test;

start 
  :  STRING {System.out.println("parsed :: "+$STRING.text);} EOF
  ;

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

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

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

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

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
  ;

文法はあなたのものと同じですが、フォーマットが少し異なるだけであることに注意してください。

そして「メイン」クラス:

import org.antlr.runtime.*;

public class Demo {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream(args[0]);
        testLexer lexer = new testLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        testParser parser = new testParser(tokens);
        parser.start();
    }
}

コンソールから、パーサーとレクサーを作成します。

java -cp antlr-3.2.jar org.antlr.Tool test.g

すべての .java ソース ファイルをコンパイルします。

javac -cp antlr-3.2.jar *.java

「メイン」クラスを実行します。

java -cp .:antlr-3.2.jar Demo \"\\nabc\"
// output:                                   parsed :: "\nabc"

java -cp .:antlr-3.2.jar Demo \"abc\"
// output:                                   parsed :: "abc"

(Windows の場合、上記のコマンドの:を aに置き換えます);

上記のコマンド ライン パラメーターは、Bash で実行される例であり、"\をエスケープする必要があることに注意してください。これは、システムによって異なる場合があります。しかし、出力からわかるように、両方とも"\nabc"適切"abc"に解析されます。

ANTLRWorks は文法ファイルを編集するための優れたツールですが、(私の経験では) このようなおかしなバグがかなりあります。そのため、お見せしたように、文法を編集し、コンソールでファイルを生成、コンパイル、テストするだけです。

HTH

于 2010-06-14T18:03:01.643 に答える