字符串"keyup"
正在被标记为NAME
令牌:这就是问题所在。
您必须意识到词法分析器独立于解析器运行。如果解析器试图匹配KEYPRESS
token,词法分析器不会“监听”它,而只是按照规则构造一个 token:
- 匹配消耗最多字符的规则
- 如果有多个规则匹配相同数量的字符,则选择第一个定义的规则
考虑到这些规则以及规则的顺序:
NAME : [A-Za-z_][A-Za-z_0-9]* ;
INT : [0-9]+ ;
KEY : [a-z] | [0-9] | 'shift' | 'ctrl' | 'alt' | 'meta' | 'space' | 'left' | 'right' | 'up' | 'down' | 'minus' | 'equals' | 'backspace' | 'openbracket' | 'closebracket' | 'backslash' | 'semicolon' | 'quote' | 'enter' | 'comma' | 'period' | 'slash' ;
KEYPRESS : 'keyup' | 'keydown' ;
a NAME
令牌将在大多数之前创建KEY
替代方案,以及所有KEYPRESS
将创建替代方案。
并且自从INT
匹配一位或多位数字并在之前定义KEY
它也有一个单位数字的替代,很明显,词法分析器永远不会产生一个KEY
or KEYPRESS
token.
如果您移动NAME
and INT
规则低于KEY
and KEYPRESS
规则,那么大多数令牌将按照您的预期构建,这是我的猜测。
EDIT
一个可能的解决方案如下:
KEY : [a-z] | 'shift' | 'ctrl' | 'alt' | 'meta' | 'space' | 'left' | 'right' | 'up' | 'down' | 'minus' | 'equals' | 'backspace' | 'openbracket' | 'closebracket' | 'backslash' | 'semicolon' | 'quote' | 'enter' | 'comma' | 'period' | 'slash' ;
KEYPRESS : 'keyup' | 'keydown' ;
NAME : [A-Za-z_][A-Za-z_0-9]* ;
SINGLE_DIGIT : [0-9] ;
INT : [0-9]+ ;
IE。我删除了[0-9]
替代方案KEY
并介绍了一个SINGLE_DIGIT
规则(放置在before the INT
rule!).
现在创建一些额外的解析器规则:
integer : INT | SINGLE_DIGIT ;
key : KEY | SINGLE_DIGIT ;
并更改所有出现的INT
内部解析器规则integer
(不要称你的规则为int
:这是一个保留字)并更改所有KEY
to key
.
你可能还想做类似的事情NAME
和[a-z]
替代方案KEY
(即单个小写字符现在永远不会被标记为NAME
,始终作为KEY
).