2

JavaScript ファイル内の 1 つの特定の (自家製の) JavaDoc タグを解析しようとしていますが、これを実現する方法を理解するのに苦労しています。Antlr は、以下に記載されているように不平を言っています。

jsDocComment 
    : '/**' (importJsDocCommand | ~('*/'))* '*/' <== See note 1
    ;

importJsDocCommand
    : '@import' gav
    ;

gav
    :  gavGroup ':' gavArtifact
    -> ^(IMPORT gavGroup gavArtifact)
    ;

gavGroup 
    : gavIdentifier
    ;

gavArtifact
    : gavIdentifier
    ;

gavIdentifier 
    : ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'-'|'.')* <== See note 2
    ;
  • 注 1: 次の選択肢は決して一致しません: 1

  • 注 2: 決定は、複数の選択肢 1、2 を使用して「'_'..'.'」などの入力と一致する可能性があります。その結果、その入力に対して選択肢 2 が無効になりました。

ここに私が解析しようとしているものがあります:

/** a */
/** @something */
/** @import com.jquery:jquery */

「IMPORT」という名前の AST ツリー要素の下に作成された @import ステートメント (その Maven group:artifact 値とともに) だけで、すべての行が正常に解析されるはずです。

ご協力ありがとうございます。

4

2 に答える 2

2

クリストファー・ハントは次のように書いています。

  • 注 1: 次の選択肢は決して一致しません: 1

~('*/')は正しくありません: lexer ルール (!) では単一の文字のみを否定できます。スニペットでは、パーサー ルールで何かを否定しようとしています。パーサー ルールでは、文字を否定するのではなく、トークンを否定します。例えば:

parse : ~A;
foo   : .;
A     : 'A';
B     : 'B';
C     : 'C';

parseルールは以外の文字には一致しませが、または'A'のいずれ'B'かに一致します'C'。Andはどの文字にも一致fooしませんが、任意のトークン (またはレクサー規則) に一致します。

クリストファー・ハントは次のように書いています。

  • 注 2: 決定は、複数の選択肢 1、2 を使用して「'_'..'.'」などの入力に一致する可能性があります。その結果、その入力に対して選択肢 2 が無効になりました。

2 つの質問:

  1. 文法全体を投稿しましたか?
  2. JS ファイル全体を解析しようとしていますか、それとも JS ファイルを「フィルタリング」して JavaDoc コメントを引き出しているだけですか?

後者の場合は、ANTLR を使用してこれを行うためのはるかに簡単な方法があります (その場合は説明を与えることができます)。

編集

DocCommentlexer に新しいルールを追加し、(既存の)Commentルールのすぐ上に配置するのが最も簡単です。

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

Comment
  :  '/*' (options {greedy=false;} : .)* '*/' {$channel=HIDDEN;}
  ;
于 2010-10-01T06:35:44.253 に答える
0

この問題に対する私の解決策は、パーサーなしでANTLRのレクサーを使用し、興味のないものをフィルターで除外することでした。これが私が思いついたものです(グローバルに定義された変数とインポートも検索します)。

lexer grammar ECMAScriptLexer;

options {filter=true;}

@lexer::header {
    package com.classactionpl.mojo.javascript;
}

@members {
    int scopeLevel = 0;
}

IMPORTDOC
    :   '/**' .* IMPORT .* (IMPORT)* '*/'
    ;

fragment 
IMPORT
    :   '@import' WS groupId=GAVID ':' artifactId=GAVID
        {System.out.println("found import: " + $groupId.text + ":" + $artifactId.text);}
    ;

fragment
GAVID  
    :   ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'-'|'0'..'9'|'.')*
    ;

COMMENT
    :   '/*' .* '*/'
    ;

SL_COMMENT
    :   '//' .* '\n' 
    ;

ENTER_SCOPE
    :   '{' {++scopeLevel;}
    ;

EXIT_SCOPE
    :   '}' {--scopeLevel;}
    ;

WINDOW_VAR
    :   'window.' name=ID WS? value=(';' | '=') ~('=')
        {
            System.out.println("found window var " + $name.text + " = " + ($value == ';'));
        }
    ;

GLOBAL_VAR
    :   'var' WS name=ID WS? value=(';' | '=') ~('=')
        {
            if (scopeLevel == 0) {
                System.out.println("found global var " + $name.text + " = " + ($value == ';'));
            }
        }
    ;

fragment
ID  :   ('a'..'z'|'A'..'Z'|'$'|'_') ('a'..'z'|'A'..'Z'|'$'|'_'|'0'..'9')*
    ;

fragment
WS  :   (' '|'\t'|'\n')+
    ;
于 2010-10-06T00:29:00.637 に答える