我仍在尝试使用ANTLR解析一个简单的Javadoc样式格式。基本上格式如下:
/**
* 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;
我的lexer语法在这里:
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退出模式而不消耗令牌,这样当我们返回DEFAULT_MODE时'* /'是下一个令牌。有什么想法吗?
答案 0 :(得分:0)
首先,您可能希望使用mode
和-> pushMode(NAME)
返回默认模式,而不是使用-> popMode
命令。
对于CLOSE_NAME
规则,您可以使用谓词而不是匹配的文字来处理评论的结尾:
CLOSE_NAME
: ( '\r'? '\n'
| {_input.LA(1) == '*' && _input.LA(2) == '/'}?
)
-> popMode
;
这可以产生零长度令牌并且在ANTLR 4.0中不被允许,但是在ANTLR 4.1中删除了限制(更改为警告),因为我们意识到可以使用零长度令牌来触发模式改变,从而避免无限循环。