无法创建只有一个字母的变量
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
.
为什么会这样?因为 HexDigit
和 ID
都匹配输入 a
并且 ANTLR(像大多数词法分析器生成器一样)根据最大 munch 规则解决歧义:当多个规则可以匹配当前输入时,它选择产生最长匹配的一个(这就是为什么具有多个字母的变量起作用的原因)然后通过选择第一个定义的那个来解决平局,在这种情况下是 HexDigit
。
请注意,词法分析器不关心解析器使用了哪些词法分析器规则以及何时使用。词法分析器仅根据词法分析器语法的内容来决定生成哪些标记,因此词法分析器不知道或不关心解析器现在需要 ID
。它会查看所有匹配的规则,然后根据最大咀嚼规则选择一个,就是这样。
在您的情况下,您实际上从未在解析器语法中使用 HexDigit
,因此您没有理由想要创建 HexDigit
标记。因此 HexDigit
不应该是词法分析器规则 - 它应该是 fragment
:
fragment HexDigit : [0-9a-fA-F];
这也适用于解析器中未使用的其他规则,包括所有 ...Digit
规则。
PS:由于这些相同的规则,您的 Number
规则永远不会匹配。它可能应该是一个解析器规则(或者其他数字规则应该是片段,如果你不关心你有哪种数字文字)。
我希望变量可以在名称中只用一个字母来声明。 当我写 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
.
为什么会这样?因为 HexDigit
和 ID
都匹配输入 a
并且 ANTLR(像大多数词法分析器生成器一样)根据最大 munch 规则解决歧义:当多个规则可以匹配当前输入时,它选择产生最长匹配的一个(这就是为什么具有多个字母的变量起作用的原因)然后通过选择第一个定义的那个来解决平局,在这种情况下是 HexDigit
。
请注意,词法分析器不关心解析器使用了哪些词法分析器规则以及何时使用。词法分析器仅根据词法分析器语法的内容来决定生成哪些标记,因此词法分析器不知道或不关心解析器现在需要 ID
。它会查看所有匹配的规则,然后根据最大咀嚼规则选择一个,就是这样。
在您的情况下,您实际上从未在解析器语法中使用 HexDigit
,因此您没有理由想要创建 HexDigit
标记。因此 HexDigit
不应该是词法分析器规则 - 它应该是 fragment
:
fragment HexDigit : [0-9a-fA-F];
这也适用于解析器中未使用的其他规则,包括所有 ...Digit
规则。
PS:由于这些相同的规则,您的 Number
规则永远不会匹配。它可能应该是一个解析器规则(或者其他数字规则应该是片段,如果你不关心你有哪种数字文字)。