33import net .marcellperger .mathexpr .*;
44import net .marcellperger .mathexpr .util .Pair ;
55import net .marcellperger .mathexpr .util .Util ;
6+ import net .marcellperger .mathexpr .util .VoidVal ;
7+ import net .marcellperger .mathexpr .util .rs .Option ;
68import net .marcellperger .mathexpr .util .rs .Result ;
79import org .jetbrains .annotations .NotNull ;
810import org .jetbrains .annotations .Nullable ;
1214import java .util .ArrayList ;
1315import java .util .Comparator ;
1416import java .util .List ;
17+ import java .util .Map ;
18+ import java .util .Objects ;
1519import java .util .function .Function ;
20+ import java .util .regex .MatchResult ;
1621import java .util .regex .Matcher ;
1722import 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 }
0 commit comments