在ANTLR中,我应该如何实现一个带有状态上下文的Visitor?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在ANTLR中,我应该如何实现一个带有状态上下文的Visitor?相关的知识,希望对你有一定的参考价值。
我想写一个简单的ANTLR解析器来处理日期调整,所以例如我可以写。+1w+1d
意思是 "穿越一周零一天",或者是 MIN(+30d, +1m)
意思是 "自输入日期起30天,或1个月,以较早者为准"。 这些规则应该是可以组合的,所以 MIN(+30d, +1m)+1d
指 "自输入日期起30天,或自输入日期起1个月,以较早者为准",以及 +1dMIN(+30d, +1m)
意思是 "从(输入日期的次日)起30天或(输入日期的次日)起1个月,以较早者为准"。
[我很欣赏这里的例子比较老套--真正的语法需要了解周末、假期、月份界限等,所以可能会出现 "一个月后(输入日期的月末或输入日期后的周五--以先到者为准) "等内容]等等。
我想写的代码是。
DateAdjutmeParser parser = buildFromString("MAX(+30d,+1m)");
ParseTree tree = parser.rootNode();
return new MyVisitor().visit(tree, LocalDate.of(2020,4,23)); //Not allowed extra parameters here.
问题是我如何才能传递 "上下文日期"?我不能把它存储在 MyVisitor
类的成员,因为 visit()
调用是递归的,这将覆盖上下文。我可以建立一个并行的对象集,这些对象确实有正确的方法,但这似乎有很多模板。
有没有一个ANTLR的解决方案?
更多细节。
这是我想写的游客程序。
public class MyVisitor extends DateAdjustBaseVisitor<LocalDate> {
@Override
public LocalDate visitOffsetRule(DateAdjustParser.OffsetRuleContext ctx) {
LocalDate contextDate = ???; //
return contextDate.plus(Integer.valueOf(ctx.num.toString()), ChronoUnit.valueOf(ctx.unit.toString()));
}
@Override
public LocalDate visitMinMaxRule(DateAdjustParser.MinMaxRuleContext ctx) {
LocalDate contextDate = ???; //
LocalDate left = this.visitChildren(ctx.left, contextDate);
LocalDate right = this.visitChildren(ctx.right, contextDate);
if(ctx.type.getText().equals("MIN")) {
return left.compareTo(right) > 0 ? left : right;
} else {
return left.compareTo(right) < 0 ? left : right;
}
}
}
这是我的语法
grammar DateAdjust;
rootNode: offset+;
offset
: num=NUMBER unit=UNIT #OffsetRule
| type=( MIN | MAX ) '(' left=offset ',' right=offset ')' #MinMaxRule
;
UNIT: [dwmy]; //Days Weeks Months Years
NUMBER: [+-]?[0..9]+;
MAX: 'MAX';
MIN: 'MIN';
答案
不是Antlr特有的解决方案,但一个典型的DSL解决方案是使用一个范围内的状态表(也就是符号表)来积累ASTCST行走的结果。
以上是关于在ANTLR中,我应该如何实现一个带有状态上下文的Visitor?的主要内容,如果未能解决你的问题,请参考以下文章
无法在 Antlr4 中实现带有自定义分隔符的 q 引用字符串