Antlr 在不使用令牌的情况下使用孤岛语法返回默认模式
我仍在尝试使用ANTLR解析一个简单的Javadoc样式的格式。基本上,格式如下所示:Antlr 在不使用令牌的情况下使用孤岛语法返回默认模式,antlr,Antlr,我仍在尝试使用ANTLR解析一个简单的Javadoc样式的格式。基本上,格式如下所示: /** * Description * * @name someId */ 我的语法分析器如下: query_doc : BEGIN_QDOC description name NOMANSLAND* END_QDOC; description : (DESCRIPTION_TEXT | NOMANSLAND)*; name : OPEN_N
/**
* Description
*
* @name someId
*/
我的语法分析器如下:
query_doc : BEGIN_QDOC description name NOMANSLAND* END_QDOC;
description : (DESCRIPTION_TEXT | NOMANSLAND)*;
name : OPEN_NAME INNER_WS NAMEID INNER_WS* CLOSE_NAME;
BEGIN_QDOC : '/**';
END_QDOC : ('*/');
NOMANSLAND : '\r'? '\n' (' ' | '\t')* '*' (' ' | '\t')*;
DESCRIPTION_TEXT : ~('\n');
OPEN_NAME : '@name' -> mode(NAME);
mode NAME;
INNER_WS : (' ' | '\t')+;
NAMEID : ('a'..'z' | 'A'..'Z' | '0'..'9' | '-' | '_' | '?')+;
CLOSE_NAME : (('\r'? '\n') | '*/') -> mode(DEFAULT_MODE);
我的lexer语法如下:
query_doc : BEGIN_QDOC description name NOMANSLAND* END_QDOC;
description : (DESCRIPTION_TEXT | NOMANSLAND)*;
name : OPEN_NAME INNER_WS NAMEID INNER_WS* CLOSE_NAME;
BEGIN_QDOC : '/**';
END_QDOC : ('*/');
NOMANSLAND : '\r'? '\n' (' ' | '\t')* '*' (' ' | '\t')*;
DESCRIPTION_TEXT : ~('\n');
OPEN_NAME : '@name' -> mode(NAME);
mode NAME;
INNER_WS : (' ' | '\t')+;
NAMEID : ('a'..'z' | 'A'..'Z' | '0'..'9' | '-' | '_' | '?')+;
CLOSE_NAME : (('\r'? '\n') | '*/') -> mode(DEFAULT_MODE);
除了在以下情况下关闭@name定义外,这似乎在大多数情况下都可以正常工作:
/**
* @name someId*/
上述观点应该是完全正确的。在注释以“*/”结尾之前,我们不需要新行。我遇到的问题是“*/”成功终止了名称定义,但它使用了令牌,并且只返回到默认模式,因此我需要:
/**
* @name someId*/*/
如果我真的想让它结束评论。我希望它返回到默认模式,然后意识到这个标记应该结束注释(即,它应该匹配end_QDOC)。如何在ANTLR中实现这一点?我尝试修复它,使CLOSE_NAME与ID相反:
CLOSE_NAME : ~('a'..'z' | 'A'..'Z' | '0'..'9' | '-' | '_' | '?');
但ANTLR仍然使用*在剩余的“/”上留下无法识别的令牌错误。我真正想做的是让ANTLR退出模式而不使用令牌,这样当我们返回到默认的_模式时,“*/”就是下一个令牌。有什么想法吗?首先,您可能不想使用
模式
命令,而是想使用->pushMode(NAME)
和->popMode
返回默认模式
对于CLOSE\u NAME
规则,可以使用谓词而不是匹配的文本来处理注释的结尾:
CLOSE_NAME
: ( '\r'? '\n'
| {_input.LA(1) == '*' && _input.LA(2) == '/'}?
)
-> popMode
;
这可能会产生一个零长度标记,在ANTLR 4.0中是不允许的,但在ANTLR 4.1中取消了该限制(更改为警告),因为我们意识到零长度标记可以用来触发模式更改,从而避免无限循环。我肯定遗漏了一些东西,因为这不起作用。现在代币消失了。它没有显示为CLOSE_名称的一部分,但我仍然得到不匹配的输入“”,期望CLOSE_名称IntStream.LA是否实际使用该字符?这在文件中并不清楚。如果LA代表前瞻,那么这就是我想要的,但它似乎不能正常工作。