如何在ANTLR4中实现错误处理 [英] How to implement error handling in ANTLR4
问题描述
我有以下语法来解析应用于图形的一阶逻辑公式:
I have the following grammar for parsing first-order logic formulas applied over graphs:
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,这是添加错误处理的地方.
I believe that this is the final version of my grammar so now I want to specify some error handling for the input. The problem is that I don't know how. What I know is that after I parse the input I can iterate over the generated AST and this is the place to add the error handling.
如果解析失败,返回解析异常;否则,我已指定以下情况返回错误消息.
If the parse fails, return the parse exception; otherwise, I have specified the following cases for returning error message.
不能有 1 个量词后跟
->条件
(这是一个公式元素)其中条件等于atom=atom
.换句话说,如果只有量词
,那么condition
应该等于atom EQUALS assignment
.
There can't be 1 quantifier followed by
-> condition
(this is a formula element) where condition is equal toatom=atom
. In other words, if there is onlyquantifier
thencondition
should be equal toatom EQUALS assignment
.
如果有 2 个量词,第一个应该以 FOREACH
If there are 2 quantifiers the first should start with FOREACH
量词中的变量应该在condition
语句中使用
The variable(s) in the quantifiers should be used in the condition
statement
表达式左侧的量词不能超过两个(因为在我开发的应用程序中只有两个图形).因此,如果量词的数量更多,则也会返回两个错误
There can't be more than two quantifiers on the left hand-side of the expression (because in the app I am developing there are only two graphs). So if the number of quantifiers is greater then two return error as well
如果有 2 个量词,那么它们应该绑定不同的变量
If there are 2 quantifiers then they should have different variables bound on them
例如,当我们将输入作为输入时,应该引发第一种情况
For example, the first case should be raised when as an input we have
Exists node in GraphA -> node.color = node1.color
因为 node1
未在表达式的左侧指定.
because node1
isn't specified in the left hand-side of the expression.
第二种情况的一个例子是以下输入
An example for the second case would be the following input
Exists node in GraphA Exists node1 in GraphB -> node.color = node1.color
所以我的问题是我是否必须对生成的解析树执行所有错误检查,或者我可以使用一些 java 代码在语法中指定其中的一些错误.如果在解析输入后发生错误处理,我可以使用 ANTLR 4 的哪些功能来实现错误情况?任何帮助或建议将不胜感激!
So my question is do I have to implement all the error checking over the generated parse tree or I can specify some of it in the grammar using some java code. If the error handling should happen after the input is parsed what functionality of ANTLR 4 can I use in order to implement the error cases? Any help or advice would be much appreciated!
推荐答案
您可能希望在侦听器中与辅助访问者一起实现这些语义检查.以下是一些示例.
You'll probably want to implement these semantic checks in a listener, in combination with helper visitors. Here are some examples.
实施:
- 创建一个访问者,返回指定解析树节点使用的变量.你会想要覆盖
defaultResult()
和aggregateResult(T, T)
为你做大部分工作,然后覆盖visitNodev
和visitEdgev
来处理正在使用的特定变量. - 在您的侦听器中,覆盖
enterFormula
方法.在此方法中,如果ctx.quantifier()
不为 null,则使用访问者获取ctx.quantifier()
中声明的变量列表和变量列表在ctx.formula()
中使用. - 根据两个结果酌情报告错误.
- Create a visitor that returns the variables used by a specified parse tree node. You'll want to override
defaultResult()
andaggregateResult(T, T)
to do most of the work for you, and then overridevisitNodev
andvisitEdgev
to handle the specific variables in use. - In your listener, override the
enterFormula
method. In this method, ifctx.quantifier()
is not null, then use your visitor to get the list of variables declared inctx.quantifier()
and the list of variables used inctx.formula()
. - Report an error as appropriate based on the two results.
规则:如果有 2 个量词,那么它们应该绑定不同的变量
实施:
- 从上一个规则实施的第 1 步中描述的访问者开始.
- 在您的侦听器中,覆盖
enterFormula
方法.方法中,如果ctx.quantifier()
不为null,则需要获取ctx返回的树下所有其他
.您可以通过调用QuantifierContext
实例的集合.formula()XPath.findAll(ctx.formula(), "//quantifier",解析器)
. - 使用上述访问者收集在每个链接的
QuantifierContext
实例中声明的变量列表.如果任何集合重叠,请酌情报告错误.
- Start with the visitor described in step 1 of the previous rule implementation.
- In your listener, override the
enterFormula
method. In the method, ifctx.quantifier()
is not null, then you need to get a collection of all the otherQuantifierContext
instances underneath the tree returned byctx.formula()
. You can do this by callingXPath.findAll(ctx.formula(), "//quantifier", parser)
. - Use the visitor described above to gather a list of variables declared in each of the linked
QuantifierContext
instances. If any of the sets overlap, report an error as appropriate.
规则:如果有 2 个量词,第一个应该以 FOREACH
开头实施:
Rule: If there are 2 quantifiers the first should start with FOREACH
Implementation:
使用上一步中描述的侦听器模式来定位公式包含多个量词
的情况.如果这些公式中的第一个具有 ctx.quantifier().FOREACH() == null
则适当地发出错误.
Use the listener pattern described in the previous step to locate cases where a formula contains more than one quantifier
. If the first of these formulas has ctx.quantifier().FOREACH() == null
emit an error as appropriate.
实施:
更新上面第二条规则的实现,如果XPath.findAll
在formula
中返回多个QuantifierContext
,则报错量词
.
Update the implementation of the 2nd rule above to report an error if XPath.findAll
returns more than one QuantifierContext
in the formula
for a quantifier
.
实施:
首先,创建一个ParseTreePattern
对象.
First, create a ParseTreePattern
object.
String patternString = "<quantifier> -> <condition>";
ParseTreePattern pattern =
parser.compileParseTreePattern(patternString, GraphParser.RULE_formula);
然后,在您的解析树中找到此模式的所有实例.
Then, find all instances of this pattern in your parse tree.
List<ParseTreeMatch> matches = pattern.findAll(tree, "//formula");
验证匹配就相当简单了.
Validating the matches is then rather simple.
for (ParseTreeMatch match : matches) {
ConditionContext condition = (ConditionContext)match.get("condition");
if (condition.assignment() == null) {
// TODO: report error here
}
}
这篇关于如何在ANTLR4中实现错误处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!