我有以下antlr4代码:
decnum returns [double value] :
NUMBER {$value = Double.parseDouble($NUMBER.text);}
;
POINT : '.';
INTNUMBER : ('0'..'9')+ ;
NUMBER : INTNUMBER (POINT INTNUMBER)?;当我在System.out.println(parser.decnum().value);上做String s = 1.2时,它正确地工作。但它也适用于这些字符串:
"0001.2000."
"0001.2000.asfgheg"
".0001.2000.37"
"5.61345345ggdfhfjg"在"5"上不起作用
我做错了什么?
此外,为什么即使解析失败,antlr4也会尝试计算表达式?我得到了token recognition error,但是评估结果还是打印出来了。怎么让它失效?
发布于 2014-12-15 11:52:15
从最后一项开始:表达式将得到评估,解析是否成功,因为您将计算作为规则的一部分。使用ANTLR 4的推荐方法是允许它简单地构建一个解析树,然后在解析完成后使用侦听器和/或访问者来执行所需的评估。例如,您的decnum规则应该如下所示:
decnum
: NUMBER
;继续输入"5"。此输入与上面列出的任何规则不匹配,因为语法中没有任何规则包括输入字符"。当ANTLR 4到达此字符且没有规则匹配时,它将通过跳过该字符并继续下一个字符恢复。第一次发生这种情况时,ANTLR 4将从本质上看这个问题,以找到下一个令牌:5"。
当ANTLR 4开始匹配5"时,它确定INTNUMBER和NUMBER规则都匹配输入5,这是最长的匹配,因为没有规则匹配较长的序列5"。ANTLR 4只能为每个令牌分配一种令牌类型,这是在任何解析规则看到令牌之前执行的。它没有将值INTNUMBER和NUMBER都分配给5,而是根据规则在语法中出现的顺序来确定这种情况下的令牌类型;也就是说,ANTLR 4将5匹配为一个也不是NUMBER令牌的INTNUMBER令牌。最后,ANTLR 4跳过最后一个"字符的原因与跳过第一个字符的原因相同。
对于您提供的其他字符串,将使用类似的计算序列。例如,"0001.2000.asfgheg"匹配为:
":忽略错误(不匹配).:POINT0001.2000:NUMBER.:POINTa:忽略错误(不匹配)s:忽略错误(不匹配)f:忽略错误(不匹配)g:忽略错误(不匹配)h:忽略错误(不匹配)e:忽略错误(不匹配)g:忽略错误(不匹配)":忽略错误(不匹配)在解析器中,上面的内容只显示为POINT、NUMBER、POINT。
如果您想将我前面提到的跳过的字符作为语法错误包含在解析树中,您可以通过在lexer中添加以下规则来实现这一点。此规则匹配任何单个字符,但前提是没有其他规则匹配,这正是错误恢复机制在不包括规则时所匹配的。此规则将将错误字符作为单个ErrorCharacter令牌传递给解析器。
ErrorCharacter
: .
;https://stackoverflow.com/questions/27477631
复制相似问题