使用 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
标记需要从词法分析的标记中删除。
我有以下解析器规则:
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
标记需要从词法分析的标记中删除。