无法创建只有一个字母的变量

Can't create a variable with just one letter

我希望变量可以在名称中只用一个字母来声明。 当我写 Integer aa;所有的工作,但是 当我输入 Integer a 时;然后 grun 说:不匹配的输入 'a' 期待 ID。 我见过反问题,但没有帮助。我认为我的代码是正确的,但我看不出哪里错了。这是我的词法分析器:

lexer grammar Symbols;

...

LineComment: '//' ~[\u000A\u000D]* -> channel(HIDDEN) ;
DelimetedComment: '/*' .*? '*/' -> channel(HIDDEN) ;

String: '"' .*? '"' ;
Character: '\'' (EscapeSeq | .) '\'' ;
IntegerLiteral: '0' | (ADD?| SUB) DecDigitNoZero DecDigit+ ;
FloatLiteral: ((ADD? | SUB) (DecDigitNoZero DecDigit*)? DOT DecDigit+ | IntegerLiteral) [F] ;
DoubleLiteral: ((ADD? | SUB) (DecDigitNoZero DecDigit*)? DOT DecDigit+ | IntegerLiteral) [D]  ;
LongLiteral: IntegerLiteral [L] ;
HexLiteral: '0' [xX] HexDigit (HexDigit | UNDERSCORE)* ;
BinLiteral: '0' [bB] BinDigit (BinDigit | UNDERSCORE)* ;
OctLiteral: '0' [cC] OctDigit (OctDigit | UNDERSCORE)* ;
Booleans: TRUE | FALSE ;
Number: IntegerLiteral | FloatLiteral | DoubleLiteral | BinLiteral | HexLiteral | OctLiteral | LongLiteral ;
EscapeSeq: UniCharacterLiteral | EscapedIdentifier;
UniCharacterLiteral: '\' 'u' HexDigit HexDigit HexDigit HexDigit ;
EscapedIdentifier: '\' ('t' | 'b' | 'r' | 'n' | '\'' | '"' | '\' | '$') ;
HexDigit: [0-9a-fA-F] ;
BinDigit: [01] ;
OctDigit: [0-7];
DecDigit: [0-9];
DecDigitNoZero: [1-9];

ID: [a-z] ([a-zA-Z_] | [0-9])*;
TYPE: [A-Z] ([a-zA-Z] | UNDERSCORE | [0-9])* ;

DATATYPE: Number | String | Character | Booleans ;

当你得到像 "Unexpected input 'foo', expected BAR" 这样的错误并且你认为 "But 'foo' is a BAR" 时,你应该做的第一件事就是为你的输入打印令牌流(你可以通过 运行 grun Symbols tokens -tokens inputfile)。如果这样做,您会看到输入中的 a 被识别为 HexDigit,而不是 ID.

为什么会这样?因为 HexDigitID 都匹配输入 a 并且 ANTLR(像大多数词法分析器生成器一样)根据最大 munch 规则解决歧义:当多个规则可以匹配当前输入时,它选择产生最长匹配的一个(这就是为什么具有多个字母的变量起作用的原因)然后通过选择第一个定义的那个来解决平局,在这种情况下是 HexDigit

请注意,词法分析器不关心解析器使用了哪些词法分析器规则以及何时使用。词法分析器仅根据词法分析器语法的内容来决定生成哪些标记,因此词法分析器不知道或不关心解析器现在需要 ID。它会查看所有匹配的规则,然后根据最大咀嚼规则选择一个,就是这样。

在您的情况下,您实际上从未在解析器语法中使用 HexDigit,因此您没有理由想要创建 HexDigit 标记。因此 HexDigit 不应该是词法分析器规则 - 它应该是 fragment:

fragment HexDigit : [0-9a-fA-F];

这也适用于解析器中未使用的其他规则,包括所有 ...Digit 规则。

PS:由于这些相同的规则,您的 Number 规则永远不会匹配。它可能应该是一个解析器规则(或者其他数字规则应该是片段,如果你不关心你有哪种数字文字)。