@@ -83,22 +83,20 @@ public MathSymbol parseInfixPrecedenceLevel(int level) throws ExprParseException
8383 PrecedenceLevelInfo precInfo = SymbolInfo .PREC_LEVELS_INFO .get (level );
8484 if (precInfo == null ) return parseInfixPrecedenceLevel (level - 1 );
8585 MathSymbol left = parseInfixPrecedenceLevel (level - 1 );
86- if (precInfo .dirn == GroupingDirection . RightToLeft ) {
87- return parseInfixPrecedenceLevel_RTL (left , precInfo );
88- }
89- return parseInfixPrecedenceLevel_LTR (left , precInfo );
90- // TODO what if dirn == null? Maybe just disallow the ambiguous case of > 2 operands in same level
86+ return switch (precInfo .dirn ) {
87+ case LeftToRight -> parseInfixPrecedenceLevel_LTR (left , precInfo );
88+ case RightToLeft -> parseInfixPrecedenceLevel_RTL ( left , precInfo );
89+ case null -> parseInfixPrecedenceLevel_noDirn (left , precInfo );
90+ };
9191 }
9292
9393 private MathSymbol parseInfixPrecedenceLevel_RTL (MathSymbol left , PrecedenceLevelInfo precInfo ) throws ExprParseException {
9494 String op ;
9595 List <Pair <SymbolInfo , MathSymbol >> otherOps = new ArrayList <>();
96- discardWhitespace ();
97- while ((op = discardMatchesNextAny_optionsSorted (precInfo .sortedInfixes )) != null ) {
96+ while ((op = discardMatchesNextAny_optionsSorted_removeWs (precInfo .sortedInfixes )) != null ) {
9897 otherOps .add (new Pair <>(
9998 Util .getNotNull (precInfo .infixToSymbolMap , op ),
10099 parseInfixPrecedenceLevel (precInfo .precedence - 1 )));
101- discardWhitespace ();
102100 }
103101 return otherOps .reversed ().stream ().reduce ((rightpair , leftpair ) ->
104102 leftpair .asVars ((preOp , argL ) ->
@@ -108,15 +106,24 @@ private MathSymbol parseInfixPrecedenceLevel_RTL(MathSymbol left, PrecedenceLeve
108106
109107 private MathSymbol parseInfixPrecedenceLevel_LTR (MathSymbol left , PrecedenceLevelInfo precInfo ) throws ExprParseException {
110108 String op ;
111- discardWhitespace ();
112- while ((op = discardMatchesNextAny_optionsSorted (precInfo .sortedInfixes )) != null ) {
109+ while ((op = discardMatchesNextAny_optionsSorted_removeWs (precInfo .sortedInfixes )) != null ) {
113110 left = BinaryOperation .construct (
114111 left , Util .getNotNull (precInfo .infixToSymbolMap , op ), parseInfixPrecedenceLevel (precInfo .precedence - 1 ));
115- discardWhitespace ();
116112 }
117113 return left ;
118114 }
119115
116+ private MathSymbol parseInfixPrecedenceLevel_noDirn (MathSymbol left , PrecedenceLevelInfo precInfo ) throws ExprParseException {
117+ String op ;
118+ if ((op = discardMatchesNextAny_optionsSorted_removeWs (precInfo .sortedInfixes )) == null ) return left ;
119+ MathSymbol result = BinaryOperation .construct (
120+ left , Util .getNotNull (precInfo .infixToSymbolMap , op ), parseInfixPrecedenceLevel (precInfo .precedence - 1 ));
121+ if (matchesNextAny_optionsSorted_removeWs (precInfo .sortedInfixes ) != null ) {
122+ throw new ExprParseException ("Error: parens are required for precedence levels without a GroupingDirection" );
123+ }
124+ return result ;
125+ }
126+
120127 // region utils
121128 protected CharSequence strFromHere () {
122129 return CharBuffer .wrap (src , idx , src .length ());
@@ -175,11 +182,19 @@ protected boolean matchesNext(@NotNull String expected) {
175182 private @ Nullable String matchesNextAny_optionsSorted (@ NotNull List <@ NotNull String > expected ) {
176183 return expected .stream ().filter (this ::matchesNext ).findFirst ().orElse (null );
177184 }
185+ private @ Nullable String matchesNextAny_optionsSorted_removeWs (@ NotNull List <@ NotNull String > expected ) {
186+ discardWhitespace ();
187+ return matchesNextAny_optionsSorted (expected );
188+ }
178189 private @ Nullable String discardMatchesNextAny_optionsSorted (@ NotNull List <@ NotNull String > expected ) {
179190 String s = matchesNextAny_optionsSorted (expected );
180191 if (s != null ) discardN (s .length ());
181192 return s ;
182193 }
194+ private @ Nullable String discardMatchesNextAny_optionsSorted_removeWs (@ NotNull List <@ NotNull String > expected ) {
195+ discardWhitespace ();
196+ return discardMatchesNextAny_optionsSorted (expected );
197+ }
183198 @ SuppressWarnings ("unused" )
184199 protected @ Nullable String matchesNextAny (@ NotNull List <@ NotNull String > expected ) {
185200 // Try to longer ones first, then shorter ones.
0 commit comments