Skip to content

Commit 38540de

Browse files
refactor: Convert back to checked exceptions
Checked exceptions are much more ergonomic has they have first-class language support and syntax, unlike my Result type.
1 parent 332a5fc commit 38540de

1 file changed

Lines changed: 26 additions & 117 deletions

File tree

  • src/main/java/net/marcellperger/mathexpr/parser

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

Lines changed: 26 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
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;
8-
import net.marcellperger.mathexpr.util.rs.Result;
96
import org.jetbrains.annotations.NotNull;
107
import org.jetbrains.annotations.Nullable;
118
import org.jetbrains.annotations.Range;
@@ -14,8 +11,6 @@
1411
import java.util.ArrayList;
1512
import java.util.Comparator;
1613
import java.util.List;
17-
import java.util.Map;
18-
import java.util.Objects;
1914
import java.util.function.Function;
2015
import java.util.regex.MatchResult;
2116
import java.util.regex.Matcher;
@@ -42,96 +37,32 @@ public MathSymbol parse() throws ExprParseException {
4237
public MathSymbol parseExpr() throws ExprParseException {
4338
return parseInfixPrecedenceLevel(SymbolInfo.MAX_PRECEDENCE);
4439
}
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-
}
5340

5441
// https://regex101.com/r/2EogTA/1
5542
protected static final Pattern DOUBLE_RE = Pattern.compile("^([+-]?)(\\d*\\.\\d+|\\d+\\.?)(?:[eE]([+-]?\\d+))?");
56-
@SuppressWarnings("unused") // ignore for now - will fix later with the better error handling
57-
public @NotNull MathSymbol parseDoubleLiteral_exc() throws ExprParseException {
58-
return switch (parseDoubleLiteral_null()) {
59-
case null -> throw new ExprParseException("Couldn't parse double in expression");
60-
case MathSymbol sym -> sym;
61-
};
62-
}
63-
public @Nullable MathSymbol parseDoubleLiteral_null() {
43+
public @NotNull MathSymbol parseDoubleLiteral() throws ExprParseException {
6444
discardWhitespace();
65-
Matcher m = DOUBLE_RE.matcher(strFromHere());
66-
if (!m.lookingAt()) return null;
67-
String s = m.group();
68-
idx += s.length();
69-
double value;
45+
String s = matchNextRegexString(DOUBLE_RE, "Invalid number (double)");
7046
try {
71-
value = Double.parseDouble(s);
72-
} catch (NumberFormatException _exc) {
73-
// Technically this should never happen - assuming I've got that regex right
74-
assert false: "There is a problem with the regex, this should've been rejected earlier";
75-
return null;
47+
return new BasicDoubleSymbol(Double.parseDouble(s));
48+
} catch (NumberFormatException exc) {
49+
throw new AssertionError("There is a problem with the regex," +
50+
" this should've been rejected earlier", exc);
7651
}
77-
return new BasicDoubleSymbol(value);
78-
}
79-
public @NotNull Result<MathSymbol, ExprParseException> parseDoubleLiteral_result() {
80-
discardWhitespace();
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-
});
8952
}
9053

91-
public @NotNull Result<MathSymbol, ExprParseException> parseParensOrLiteral_result() {
54+
public @NotNull MathSymbol parseParensOrLiteral() throws ExprParseException {
9255
discardWhitespace();
93-
return peek() == '(' ? parseParens_result() : parseDoubleLiteral_result();
56+
return peek() == '(' ? parseParens() : parseDoubleLiteral();
9457
}
9558

96-
public @NotNull Result<MathSymbol, ExprParseException> parseParens_result() {
97-
return advanceExpectNext_ignoreWs_result('(')
98-
.andThen(_c -> parseExpr_result())
99-
.runIfOk(_sym -> advanceExpectNext_ignoreWs_result(')'));
100-
}
101-
102-
public @Nullable MathSymbol parseParensOrLiteral() throws ExprParseException {
103-
discardWhitespace();
104-
if(peek() == '(') return parseParens();
105-
// TODO add a better error handling system - don't want to maintain 2 versions of each function
106-
// returning null: +easier to do unions, +no need for verbose try/catch, -no info about errors
107-
return parseDoubleLiteral_null();
108-
}
109-
110-
public @Nullable MathSymbol parseParens() throws ExprParseException {
59+
public MathSymbol parseParens() throws ExprParseException {
11160
advanceExpectNext_ignoreWs('(');
11261
MathSymbol sym = parseExpr();
11362
advanceExpectNext_ignoreWs(')');
11463
return sym;
11564
}
11665

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-
13566
public MathSymbol parseInfixPrecedenceLevel(int level) throws ExprParseException {
13667
discardWhitespace();
13768
if(level == 0) return parseParensOrLiteral();
@@ -145,22 +76,6 @@ public MathSymbol parseInfixPrecedenceLevel(int level) throws ExprParseException
14576
};
14677
}
14778

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-
16479
private MathSymbol parseInfixPrecedenceLevel_RTL(MathSymbol left, PrecedenceLevelInfo precInfo) throws ExprParseException {
16580
String op;
16681
List<Pair<SymbolInfo, MathSymbol>> otherOps = new ArrayList<>();
@@ -237,45 +152,39 @@ protected void discardWhitespace() {
237152
advanceWhile(Character::isWhitespace);
238153
}
239154

240-
protected void advanceExpectNext(char expected) {
155+
protected void advanceExpectNext(char expected) throws ExprParseException {
241156
char actual = advance();
242-
if(actual != expected) throw new ExprParseRtException("Expected '%c', got '%c'".formatted(expected, actual));
157+
if(actual != expected) throw new ExprParseException("Expected '%c', got '%c'".formatted(expected, actual));
243158
}
244-
protected void advanceExpectNext_ignoreWs(char expected) {
159+
protected void advanceExpectNext_ignoreWs(char expected) throws ExprParseException {
245160
discardWhitespace();
246161
advanceExpectNext(expected);
247162
}
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-
}
257163

258-
protected Result<MatchResult, ExprParseException> matchNextRegexResult(@NotNull Pattern pat, ExprParseException exc) {
164+
protected MatchResult matchNextRegexResult(@NotNull Pattern pat, ExprParseException exc) throws ExprParseException {
259165
Matcher m = pat.matcher(strFromHere());
260-
if (!m.lookingAt()) return Result.fromExc(exc);
166+
if (!m.lookingAt()) throw exc;
261167
String s = m.group();
262168
idx += s.length();
263-
return Result.newOk(m.toMatchResult());
169+
return m.toMatchResult();
264170
}
265-
protected Result<MatchResult, ExprParseException> matchNextRegexResult(@NotNull Pattern pat, String exc) {
171+
protected MatchResult matchNextRegexResult(@NotNull Pattern pat, String exc) throws ExprParseException {
266172
return matchNextRegexResult(pat, new ExprParseException(exc));
267173
}
268-
protected Result<MatchResult, ExprParseException> matchNextRegexResult(@NotNull Pattern pat) {
174+
protected MatchResult matchNextRegexResult(@NotNull Pattern pat) throws ExprParseException {
269175
return matchNextRegexResult(pat, "Regex should've been matched");
270176
}
271-
protected Result<String, ExprParseException> matchNextRegexString(@NotNull Pattern pat, ExprParseException exc) {
272-
return matchNextRegexResult(pat, exc).map(MatchResult::group);
177+
@SuppressWarnings("unused")
178+
protected String matchNextRegexString(@NotNull Pattern pat, ExprParseException exc) throws ExprParseException {
179+
return matchNextRegexResult(pat, exc).group();
273180
}
274-
protected Result<String, ExprParseException> matchNextRegexString(@NotNull Pattern pat, String msg) {
275-
return matchNextRegexResult(pat, msg).map(MatchResult::group);
181+
@SuppressWarnings("SameParameterValue")
182+
protected String matchNextRegexString(@NotNull Pattern pat, String msg) throws ExprParseException {
183+
return matchNextRegexResult(pat, msg).group();
276184
}
277-
protected Result<String, ExprParseException> matchNextRegexString(@NotNull Pattern pat) {
278-
return matchNextRegexResult(pat).map(MatchResult::group);
185+
@SuppressWarnings("unused")
186+
protected String matchNextRegexString(@NotNull Pattern pat) throws ExprParseException {
187+
return matchNextRegexResult(pat).group();
279188
}
280189

281190
protected boolean matchesNext(@NotNull String expected) {

0 commit comments

Comments
 (0)