Skip to content

Commit 332a5fc

Browse files
refactor: More progress on converting to Result
1 parent 23c8da5 commit 332a5fc

2 files changed

Lines changed: 107 additions & 15 deletions

File tree

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

Lines changed: 100 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import net.marcellperger.mathexpr.*;
44
import net.marcellperger.mathexpr.util.Pair;
55
import net.marcellperger.mathexpr.util.Util;
6+
import net.marcellperger.mathexpr.util.VoidVal;
7+
import net.marcellperger.mathexpr.util.rs.Option;
68
import net.marcellperger.mathexpr.util.rs.Result;
79
import org.jetbrains.annotations.NotNull;
810
import org.jetbrains.annotations.Nullable;
@@ -12,7 +14,10 @@
1214
import java.util.ArrayList;
1315
import java.util.Comparator;
1416
import java.util.List;
17+
import java.util.Map;
18+
import java.util.Objects;
1519
import java.util.function.Function;
20+
import java.util.regex.MatchResult;
1621
import java.util.regex.Matcher;
1722
import java.util.regex.Pattern;
1823

@@ -37,6 +42,14 @@ public MathSymbol parse() throws ExprParseException {
3742
public MathSymbol parseExpr() throws ExprParseException {
3843
return parseInfixPrecedenceLevel(SymbolInfo.MAX_PRECEDENCE);
3944
}
45+
public Result<MathSymbol, ExprParseException> parseExpr_result() {
46+
// TODO do this better
47+
try {
48+
return Result.newOk(parseInfixPrecedenceLevel(SymbolInfo.MAX_PRECEDENCE));
49+
} catch (ExprParseException e) {
50+
return Result.newErr(e);
51+
}
52+
}
4053

4154
// https://regex101.com/r/2EogTA/1
4255
protected static final Pattern DOUBLE_RE = Pattern.compile("^([+-]?)(\\d*\\.\\d+|\\d+\\.?)(?:[eE]([+-]?\\d+))?");
@@ -63,21 +76,27 @@ public MathSymbol parseExpr() throws ExprParseException {
6376
}
6477
return new BasicDoubleSymbol(value);
6578
}
66-
public @NotNull Result<MathSymbol, Throwable> parseDoubleLiteral_result() {
79+
public @NotNull Result<MathSymbol, ExprParseException> parseDoubleLiteral_result() {
6780
discardWhitespace();
68-
Matcher m = DOUBLE_RE.matcher(strFromHere());
69-
if (!m.lookingAt()) return Result.fromExc(new ExprParseException("Invalid number"));
70-
String s = m.group();
71-
idx += s.length();
72-
double value;
73-
try {
74-
value = Double.parseDouble(s);
75-
} catch (NumberFormatException exc) {
76-
// Technically this should never happen - assuming I've got that regex right
77-
throw new AssertionError(
78-
"There is a problem with the regex, this should've been rejected earlier", exc);
79-
}
80-
return Result.newOk(new BasicDoubleSymbol(value));
81+
return matchNextRegexString(DOUBLE_RE, "Invalid number").andThen(s -> {
82+
try {
83+
return Result.newOk(new BasicDoubleSymbol(Double.parseDouble(s)));
84+
} catch (NumberFormatException exc) {
85+
throw new AssertionError("There is a problem with the regex," +
86+
" this should've been rejected earlier", exc);
87+
}
88+
});
89+
}
90+
91+
public @NotNull Result<MathSymbol, ExprParseException> parseParensOrLiteral_result() {
92+
discardWhitespace();
93+
return peek() == '(' ? parseParens_result() : parseDoubleLiteral_result();
94+
}
95+
96+
public @NotNull Result<MathSymbol, ExprParseException> parseParens_result() {
97+
return advanceExpectNext_ignoreWs_result('(')
98+
.andThen(_c -> parseExpr_result())
99+
.runIfOk(_sym -> advanceExpectNext_ignoreWs_result(')'));
81100
}
82101

83102
public @Nullable MathSymbol parseParensOrLiteral() throws ExprParseException {
@@ -95,6 +114,24 @@ public MathSymbol parseExpr() throws ExprParseException {
95114
return sym;
96115
}
97116

117+
// public Result<MathSymbol, ExprParseException> parseInfixPrecedenceLevel_result(int level) {
118+
// discardWhitespace();
119+
// if(level == 0) return parseParensOrLiteral_result();
120+
// PrecedenceLevelInfo precInfo = SymbolInfo.PREC_LEVELS_INFO.get(level);
121+
// if (precInfo == null) return parseInfixPrecedenceLevel_result(level - 1); // fallthrough empty levels
122+
// return parseInfixPrecedenceLevel_result(level - 1).andThen(left -> switch (precInfo.dirn) {
123+
// case LeftToRight -> parseInfixPrecedenceLevel_LTR(left, precInfo);
124+
// case RightToLeft -> parseInfixPrecedenceLevel_RTL(left, precInfo);
125+
// case null -> parseInfixPrecedenceLevel_noDirn(left, precInfo);
126+
// });
127+
//// MathSymbol left = parseInfixPrecedenceLevel(level - 1);
128+
//// return switch (precInfo.dirn) {
129+
//// case LeftToRight -> parseInfixPrecedenceLevel_LTR(left, precInfo);
130+
//// case RightToLeft -> parseInfixPrecedenceLevel_RTL(left, precInfo);
131+
//// case null -> parseInfixPrecedenceLevel_noDirn(left, precInfo);
132+
//// };
133+
// }
134+
98135
public MathSymbol parseInfixPrecedenceLevel(int level) throws ExprParseException {
99136
discardWhitespace();
100137
if(level == 0) return parseParensOrLiteral();
@@ -108,6 +145,22 @@ public MathSymbol parseInfixPrecedenceLevel(int level) throws ExprParseException
108145
};
109146
}
110147

148+
private Result<MathSymbol, ExprParseException> parseInfixPrecedenceLevel_RTL_result(MathSymbol left, PrecedenceLevelInfo precInfo) {
149+
return Result.fromTry(() -> {
150+
String op;
151+
List<Pair<SymbolInfo, MathSymbol>> otherOps = new ArrayList<>();
152+
while((op = discardMatchesNextAny_optionsSorted_removeWs(precInfo.sortedInfixes)) != null) {
153+
otherOps.add(new Pair<>(
154+
Util.getNotNull(precInfo.infixToSymbolMap, op),
155+
parseInfixPrecedenceLevel(precInfo.precedence - 1)));
156+
}
157+
return otherOps.reversed().stream().reduce((rightpair, leftpair) ->
158+
leftpair.asVars((preOp, argL) ->
159+
new Pair<>(preOp, rightpair.asVars((midOp, argR) -> BinaryOperation.construct(argL, midOp, argR))))
160+
).map(p -> p.asVars((midOp, argR) -> BinaryOperation.construct(left, midOp, argR))).orElse(left);
161+
}, ExprParseException.class);
162+
}
163+
111164
private MathSymbol parseInfixPrecedenceLevel_RTL(MathSymbol left, PrecedenceLevelInfo precInfo) throws ExprParseException {
112165
String op;
113166
List<Pair<SymbolInfo, MathSymbol>> otherOps = new ArrayList<>();
@@ -192,11 +245,43 @@ protected void advanceExpectNext_ignoreWs(char expected) {
192245
discardWhitespace();
193246
advanceExpectNext(expected);
194247
}
248+
protected Result<Character, ExprParseException> advanceExpectNext_ignoreWs_result(char expected) {
249+
discardWhitespace();
250+
return advanceExpectNext_result(expected);
251+
}
252+
protected Result<Character, ExprParseException> advanceExpectNext_result(char expected) {
253+
char actual = advance();
254+
if (actual == expected) return Result.newOk(actual);
255+
return Result.newErr(new ExprParseException("Expected '%c', got '%c'".formatted(expected, actual)));
256+
}
257+
258+
protected Result<MatchResult, ExprParseException> matchNextRegexResult(@NotNull Pattern pat, ExprParseException exc) {
259+
Matcher m = pat.matcher(strFromHere());
260+
if (!m.lookingAt()) return Result.fromExc(exc);
261+
String s = m.group();
262+
idx += s.length();
263+
return Result.newOk(m.toMatchResult());
264+
}
265+
protected Result<MatchResult, ExprParseException> matchNextRegexResult(@NotNull Pattern pat, String exc) {
266+
return matchNextRegexResult(pat, new ExprParseException(exc));
267+
}
268+
protected Result<MatchResult, ExprParseException> matchNextRegexResult(@NotNull Pattern pat) {
269+
return matchNextRegexResult(pat, "Regex should've been matched");
270+
}
271+
protected Result<String, ExprParseException> matchNextRegexString(@NotNull Pattern pat, ExprParseException exc) {
272+
return matchNextRegexResult(pat, exc).map(MatchResult::group);
273+
}
274+
protected Result<String, ExprParseException> matchNextRegexString(@NotNull Pattern pat, String msg) {
275+
return matchNextRegexResult(pat, msg).map(MatchResult::group);
276+
}
277+
protected Result<String, ExprParseException> matchNextRegexString(@NotNull Pattern pat) {
278+
return matchNextRegexResult(pat).map(MatchResult::group);
279+
}
195280

196281
protected boolean matchesNext(@NotNull String expected) {
197282
return src.startsWith(expected, /*start*/idx);
198283
}
199-
284+
200285
private @NotNull List<@NotNull String> sortedByLength(@NotNull List<@NotNull String> arr) {
201286
return arr.stream().sorted(Comparator.comparingInt(String::length).reversed()).toList();
202287
}

src/main/java/net/marcellperger/mathexpr/util/rs/Result.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,13 @@ default Result<T, E> inspectErr(Consumer<? super E> f) {
158158
return mapErr(Util.consumerToIdentityFunc(f));
159159
}
160160

161+
default Result<T, E> runIfOk(Consumer<? super T> f) {
162+
return map(Util.consumerToIdentityFunc(f));
163+
}
164+
default Result<T, E> runIfErr(Consumer<? super E> f) {
165+
return mapErr(Util.consumerToIdentityFunc(f));
166+
}
167+
161168
// .iter()-esque methods: why does Java have SO MANY - one is enough.
162169
default Stream<T> stream() {
163170
return okOpt().map(Ok::value).stream();

0 commit comments

Comments
 (0)