@@ -17,6 +17,13 @@ private protected Expression()
1717 /// </summary>
1818 public virtual string Name => string . Empty ;
1919
20+ /// <summary>
21+ /// The relative precedence of an expression.
22+ /// When two are in scope, the higher one runs first, otherwise they run left-to-right.
23+ /// </summary>
24+ /// <remarks>Reference: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/operator-precedence-transact-sql</remarks>
25+ public virtual byte Precedence => 0 ;
26+
2027 /// <summary>
2128 /// Converts the tokens from a command into a single expression.
2229 /// </summary>
@@ -120,7 +127,7 @@ public static Expression Parse(ParserContext context)
120127 }
121128 }
122129
123- return expression ;
130+ return expression is TwoSidedExpression twoSided ? twoSided . AdjustForPrecedence ( ) : expression ;
124131 }
125132 }
126133
@@ -188,6 +195,8 @@ private sealed class NamedExpression(Expression expression, string name) : Expre
188195
189196 public override string Name => this . name ;
190197
198+ public override byte Precedence => expression . Precedence ;
199+
191200 public override object ? Run ( Func < List < string > , object ? > getColumnValue ) => this . expression . Run ( getColumnValue ) ;
192201
193202#if DEBUG
@@ -237,9 +246,18 @@ public Value(DoubleAtPrefixedString doubleAtPrefixedString)
237246#endif
238247 }
239248
240- public abstract class TwoSidedExpression ( Expression left , Expression right ) : Expression
249+ private abstract class TwoSidedExpression ( Expression left , Expression right ) : Expression
241250 {
242- private readonly Expression left = left , right = right ;
251+ private Expression right = right , left = left ;
252+
253+ public TwoSidedExpression AdjustForPrecedence ( )
254+ {
255+ if ( this . right is not TwoSidedExpression rightTwo || rightTwo . Precedence < this . Precedence )
256+ return this ;
257+
258+ ( rightTwo . left , this . right ) = ( this , rightTwo . left ) ;
259+ return rightTwo ;
260+ }
243261
244262 public sealed override object ? Run ( Func < List < string > , object ? > getColumnValue )
245263 => Run ( left . Run ( getColumnValue ) , right . Run ( getColumnValue ) ) ;
@@ -253,70 +271,84 @@ public abstract class TwoSidedExpression(Expression left, Expression right) : Ex
253271#endif
254272 }
255273
256- public sealed class Add ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
274+ private sealed class Add ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
257275 {
276+ public override byte Precedence => 3 ;
277+
258278 protected override object ? Run ( object ? left , object ? right ) => ( int ) left ! + ( int ) right ! ;
259279
260280#if DEBUG
261281 protected override char Operator => '+' ;
262282#endif
263283 }
264284
265- public sealed class Subtract ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
285+ private sealed class Subtract ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
266286 {
287+ public override byte Precedence => 3 ;
288+
267289 protected override object ? Run ( object ? left , object ? right ) => ( int ) left ! - ( int ) right ! ;
268290
269291#if DEBUG
270292 protected override char Operator => '-' ;
271293#endif
272294 }
273295
274- public sealed class Multiply ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
296+ private sealed class Multiply ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
275297 {
298+ public override byte Precedence => 2 ;
299+
276300 protected override object ? Run ( object ? left , object ? right ) => ( int ) left ! * ( int ) right ! ;
277301
278302#if DEBUG
279303 protected override char Operator => '*' ;
280304#endif
281305 }
282306
283- public sealed class Divide ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
307+ private sealed class Divide ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
284308 {
309+ public override byte Precedence => 2 ;
310+
285311 protected override object ? Run ( object ? left , object ? right ) => ( int ) left ! / ( int ) right ! ;
286312
287313#if DEBUG
288314 protected override char Operator => '/' ;
289315#endif
290316 }
291317
292- public sealed class BitwiseAnd ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
318+ private sealed class BitwiseAnd ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
293319 {
320+ public override byte Precedence => 3 ;
321+
294322 protected override object ? Run ( object ? left , object ? right ) => ( int ) left ! & ( int ) right ! ;
295323
296324#if DEBUG
297325 protected override char Operator => '&' ;
298326#endif
299327 }
300328
301- public sealed class BitwiseOr ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
329+ private sealed class BitwiseOr ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
302330 {
331+ public override byte Precedence => 3 ;
332+
303333 protected override object ? Run ( object ? left , object ? right ) => ( int ) left ! | ( int ) right ! ;
304334
305335#if DEBUG
306336 protected override char Operator => '|' ;
307337#endif
308338 }
309339
310- public sealed class BitwiseExclusiveOr ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
340+ private sealed class BitwiseExclusiveOr ( Expression left , Expression right ) : TwoSidedExpression ( left , right )
311341 {
342+ public override byte Precedence => 3 ;
343+
312344 protected override object ? Run ( object ? left , object ? right ) => ( int ) left ! ^ ( int ) right ! ;
313345
314346#if DEBUG
315347 protected override char Operator => '^' ;
316348#endif
317349 }
318350
319- public sealed class Reference ( Name name ) : Expression
351+ private sealed class Reference ( Name name ) : Expression
320352 {
321353 private readonly List < string > name = [ name . Value ] ;
322354
@@ -334,7 +366,7 @@ public sealed class Reference(Name name) : Expression
334366 /// <summary>
335367 /// Encapsulates the SQL DATALENGTH command: https://learn.microsoft.com/en-us/sql/t-sql/functions/datalength-transact-sql
336368 /// </summary>
337- public sealed class DataLength ( ParserContext context ) : Expression
369+ private sealed class DataLength ( ParserContext context ) : Expression
338370 {
339371 private readonly Expression source = Parse ( context ) ;
340372
@@ -353,7 +385,7 @@ public sealed class DataLength(ParserContext context) : Expression
353385 /// <summary>
354386 /// Encapsulates the SQL ABS command: https://learn.microsoft.com/en-us/sql/t-sql/functions/abs-transact-sql
355387 /// </summary>
356- public sealed class AbsoluteValue ( ParserContext context ) : Expression
388+ private sealed class AbsoluteValue ( ParserContext context ) : Expression
357389 {
358390 private readonly Expression source = Parse ( context ) ;
359391
0 commit comments