2

我试图在我的 JavaScript 文件中解析一个特定的(本地开发的)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 组:工件值)。

感谢你的协助。

4

2 回答 2

2

克里斯托弗亨特写道:

  • 注 1:永远不能匹配以下备选方案: 1

~('*/')不正确:您只能否定词法分析器规则中的单个字符 (!)。在您的代码段中,您试图否定解析器规则中的某些内容。在解析器规则中,您不是否定字符,而是令牌。例如:

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

parse规则将匹配除 之外的任何字符'A',但匹配'B''C'。并且foo不匹配任何字符,但匹配任何标记(或词法分析器规则)

克里斯托弗亨特写道:

  • 注意 2:决策可以使用多个替代项匹配诸如“'_'..'.'”之类的输入:1、2 因此,该输入的替代项 2 被禁用

两个问题:

  1. 你把整个语法贴出来了吗?
  2. 您是在尝试解析整个 JS 文件,还是只是“过滤”JS 文件并提取 JavaDoc 注释?

如果是后者,那么使用 ANTLR 有一种更简单的方法(如果是这种情况,可以给出解释)。

编辑

DocComment最简单的方法是在词法分析器中添加一个新规则并将其放在(现有)Comment规则之上:

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

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

我对这个问题的解决方案是在没有解析器的情况下使用 ANTLR 的 Lexer 并过滤掉我不感兴趣的东西。这是我想出的(它还查找全局定义的变量和导入):

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 回答