123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- package com.sundata.internalevaluation.model.antlr;
- import com.google.common.collect.Range;
- 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<Interval, Integer> 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<Interval, Integer> 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);
- }
- }
- }
- }
|