/
FormulaSyntax.java
93 lines (68 loc) · 2.86 KB
/
FormulaSyntax.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package de.fluxparticle.sevenguis.gui7cells.formula;
import de.fluxparticle.syntax.parser.ParserHelper;
import de.fluxparticle.syntax.structure.Rule;
import de.fluxparticle.syntax.structure.RuleType;
import de.fluxparticle.syntax.structure.SimpleRule;
import de.fluxparticle.syntax.structure.SingleElement;
import java.util.List;
import java.util.function.Function;
import static de.fluxparticle.sevenguis.gui7cells.formula.Operator.fromString;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.joining;
/**
* Created by sreinck on 18.11.16.
*/
public enum FormulaSyntax implements Rule {
DIGIT("[0-9]", objects -> objects[0].toString()),
NUMBER("+DIGIT ?{'.' +DIGIT}", FormulaSyntax::reduceNumber),
BIG_LETTER("[A-Z]", objects -> objects[0].toString()),
REFERENCE("BIG_LETTER +DIGIT", FormulaSyntax::reduceReference),
BRACKETS("'(' EXPRESSION ')'", objects -> objects[1]),
FACTOR("(REFERENCE|NUMBER|BRACKETS)", objects -> new Operand((Formula) objects[0])),
TERM("FACTOR *{('*'|'/'|'%') FACTOR}", FormulaSyntax::reduceExpression),
EXPRESSION("TERM *{('+'|'-') TERM}", FormulaSyntax::reduceExpression),
EQUATION("'=' EXPRESSION", objects -> new Equation((Expression) objects[1])),
FORMULA("(NUMBER|EQUATION)", objects -> objects[0]);
private final SingleElement[] elements;
private final Function<Object[], Object> reduceFunction;
FormulaSyntax(String s, Function<Object[], Object> reduceFunction) {
SimpleRule rule = ParserHelper.parse(name() + " := " + s + ";");
this.elements = rule.getElements();
this.reduceFunction = reduceFunction;
}
@Override
public RuleType getRuleType() {
return RuleType.SIMPLE;
}
@Override
public Object reduce(Object[] objects) {
return reduceFunction.apply(objects);
}
@Override
public SingleElement[] getElements() {
return elements;
}
private static Object reduceNumber(Object[] objects) {
String s = join(objects[0]) + ofNullable((List) objects[1]).map(l -> "." + join(l.get(1))).orElse("");
double value = Double.parseDouble(s);
return new Number(value);
}
private static Object reduceReference(Object[] objects) {
String s = objects[0].toString() + join(objects[1]);
return new Reference(s);
}
@SuppressWarnings("unchecked")
private static Object reduceExpression(Object[] objects) {
Expression left = (Expression) objects[0];
for (List l : (List<List>) objects[1]) {
Operator op = fromString(l.get(0).toString());
Formula right = (Formula) l.get(1);
left = new Operation(left, op, right);
}
return left;
}
@SuppressWarnings("unchecked")
private static String join(Object o) {
return ((List<String>) o).stream().collect(joining());
}
}