package com.sundata.internalevaluation.model.antlr; import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.ParseTreeWalker; import java.util.HashMap; import java.util.Map; public class IntervalEvaluator { private final Map intervals = new HashMap<>(); public static void main(String[] args) { String input = """ -> [0,10) -> 10 -> (10,20) -> 20 -> [20,30] -> 30 -> (30,+] -> 40 -> [-,+] -> 100 -> [] -> 0 """; CharStream stream = CharStreams.fromString(input); // 1. 词法分析 IntervalParserLexer lexer = new IntervalParserLexer(stream); CommonTokenStream tokens = new CommonTokenStream(lexer); IntervalParserParser parser = new IntervalParserParser(tokens); IntervalEvaluator evaluator = new IntervalEvaluator(); evaluator.parseAndEvaluate(parser.parse()); // 测试不同的输入值 System.out.println(evaluator.evaluate(15)); // 输出 20 System.out.println(evaluator.evaluate(25)); // 输出 30 System.out.println(evaluator.evaluate(5)); // 输出 10 System.out.println(evaluator.evaluate(null));// 输出 0 } public void parseAndEvaluate(ParseTree tree) { ParseTreeWalker.DEFAULT.walk(new IntervalListener(this), tree); } public int evaluate(Number x) { if (x == null) { return intervals.get(new Interval(true, null, null)); } for (Map.Entry entry : intervals.entrySet()) { Interval interval = entry.getKey(); if (interval.contains(x.doubleValue())) { return entry.getValue(); } } return intervals.get(new Interval(false, null, null)); } private static class Interval { private final boolean empty; private final Double lower; private final Double upper; private final boolean lowerInclusive; private final boolean upperInclusive; public Interval(boolean empty, Double lower, Double upper) { this.empty = empty; this.lower = lower; this.upper = upper; this.lowerInclusive = false; this.upperInclusive = false; } public Interval(boolean lowerInclusive, Double lower, boolean upperInclusive, Double upper) { this.empty = false; this.lower = lower; this.upper = upper; this.lowerInclusive = lowerInclusive; this.upperInclusive = upperInclusive; } public boolean contains(double value) { if (empty) { return false; } boolean lowerValid = lower == null || (lowerInclusive ? value >= lower : value > lower); boolean upperValid = upper == null || (upperInclusive ? value <= upper : value < upper); return lowerValid && upperValid; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Interval interval = (Interval) o; if (empty != interval.empty) return false; if (lower != null ? !lower.equals(interval.lower) : interval.lower != null) return false; if (upper != null ? !upper.equals(interval.upper) : interval.upper != null) return false; if (lowerInclusive != interval.lowerInclusive) return false; return upperInclusive == interval.upperInclusive; } @Override public int hashCode() { int result = (empty ? 1 : 0); result = 31 * result + (lower != null ? lower.hashCode() : 0); result = 31 * result + (upper != null ? upper.hashCode() : 0); result = 31 * result + (lowerInclusive ? 1 : 0); result = 31 * result + (upperInclusive ? 1 : 0); return result; } } private static class IntervalListener extends IntervalParserBaseListener { private final IntervalEvaluator evaluator; public IntervalListener(IntervalEvaluator evaluator) { this.evaluator = evaluator; } @Override public void enterLine(IntervalParserParser.LineContext ctx) { IntervalParserParser.IntervalContext intervalCtx = ctx.interval(); Interval interval = parseInterval(intervalCtx); int value = Integer.parseInt(ctx.value().NUMBER().getText()); evaluator.intervals.put(interval, value); } private Interval parseInterval(IntervalParserParser.IntervalContext ctx) { if (ctx.getChild(0).getText().equals("[")) { if (ctx.getChildCount() == 2) { return new Interval(true, null, null); } boolean lowerInclusive = ctx.getChild(0).getText().equals("["); boolean upperInclusive = ctx.getChild(ctx.getChildCount() - 1).getText().equals("]"); Double lower = ctx.lower != null ? Double.parseDouble(ctx.lower.getText()) : null; Double upper = ctx.upper != null ? Double.parseDouble(ctx.upper.getText()) : null; if (ctx.getChild(1).getText().equals("-")) { return new Interval(false, null, null); } return new Interval(lowerInclusive, lower, upperInclusive, upper); } else { boolean lowerInclusive = ctx.getChild(0).getText().equals("("); boolean upperInclusive = ctx.getChild(ctx.getChildCount() - 1).getText().equals("]"); Double lower = ctx.lower != null ? Double.parseDouble(ctx.lower.getText()) : null; Double upper = ctx.upper != null ? Double.parseDouble(ctx.upper.getText()) : null; if (upper != null && upper.toString().equals("+")) { upper = null; } return new Interval(lowerInclusive, lower, upperInclusive, upper); } } } }