该规则有以下几点错误:
rest:
~('\n'|'\r')* '\r'? ('\n'|EOF)
;
在解析器规则中
~
否定lexer生成的整个令牌集。所以
~('\n'|'\r')
没有
不
匹配除之外的单个字符
'\n'
或
'\r'
。它匹配任何
代币
除了匹配的令牌
\r
或
\n
。
此外,由于你的lexer
'\n'
和
'\r'
在隐藏通道上,这些令牌在解析器中不可用。这意味着
'\n'
在
rest
规则永远无法匹配。
简而言之:你不能“告诉”你的解析器一行的末尾是什么,因为这些字符被你的
WS
规则这意味着你没有办法正确地写出这样的
休息
语法分析器规则。
请输入:
0: IN 0,0,0
1: LDC 1,1,0 r1=0
(注意,我删除了
'rule:'
的)
以下令牌由lexer生成:
token[type=INTEGER text='0']
token[type=':' text=':']
token[type='IN' text='IN']
token[type=INTEGER text='0']
token[type=',' text=',']
token[type=INTEGER text='0']
token[type=',' text=',']
token[type=INTEGER text='0']
token[type=INTEGER text='1']
token[type=':' text=':']
token[type='LDC' text='LDC']
token[type=INTEGER text='1']
token[type=',' text=',']
token[type=INTEGER text='1']
token[type=',' text=',']
token[type=INTEGER text='0']
token[type=INTEGER text='1']
token[type=INTEGER text='0']
因此,这些是解析器规则中可用的令牌。
请注意以下两个字符:
'='
和
'r'
无法被lexer匹配,正如您通过查看错误所看到的:
line 2:13 no viable alternative at character 'r'
line 2:15 no viable alternative at character '='
一个可能的解决方案是创建一个匹配整数和冒号的lexer规则:
START : INTEGER ':';
让你的
rule
从这个令牌开始:
rule
: START ro=rocommand i1=INTEGER ',' i2=INTEGER ',' i3=INTEGER rest ...
| ...
;
那样,你的
休息
可以匹配除此之外的零个或多个令牌
START
令牌:
rest
: ~START*
;
为了捕捉
'='
和
“r”
字符,创建
ANY
规则,并将此规则放在lexer规则的末尾:
ANY : . ; // match any char
这样,解析器将创建以下解析树:
另一个解决方案是创建
LINE_BREAK
令牌:
LINE_BREAK : '\r'? '\n' | '\r';
(并移除
\r
和
\n个
从…起
操作系统
,当然!)
然后这样做:
rule
: INTEGER ':' ro=rocommand i1=INTEGER ',' i2=INTEGER ',' i3=INTEGER rest LINE_BREAK ...
| ...
;
rest
: ~LINE_BREAK*
;