在ANTLR中,我应该如何实现一个带有状态上下文的Visitor?

问题描述 投票:0回答:1

我想写一个简单的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 antlr4
1个回答
1
投票

不是Antlr特有的解决方案,但一个典型的DSL解决方案是使用一个范围内的状态表(也就是符号表)来积累ASTCST行走的结果。

请看这个 答辩. 另一个存在于: Antlr存储库.

© www.soinside.com 2019 - 2024. All rights reserved.