我有以下语法来解析应用于图形的一阶逻辑公式:
grammar Graph;
/*------------------------------------------------------------------
* PARSER RULES
*------------------------------------------------------------------*/
input
:
formula EOF
;
formula
:
TRUE
| FALSE
| formula AND formula
| formula OR formula
| quantifier formula
| ST condition
;
condition
:
atom EQUALS QUOTE? (assignment | atom) QUOTE?
;
quantifier
:
(FOREACH | EXISTS) variable IN domain
;
domain
:
(GRAPH_A | GRAPH_B)
;
atom
:
variable DOT property
;
variable
:
(nodev | edgev)
;
nodev
:
(NODE | NODE1)
;
edgev
:
(EDGE | EDGE1)
;
property
:
(COLOR | VALUE)
;
assignment
:
(COLORTYPE | NUMBER)
;
/*------------------------------------------------------------------
* LEXER RULES
*------------------------------------------------------------------*/
TRUE : 'True' ;
FALSE : 'False' ;
AND : '&' ;
OR : '|' ;
ST : '->' ;
EXISTS : 'Exists' ;
FOREACH : 'Foreach' ;
NODE : 'node' ;
NODE1 : 'node1' ;
EDGE : 'edge' ;
EDGE1 : 'edge1' ;
IN : 'in' ;
GRAPH_A : 'GraphA' ;
GRAPH_B : 'GraphB' ;
EQUALS : '=' ;
DOT : '.' ;
COLOR : 'color' ;
VALUE : 'value' ;
NUMBER : ('0'..'9')+ (DOT ('0'..'9')+)? ;
QUOTE : '\'' ;
COLORTYPE : ('a'..'z')+ ;
WS : [ \t\r\n]+ -> skip ;
我相信这是我的语法的最终版本所以现在我想为输入指定一些错误处理。问题是我不知道怎么做。我所知道的是,在我解析输入后,我可以迭代生成的AST,这是添加错误处理的地方。
如果解析失败,则返回解析异常;否则,我已指定以下情况返回错误消息。
条件等于-> condition
时,不能有1个量词,后跟atom=atom
(这是一个公式元素)。换句话说,如果只有quantifier
,那么condition
应该等于atom EQUALS assignment
。
如果有2个量词,则第一个应以FOREACH
量词中的变量应在condition
陈述中使用
在表达式的左侧不能有两个以上的量词(因为在我正在开发的应用程序中,只有两个图形)。因此,如果量词的数量大于那么两个返回错误
如果有2个量词,那么它们应该有不同的变量绑定
例如,当我们作为输入
时,应该引发第一种情况Exists node in GraphA -> node.color = node1.color
因为node1
未在表达式的左侧指定。
第二种情况的例子是以下输入
Exists node in GraphA Exists node1 in GraphB -> node.color = node1.color
所以我的问题是我是否必须对生成的解析树实现所有错误检查,或者我可以使用一些java代码在语法中指定一些错误检查。如果在解析输入后发生错误处理,我可以使用ANTLR 4的哪些功能来实现错误情况?任何帮助或建议将不胜感激!
答案 0 :(得分:6)
您可能希望在侦听器中与辅助访问者一起实现这些语义检查。以下是一些例子。
quantifier
中的变量应在condition
实现:
defaultResult()
和aggregateResult(T, T)
以完成大部分工作,然后覆盖visitNodev
和visitEdgev
以处理正在使用的特定变量。enterFormula
方法。在此方法中,如果ctx.quantifier()
不为null,则使用您的访问者获取ctx.quantifier()
中声明的变量列表以及ctx.formula()
中使用的变量列表。实现:
enterFormula
方法。在该方法中,如果ctx.quantifier()
不为null,则需要获取QuantifierContext
返回的树下所有其他ctx.formula()
个实例的集合。您可以致电XPath.findAll(ctx.formula(), "//quantifier", parser)
。QuantifierContext
实例中声明的变量列表。如果任何集重叠,请报告错误。FOREACH
实现:
使用上一步中描述的侦听器模式来查找公式包含多个quantifier
的情况。如果这些公式中的第一个具有ctx.quantifier().FOREACH() == null
,则会在适当时发出错误。
实现:
如果XPath.findAll
在QuantifierContext
的{{1}}中为formula
返回多个quantifier
,则更新上述第二条规则的实施,以报告错误。
实现:
首先,创建一个ParseTreePattern
对象。
String patternString = "<quantifier> -> <condition>";
ParseTreePattern pattern =
parser.compileParseTreePattern(patternString, GraphParser.RULE_formula);
然后,在解析树中找到此模式的所有实例。
List<ParseTreeMatch> matches = pattern.findAll(tree, "//formula");
验证匹配非常简单。
for (ParseTreeMatch match : matches) {
ConditionContext condition = (ConditionContext)match.get("condition");
if (condition.assignment() == null) {
// TODO: report error here
}
}