0

ANTLR 文法には次のようなルールがあります。

COMMENT :  '/*' (options {greedy=false;} : . )* '*/' ;

このルールは単純に C スタイルのコメントに一致するため、/* と */ の間にある任意のテキストを含む任意のペアを受け入れ、正常に機能します。

ここでやりたいことは、ルールが一致したときに /* と */ の間のすべてのテキストをキャプチャして、アクションにアクセスできるようにすることです。このようなもの:

COMMENT :  '/*' e=((options {greedy=false;} : . )*) '*/' {System.out.println("got: " + $e.text);

このアプローチは機能しません。解析中に「/*」の後の最初の文字に到達すると、「実行可能な代替手段はありません」となります。

これを行うことができるかどうか、またはどのように行うことができるかについては、よくわかりません。提案やガイダンスを歓迎します。

4

2 に答える 2

4

簡単にできることに注意してください:

getText().substring(2, getText().length()-2)

最初と最後の 2 文字は常に and であるため、トークンCOMMENT は./**/

とのoptions {greedy=false;} :両方貪欲でないため、 を削除することもできます(ただし、 がなければ貪欲です) (i)。.*.+.

編集

またはsetText(...)、トークンで使用してand をすぐCommentに破棄します。ちょっとしたデモ:/**/

ファイルT.g:

grammar T;

@parser::members {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream(
                "/* abc */   \n" +
                "            \n" + 
                "/*          \n" +
                "   DEF      \n" + 
                "*/            "
        );
        TLexer lexer = new TLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        TParser parser = new TParser(tokens);
        parser.parse();
    }
}

parse
  :  ( Comment {System.out.printf("parsed :: >\%s<\%n", $Comment.getText());} )+ EOF
  ;

Comment
  :  '/*' .* '*/' {setText(getText().substring(2, getText().length()-2));}
  ;

Space
  :  (' ' | '\t' | '\r' | '\n') {skip();}
  ;

次に、パーサーとレクサーを生成し、すべての .java ファイルをコンパイルして、main メソッドを含むパーサーを実行します。

java -cp antlr-3.2.jar org.antlr.Tool Tg
javac -cp antlr-3.2.jar *.java
java -cp .:antlr-3.2.jar TParser
  (または Windows では「java -cp .;antlr-3.2.jar TParser」)

次の出力が生成されます。

parsed :: > abc <
parsed :: >          
   DEF      
<

(i) The Definitive ANTLR Reference、第 4 章、拡張 BNF サブルール、86 ページ。

于 2011-01-13T08:23:25.787 に答える
1

これを試して:

COMMENT :
  '/*' {StringBuilder comment = new StringBuilder();} ( options {greedy=false;} : c=. {comment.appendCodePoint(c);} )* '*/' {System.out.println(comment.toString());};

プログラムで使用できるように、実際に StringBuilder オブジェクトを返す別の方法:

COMMENT returns [StringBuilder comment]:
  '/*' {comment = new StringBuilder();} ( options {greedy=false;} : c=. {comment.append((char)c);} )* '*/';
于 2011-01-13T05:22:54.507 に答える