我有一个基于 SQL Antlr4 的词法分析器,它也在解析 SQL 注释中的特定标签:
OPEN_COMMENT: '/*' -> mode(COMMENT);
mode COMMENT;
NAME_TAG : '@name';
CLOSE_COMMENT: '*/' -> mode(DEFAULT_MODE);
此词法分析器能够读取以下内容:
/* @name GetAllUsers */
但是,我也希望能够阅读行注释:
-- @name @GetAllUsers
我不能使用相同的模式,因为CLOSE_COMMENT应该以不同的方式工作:它应该*/
块注释,n
行注释。但是,我希望解析器获得相同的令牌,无论它是行注释还是块注释。
我该如何实现?或者使用词法分析器模式可能根本不是正确的方法?
(出于这个问题的目的,我将代码修剪为仅必要的部分,因此更容易阅读和推理。您可以在此处找到有问题的整个代码。
你需要将一些东西复制到2种不同的模式中。您可以定义通用标记,例如语法tokens { ... }
块中的NAME
标记,以便可以在两种模式下共享它。
快速演示:
lexer grammar TestLexer;
tokens {
NAME
}
ID
: [a-zA-Z_] [a-zA-Z_0-9]*
;
LINE_COMMENT_START
: '--' -> skip, mode(LINE_COMMENT_MODE)
;
BLOCK_COMMENT_START
: '/*' -> skip, mode(BLOCK_COMMENT_MODE)
;
mode LINE_COMMENT_MODE;
LINE_COMMENT_MODE_ID
: ID -> type(ID)
;
LINE_COMMENT_NAME
: '@name' -> type(NAME)
;
LINE_COMMENT_END
: [rn]+ -> skip, mode(DEFAULT_MODE)
;
LINE_COMMENT_OTHER
: . -> skip
;
mode BLOCK_COMMENT_MODE;
BLOCK_COMMENT_MODE_ID
: ID -> type(ID)
;
BLOCK_COMMENT_NAME
: '@name' -> type(NAME)
;
BLOCK_COMMENT_END
: '*/' -> skip, mode(DEFAULT_MODE)
;
BLOCK_COMMENT_OTHER
: . -> skip
;
如果标记输入:
-- @name GetAllUsers
/* @name GetAllUsers */
您将获取以下令牌:
NAME `@name`
ID `GetAllUsers`
NAME `@name`
ID `GetAllUsers`