我正在尝试在我的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组:工件值)。
感谢您的协助。
答案 0 :(得分:2)
Christopher Hunt写道:
- 注1:永远不能匹配以下替代方案:1
~('*/')
不正确:你只能在词法规则中否定单个字符(!)。在您的代码段中,您试图在解析器规则中否定某些内容。在解析器规则中,您不是否定字符,而是标记令牌。例如:
parse : ~A;
foo : .;
A : 'A';
B : 'B';
C : 'C';
parse
规则将不匹配除'A'
之外的任何字符,但匹配'B'
或'C'
。并且foo
不匹配任何字符,但匹配任何标记(或词法分析器规则)。
Christopher Hunt写道:
- 注2:决策可以匹配输入,例如“'_'..'。'”使用多个替代方案:1,2因此,替代方案2被禁用该输入
两个问题:
如果是后者,使用ANTLR可以更容易地做到这一点(如果是这种情况可以给出解释)。
修改强>
最简单的方法是在lexer上添加一个新的DocComment
规则,并将其放在(现有的)Comment
规则之上:
DocComment
: '/**' (options {greedy=false;} : .)* '*/'
;
Comment
: '/*' (options {greedy=false;} : .)* '*/' {$channel=HIDDEN;}
;
答案 1 :(得分: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')+
;