static Optional<List<Token>> parseAll(String s) { var i = 0; var list = new LinkedList<Token>(); while (i < s.length()) { var r = parse(s, i); if (r.isPresent()) { list.add(r.get().a()); i = r.get().b(); } else { return Optional.empty(); } } return Optional.of(list); }
static Optional<Tuple<Token, Integer>> parse(String s, int p) { var c = s.charAt(p); returnswitch (c) { case'(' -> Optional.of(new Tuple<>(Bracket.LEFT, p + 1)); case')' -> Optional.of(new Tuple<>(Bracket.RIGHT, p + 1)); case'*' -> Optional.of(new Tuple<>(Operator.MULTIPLY, p + 1)); case'/' -> Optional.of(new Tuple<>(Operator.DIVIDED, p + 1)); case'+' -> Optional.of(new Tuple<>(Operator.ADD, p + 1)); case'-' -> Optional.of(new Tuple<>(Operator.MINUS, p + 1)); default -> parseNumber(s, p); }; }
static Optional<Tuple<Token, Integer>> parseNumber(String s, int p) { int i = 0; if (!Character.isDigit(s.charAt(p))){ return Optional.empty(); }
while (p < s.length() && Character.isDigit(s.charAt(p))) { i = i * 10 + (s.charAt(p++) - '0'); } return Optional.of(new Tuple<>(new Number(i), p)); }
接下来是解释部分,左递归消除就不赘述了,简单说下文法:
1 2 3 4 5
expr = term expr1 expr1 = (+/-) term expr1 | ε term = digit | term1 term1 = (*//) digit term1 | ε digit = 整数 | '(' expr ')'
static Optional<Tuple<Double,Integer>> expr(List<Token> list,int p){ var term = term(list, p); return term.flatMap(x ->{ var tuples = expr1(list, x.b()); return tuples.map(xs -> { double s = x.a(); for (var tuple : xs.a()) { switch (tuple.a()) { case ADD -> s += tuple.b(); case MINUS -> s -= tuple.b(); default -> thrownew UnsupportedOperationException(); } } returnnew Tuple<>(s, xs.b()); }); }); }
static Optional<Tuple<List<Tuple<Operator, Double>>, Integer>> expr1(List<Token> list, int p){ var result = new LinkedList<Tuple<Operator,Double>>(); while (p < list.size()) { var token = list.get(p); var term = term(list, p + 1); if(term.isPresent() && (token == Operator.ADD || token == Operator.MINUS)){ result.add(new Tuple<>((Operator)token, term.get().a())); p = p + 2; }else { break; } } return Optional.of(new Tuple<>(result, p)); }
static Optional<Tuple<Double,Integer>> term(List<Token> list,int p){ var digit = digit(list, p); return digit.flatMap(x -> { var tuples = term1(list, x.b()); return tuples.map(xs -> { double s = x.a(); for (Tuple<Operator, Double> tuple : xs.a()) { switch (tuple.a()) { case MULTIPLY -> s *= tuple.b(); case DIVIDED -> s /= tuple.b(); default -> thrownew UnsupportedOperationException(); } } returnnew Tuple<>(s,xs.b()); }); }); }
static Optional<Tuple<List<Tuple<Operator,Double>>,Integer>> term1(List<Token> list,int p){ var result = new LinkedList<Tuple<Operator,Double>>(); while (p < list.size()) { var token = list.get(p); var term = digit(list, p + 1); if(term.isPresent() && (token == Operator.MULTIPLY || token == Operator.DIVIDED)){ result.add(new Tuple<>((Operator)token, term.get().a())); p = p + 2; }else { break; } } return Optional.of(new Tuple<>(result, p)); }
static Optional<Tuple<Double, Integer>> digit(List<Token> list, int p) { if (p < list.size()){ var t = list.get(p); if (t instanceof Number) return Optional.of(new Tuple<>(((double) ((Number) list.get(p)).i()), p + 1)); elseif(t == Bracket.LEFT){ return expr(list, p + 1).flatMap(x -> { if (x.b() < list.size() && list.get(x.b()) == Bracket.RIGHT) { return Optional.of(new Tuple<>(x.a(), x.b() + 1)); }else { return Optional.empty(); } }); } } return Optional.empty(); }
最后返回的是值和字符所在位置的tuple,再加一个包装函数就完工了:
1 2 3 4 5
static Optional<Double> caculate(List<Token> tokens){ var list = new ArrayList<Token>(tokens.size()); list.addAll(tokens); return expr(list,0).map(Tuple::a); }