非片段词法分析器规则 x 可以匹配空字符串

non-fragment lexer rule x can match the empty string

下面的 antlr 词法分析器有什么问题?

我收到一个错误

warning(146): MySQL.g4:5685:0: non-fragment lexer rule VERSION_COMMENT_TAIL can match the empty string

附源码

VERSION_COMMENT_TAIL:
{ VERSION_MATCHED == False }? // One level of block comment nesting is allowed for version comments.
    ((ML_COMMENT_HEAD MULTILINE_COMMENT) | . )*? ML_COMMENT_END { self.setType(MULTILINE_COMMENT); }
| { self.setType(VERSION_COMMENT); IN_VERSION_COMMENT = True; }

;

您正在尝试将我的 MySQL 的 ANTLR3 语法转换为 ANTLR4?删除词法分析器中的所有注释规则并插入:

// There are 3 types of block comments:
// /* ... */ - The standard multi line comment.
// /*! ... */ - A comment used to mask code for other clients. In MySQL the content is handled as normal code.
// /*!12345 ... */ - Same as the previous one except code is only used when the given number is a lower value
//                   than the current server version (specifying so the minimum server version the code can run with).
VERSION_COMMENT_START: ('/*!' DIGITS) (
  {checkVersion(getText())}? // Will set inVersionComment if the number matches.
  | .*? '*/'
) -> channel(HIDDEN)
;

// inVersionComment is a variable in the base lexer.
MYSQL_COMMENT_START: '/*!' { inVersionComment = true; setChannel(HIDDEN); };
VERSION_COMMENT_END: '*/' {inVersionComment}? { inVersionComment = false; setChannel(HIDDEN); };
BLOCK_COMMENT: '/*' ~[!] .*? '*/' -> channel(HIDDEN);

POUND_COMMENT: '#' ~([\n\r])*  -> channel(HIDDEN);
DASHDASH_COMMENT: DOUBLE_DASH ([ \t] (~[\n\r])* | LINEBREAK | EOF) -> channel(HIDDEN);

你需要一个本地 inVersionComment 成员和一个函数 checkVersion() 在你的词法分析器中(我在生成的词法分析器派生的基础词法分析器中有它)returns true or false , 取决于当前服务器版本是否等于或高于给定版本。

对于您的问题:您不能在备选方案中采取行动。操作只能出现在整个规则的末尾。这与 ANTLR3 不同。