ANTLR4没有可行的替代方案;空间问题



grammar Hello;
@parser::header {
import java.util.*;
}
@parser::members {
Map<Integer, String> map = new HashMap<Integer, String>();
int A = 0;
int B = 0;
int max = 0;
}
prog
@after {
List<Integer> msgs = new ArrayList<>(map.keySet());
Collections.sort(msgs);
for (int i=0; i< msgs.size(); i++){
System.out.println(map.get(msgs.get(i)));
}
System.out.println("Alice: "+ A +", Bob: "+B);
System.out.println(max);
}
: stat+;
stat: message NL | message;
message: h=T_NUM ':' m=T_NUM ':' s=T_NUM 'A' ':' T_MSG {
String msg = $h.getText() + ":" + $m.getText() +  ":" + $s.getText() + " A: " + $T_MSG.getText();
int len = $T_MSG.getText().length();
if (len > max) max = len;
A++;
int id = Integer.parseInt($h.getText()) * 3600 + Integer.parseInt($m.getText()) * 60 + Integer.parseInt($s.getText());
map.put(id, msg);
} | h=T_NUM ':' m=T_NUM ':' s=T_NUM 'B' ':' T_MSG {
String msg = $h.getText() + ":" + $m.getText() +  ":" + $s.getText() + " A: " + $T_MSG.getText();
int len = $T_MSG.getText().length();
if (len > max) max = len;
B++;
int id = Integer.parseInt($h.getText()) * 3600 + Integer.parseInt($m.getText()) * 60 + Integer.parseInt($s.getText());
map.put(id, msg);
};

T_NUM: [0-9][0-9];
T_MSG: [A-Za-z0-9.,!? ]+;
NL: [n]+;
WS : [ tr]+ -> skip ; // skip spaces, tabs, newlines

你好!因此,我有一项任务要在ANTLR4中编写语法和语法分析器,它可以识别这种输入:

00:10:11 A: Message 1 
23:12:12 B: Message 5 
11:12:13 A: Message 2 
12:21:12 B: Message 4 
11:12:15 A: Message 3

作为输出,它必须按时间对消息进行排序。现在我的问题是空间。我想能够识别消息中的空格,但我遇到了一个错误:

第1:6行输入"00:10:11 A"时没有可行的替代方案爱丽丝:0,鲍勃:00

当我从T_MSG标记中删除空格并输入时,它显然是有效的。但我不知道如何让它能够识别消息中的空格。

始终转储您的令牌流,以查看Lexer为Parser生成的内容。

对于测试输入的第一行(使用grun Hello prog -tokens < Hello.txt(,我得到:

[@0,0:1='00',<T_NUM>,1:0]
[@1,2:2=':',<':'>,1:2]
[@2,3:4='10',<T_NUM>,1:3]
[@3,5:5=':',<':'>,1:5]
[@4,6:9='11 A',<T_MSG>,1:6]
[@5,10:10=':',<':'>,1:10]
[@6,11:21=' Message 1 ',<T_MSG>,1:11]
[@7,22:22='n',<NL>,1:22]
[@8,23:22='<EOF>',<EOF>,2:0]
line 1:6 no viable alternative at input '00:10:11 A'
Alice: 0, Bob: 0
0

特别注意

[@4,6:9='11 A',<T_MSG>,1:6]

您的解析器没有看到解析器规则认为它会看到的令牌流。

这是因为";11A";与T_MSGLexer规则相匹配。注意:即使CCD_ 3规则与";11〃;输入,ANTLR的Lexer将使用消耗最多输入的Lexe规则,因此ANTLR将生成T_MSG令牌。

这就是为什么你会得到观察到的错误。


有一些方法可以使用Lexer模式,而不是skippingWS(这意味着说明WS可能出现在解析器规则中的所有位置(,或者可能使用其他一些技术。

也就是说,你真的在工作中使用了错误的工具。逐行读取此输入并应用具有捕获组的Regex将非常简单。您的输入不需要一个完整的解析器。

如果你继续使用ANTLR,你可能也会更好地计算语法以获得正确的解析树,然后使用listener来处理结果。如果您还没有构建正确的解析树,那么所有的@parser*prog {...}和解析器规则操作充其量只是分散注意力。

最新更新