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