我正在尝试使用antlr和java创建一个编译器。我有一个问题,我有一个规则,我不能得到只是它的一部分使用。我有一个命令,例如0:halt0,0,0,我想在那之后忽略其他的一切。
e、 g.0:停下,等等,等等,等等,等等,我想忽略这些
我的规则是:
rule returns [String value]
:
INTEGER':' ro=rocommand i1=INTEGER',' i2=INTEGER ',' i3=INTEGER rest {$value = $ro.text+" "+$i1.text+","+$i2.text+","+$i3.text; }
| INTEGER':' rm=rmcommand j1=INTEGER ',' j2=INTEGER '('j3=INTEGER')' rest {$value = $rm.text+" "+$j1.text+","+$j2.text+"("+$j3.text+")"; }
;
我的密码是:
CharStream charStream = new ANTLRStringStream(strLine);
simulatorLexer lexer = new simulatorLexer(charStream);
TokenStream tokenStream = new CommonTokenStream(lexer);
simulatorParser parser = new simulatorParser(tokenStream);
System.out.println(parser.rule());
我得到的是:
0: rule:IN 0,0,0
1: rule:LDC 1,1,0
line 1:15 no viable alternative at character 'r'
line 1:18 no viable alternative at character '='
line 1:15 no viable alternative at character 'i'
对于文本:
0: rule:IN 0,0,0
1: rule:LDC 1,1,0 r1=0
所以它应该正确解析第一行,第二行直到0。那么它应该忽略r1=0。到目前为止,它工作正常,但它显示了一些错误,我想消除它们。请帮帮我!
编辑
我把全部语法都贴出来了,这样你能帮我更好。我只想知道规则的部分。
program:
rule+
;
rocommand:
'HALT'|'IN'|'OUT'|'ADD'|'SUB'|'MUL'|'DIV'|'LDC'
;
rmcommand:
'LD'|'LDA'|'LDC'|'ST'|'JLT'|'JLE'|'JGE'|'JGT'|'JEQ'|'JNE'
;
rest:
~('\n'|'\r')* '\r'? ('\n'|EOF)
;
rule returns [String value]
:
INTEGER':' ro=rocommand i1=INTEGER',' i2=INTEGER ',' i3=INTEGER rest {$value = $ro.text+" "+$i1.text+","+$i2.text+","+$i3.text; }
| INTEGER':' rm=rmcommand j1=INTEGER ',' j2=INTEGER '('j3=INTEGER')' rest {$value = $rm.text+" "+$j1.text+","+$j2.text+"("+$j3.text+")"; }
;
WS : (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;};
INTEGER : '0'..'9'+;
IGNORELINE : '*' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;};
亚历克斯
1条答案
按热度按时间jq6vz3qz1#
这条规则有几个地方有问题:
在解析器规则中
~
否定lexer生成的整个标记集。所以呢~('\n'|'\r')
不匹配除'\n'
或者'\r'
. 它匹配除匹配的令牌之外的任何令牌\r
或者\n
.还有,既然你的雷克瑟
'\n'
以及'\r'
在隐藏通道上,这些令牌在解析器中不可用。这意味着'\n'
在rest
规则永远无法匹配。简而言之:你不能“告诉”你的解析器一行的结尾是什么,因为这些字符被你的解析器丢弃了
WS
规则。这意味着你没有办法正确地写这样一篇文章rest
分析器规则。供您输入:
(请注意,我删除了
'rule:'
的)以下令牌由lexer生成:
这些是解析器规则中可用的标记。
请注意以下两个字符:
'='
以及'r'
无法与lexer匹配,通过查看错误可以看出:一个可能的解决方案是创建一个匹配整数和冒号的lexer规则:
让你的
rule
从以下令牌开始:那样,你的
rest
可以匹配零个或多个令牌START
代币:为了抓住
'='
以及'r'
角色,创建ANY
规则并将此规则放在lexer规则的末尾:这样,解析器将创建以下解析树:
另一个解决方案是创建一个
LINE_BREAK
代币:(并移除
\r
以及\n
从WS
,当然!)然后这样做: