如何在 Antlr 的不同词法分析模式下使用相同的令牌?



我有一个基于 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`

最新更新