Skip to content

Commit 4ff1ed8

Browse files
Split parseInfixPrecedenceLevel into LR and RTL versions
1 parent 1efbff6 commit 4ff1ed8

File tree

2 files changed

+33
-25
lines changed

2 files changed

+33
-25
lines changed

src/main/java/net/marcellperger/mathexpr/parser/Parser.java

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import net.marcellperger.mathexpr.*;
44
import net.marcellperger.mathexpr.util.Pair;
5+
import net.marcellperger.mathexpr.util.Util;
56
import net.marcellperger.mathexpr.util.UtilCollectors;
67
import org.jetbrains.annotations.NotNull;
78
import org.jetbrains.annotations.Nullable;
@@ -15,7 +16,6 @@
1516
import java.util.stream.Collectors;
1617

1718

18-
1919
public class Parser {
2020
protected String src;
2121
/** Next index to parse */
@@ -92,38 +92,42 @@ public MathSymbol parseInfixPrecedenceLevel(int level) throws ExprParseException
9292
Function.identity()));
9393
String[] infixesToFind = sortedByLength(infixToSymbolInfo.keySet().toArray(String[]::new));
9494
MathSymbol left = parseInfixPrecedenceLevel(level - 1);
95-
String op;
96-
9795
if(dirn == GroupingDirection.RightToLeft) {
98-
// TODO: refactor this mess - 2 separate loops?
99-
// I feel like it should be doable w/ one loop but that may involve risking NullPointerException
100-
// by setting some members of LeftRightBinaryOperation to null
101-
// Actually, this first loop could be common between them if we make the other path 2 loops as well
102-
List<Pair<SymbolInfo, MathSymbol>> otherOps = new ArrayList<>();
96+
return parseInfixPrecedenceLevel_RTL(left, level, infixesToFind, infixToSymbolInfo);
97+
}
98+
return parseInfixPrecedenceLevel_LTR(left, level, infixesToFind, infixToSymbolInfo);
99+
// TODO what if dirn == null? Maybe just disallow the ambiguous case of > 2 operands in same level
100+
}
101+
102+
private MathSymbol parseInfixPrecedenceLevel_RTL(MathSymbol left, int level, String[] infixesToFind,
103+
Map<String, SymbolInfo> infixToSymbolInfo) throws ExprParseException {
104+
// TODO: refactor this mess - 2 separate loops?
105+
// I feel like it should be doable w/ one loop but that may involve risking NullPointerException
106+
// by setting some members of LeftRightBinaryOperation to null
107+
// Actually, this first loop could be common between them if we make the other path 2 loops as well
108+
String op;
109+
List<Pair<SymbolInfo, MathSymbol>> otherOps = new ArrayList<>();
110+
discardWhitespace();
111+
while((op = discardMatchesNextAny_optionsSorted(infixesToFind)) != null) {
112+
otherOps.add(new Pair<>(Util.getNotNull(infixToSymbolInfo, op), parseInfixPrecedenceLevel(level - 1)));
103113
discardWhitespace();
104-
while((op = discardMatchesNextAny_optionsSorted(infixesToFind)) != null) {
105-
SymbolInfo opInfo = Objects.requireNonNull(infixToSymbolInfo.get(op));
106-
MathSymbol sym = parseInfixPrecedenceLevel(level - 1);
107-
otherOps.add(new Pair<>(opInfo, sym));
108-
discardWhitespace();
109-
}
110-
if(otherOps.isEmpty()) return left;
111-
MathSymbol javaIsAnIdiot_left = left;
112-
return otherOps.reversed().stream().reduce((rightpair, leftpair) ->
113-
leftpair.asVars((preOp, argL) ->
114-
new Pair<>(preOp, rightpair.asVars((midOp, argR) -> midOp.getBiConstructor().construct(argL, argR))))
115-
).map(p -> p.asVars((midOp, argR) -> midOp.getBiConstructor().construct(javaIsAnIdiot_left, argR))).orElse(left);
116114
}
115+
return otherOps.reversed().stream().reduce((rightpair, leftpair) ->
116+
leftpair.asVars((preOp, argL) ->
117+
new Pair<>(preOp, rightpair.asVars((midOp, argR) -> midOp.getBiConstructor().construct(argL, argR))))
118+
).map(p -> p.asVars((midOp, argR) -> midOp.getBiConstructor().construct(left, argR))).orElse(left);
119+
}
120+
121+
private MathSymbol parseInfixPrecedenceLevel_LTR(MathSymbol left, int level, String[] infixesToFind,
122+
Map<String, SymbolInfo> infixToSymbolInfo) throws ExprParseException {
123+
String op;
117124
discardWhitespace();
118125
while((op = discardMatchesNextAny_optionsSorted(infixesToFind)) != null) {
119-
SymbolInfo opInfo = Objects.requireNonNull(infixToSymbolInfo.get(op));
120-
MathSymbol right = parseInfixPrecedenceLevel(level - 1);
121-
BinOpBiConstructor ctor = opInfo.getBiConstructor();
122-
left = ctor.construct(left, right);
126+
left = Util.getNotNull(infixToSymbolInfo, op).getBiConstructor()
127+
.construct(left, parseInfixPrecedenceLevel(level - 1));
123128
discardWhitespace();
124129
}
125130
return left;
126-
// TODO what if dirn == null? Maybe just disallow the ambiguous case of > 2 operands in same level
127131
}
128132

129133
// region utils

src/main/java/net/marcellperger/mathexpr/util/Util.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,8 @@ public static<T> T getOnlyItem(@Flow(sourceIsContainer = true) @NotNull Sequence
175175
if(c.size() != 1) throw new CollectionSizeException("Expected collection to have 1 item");
176176
return c.getFirst();
177177
}
178+
179+
public static <K, V> @NotNull V getNotNull(@NotNull Map<K, V> map, K key) {
180+
return Objects.requireNonNull(map.get(key));
181+
}
178182
}

0 commit comments

Comments
 (0)