使用 ANTLR 解析字母范围

Parsing letter ranges with ANTLR

我有以下解析器规则:

defDirective : defType whiteSpace letterSpec (whiteSpace? COMMA whiteSpace? letterSpec)*;
defType :
        DEFBOOL | DEFBYTE | DEFINT | DEFLNG | DEFLNGLNG | DEFLNGPTR | DEFCUR |
        DEFSNG | DEFDBL | DEFDATE | 
        DEFSTR | DEFOBJ | DEFVAR
;
letterSpec : universalLetterRange | letterRange | singleLetter;

singleLetter : RESTRICTED_LETTER;
universalLetterRange : upperCaseA whiteSpace? MINUS whiteSpace? upperCaseZ;
upperCaseA : {_input.Lt(1).Text.Equals("A")}? RESTRICTED_LETTER;
upperCaseZ : {_input.Lt(1).Text.Equals("Z")}? RESTRICTED_LETTER;
letterRange : firstLetter whiteSpace? MINUS whiteSpace? lastLetter;
firstLetter : RESTRICTED_LETTER;
lastLetter : RESTRICTED_LETTER;

whiteSpace : (WS | LINE_CONTINUATION)+;

使用相关的 Lexer 规则:

RESTRICTED_LETTER : [a-zA-Z];
MINUS : '-';
COMMA : ',';
WS : [ \t];
LINE_CONTINUATION : [ \t]* UNDERSCORE [ \t]* '\r'? '\n';

DefTypes 匹配他们的驼峰拼写。

现在,当我尝试在以下输入上对此进行测试时,它完全按预期工作:

DefInt I,J,K
DefBool A-Z

工作但是在任意字母范围内(见规则letterRange)。当我使用输入 DefByte B-F 时,我收到错误消息 "line 1:8 mismatched input 'B' expecting RESTRICTED_LETTER"

我试过将 RESTRICTED_IDENTIFIER 表示为一个范围 ('A'..'Z'|'a'..'z'),但这并没有改变错误消息的任何内容。

当将 defDirective 中的第一个 whiteSpace 更改为 whiteSpace+ 时,错误消息会变长一点(现在在预期的替代项中包括 WS 和 LINE_CONTINUATION)。

而且由 IntelliJ ANTLR 插件生成的解析树突然开始将 F 识别为 singleLetter,而它以前没有。

此行为似乎在目标语言 Java 和 CSharp 之间是一致的。

以前规则要宽松得多,但这会导致错误的解析树,所以我有点想解决这个问题。

如何正确识别这里的letterRange

所以……@BartKiers 的怀疑是正确的。给定的 Lexer 规则并不是该过程中涉及的所有规则。

完整语法包含一个词法分析器规则 B_CHAR : B,用于不相关语法规则的特殊情况。在对输入流进行词法分析时,B_CHAR 优先于 RESTRICTED_LETTER

提供的语法规则是正确的(并且工作正常),但是 B_CHAR 标记需要从词法分析的标记中删除。