@@ -20,14 +20,11 @@ private protected Expression()
2020 /// <summary>
2121 /// Converts the tokens from a command into a single expression.
2222 /// </summary>
23- /// <param name="simulation">Simulation shared context.</param>
24- /// <param name="tokens">The sequence of command tokens. This will be advanced to the end of the expression.</param>
25- /// <param name="token">Retains the most recently provided token from <paramref name="tokens"/>.</param>
26- /// <param name="getVariableValue">Provides the value to any variable included alongside the command.</param>
23+ /// <param name="context">Manages the overall parsing state.</param>
2724 /// <returns>The parsed expression.</returns>
2825 /// <exception cref="SimulatedSqlException">A variety of messages are possible for various problems with the command.</exception>
2926 /// <exception cref="NotSupportedException">A condition was encountered that may be valid but can't currently be parsed.</exception>
30- public static Expression Parse ( Simulation simulation , IEnumerator < Token > tokens , ref Token ? token , Func < string , object ? > getVariableValue )
27+ public static Expression Parse ( ParserContext context )
3128 {
3229 Expression ? expression = null ;
3330 bool tokenWasRead ;
@@ -36,13 +33,13 @@ public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens,
3633 {
3734 tokenWasRead = false ;
3835
39- switch ( token )
36+ switch ( context . Token )
4037 {
4138 case Numeric number :
4239 expression = new Value ( number ) ;
4340 break ;
4441 case AtPrefixedString atPrefixed :
45- expression = new Value ( atPrefixed , getVariableValue ) ;
42+ expression = new Value ( atPrefixed , context ) ;
4643 break ;
4744 case DoubleAtPrefixedString doubleAtPrefixedString :
4845 expression = new Value ( doubleAtPrefixedString ) ;
@@ -51,11 +48,11 @@ public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens,
5148 switch ( reservedKeyword . Keyword )
5249 {
5350 case Keyword . As :
54- if ( expression is null || ! tokens . TryMoveNext ( out token ) || token is not Name alias )
51+ if ( expression is null || ! context . TryMoveNext ( out context . Token ) || context . Token is not Name alias )
5552 throw SimulatedSqlException . SyntaxErrorNearKeyword ( reservedKeyword ) ;
5653
5754 expression = new NamedExpression ( expression , alias . Value ) ;
58- _ = tokens . TryMoveNext ( out token ) ;
55+ _ = context . TryMoveNext ( out context . Token ) ;
5956 return expression ;
6057 case Keyword . From :
6158 if ( expression is null )
@@ -74,15 +71,15 @@ public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens,
7471 case Plus :
7572 if ( expression is null )
7673 {
77- token = tokens . RequireNext ( ) ;
78- expression = Expression . Parse ( simulation , tokens , ref token , getVariableValue ) ;
74+ context . Token = context . RequireNext ( ) ;
75+ expression = Expression . Parse ( context ) ;
7976 break ;
8077 }
8178
82- token = tokens . RequireNext ( ) ;
79+ context . Token = context . RequireNext ( ) ;
8380
8481 {
85- var parsed = Parse ( simulation , tokens , ref token , getVariableValue ) ;
82+ var parsed = Parse ( context ) ;
8683 expression = new Add ( expression , parsed ) ;
8784 if ( parsed is NamedExpression named )
8885 expression = named . TransferName ( expression ) ;
@@ -93,16 +90,16 @@ public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens,
9390 case Minus :
9491 if ( expression is null )
9592 {
96- token = tokens . RequireNext ( ) ;
97- expression = Expression . Parse ( simulation , tokens , ref token , getVariableValue ) ;
93+ context . Token = context . RequireNext ( ) ;
94+ expression = Parse ( context ) ;
9895 expression = new Subtract ( new Value ( 0 ) , expression ) ;
9996 break ;
10097 }
10198
102- token = tokens . RequireNext ( ) ;
99+ context . Token = context . RequireNext ( ) ;
103100
104101 {
105- var parsed = Parse ( simulation , tokens , ref token , getVariableValue ) ;
102+ var parsed = Parse ( context ) ;
106103 expression = new Subtract ( expression , parsed ) ;
107104 if ( parsed is NamedExpression named )
108105 expression = named . TransferName ( expression ) ;
@@ -119,27 +116,27 @@ public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens,
119116 if ( expression is not Reference reference )
120117 throw new NotSupportedException ( "Simulated expression parser doesn't know how to handle '.' here." ) ;
121118
122- reference . AddMultiPartComponent ( tokens . RequireNext < Name > ( ) ) ;
119+ reference . AddMultiPartComponent ( context . RequireNext < Name > ( ) ) ;
123120 }
124121 break ;
125122 case Comma :
126123 case CloseParentheses :
127124 if ( expression is null )
128- throw SimulatedSqlException . SyntaxErrorNear ( token ) ;
125+ throw SimulatedSqlException . SyntaxErrorNear ( context . Token ) ;
129126 return expression ;
130127 case OpenParentheses :
131128 {
132129 if ( expression is not Reference reference )
133- throw SimulatedSqlException . SyntaxErrorNear ( token ) ;
134- token = tokens . RequireNext ( ) ; // Move past (
135- expression = ResolveBuiltIn ( reference . Name , simulation , tokens , ref token , getVariableValue ) ;
136- _ = tokens . TryMoveNext ( out token ) ; // Move past )
130+ throw SimulatedSqlException . SyntaxErrorNear ( context . Token ) ;
131+ context . Token = context . RequireNext ( ) ; // Move past (
132+ expression = ResolveBuiltIn ( reference . Name , context ) ;
133+ _ = context . TryMoveNext ( out context . Token ) ; // Move past )
137134 return expression ;
138135 }
139136 default :
140- throw new NotSupportedException ( $ "Simulated expression parser doesn't know how to handle '{ token } '.") ;
137+ throw new NotSupportedException ( $ "Simulated expression parser doesn't know how to handle '{ context . Token } '.") ;
141138 }
142- } while ( ( tokenWasRead && token is not null ) || tokens . TryMoveNext ( out token ) ) ;
139+ } while ( ( tokenWasRead && context . Token is not null ) || context . TryMoveNext ( out context . Token ) ) ;
143140
144141 return expression ;
145142 }
@@ -155,19 +152,19 @@ public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens,
155152 public abstract override string ToString ( ) ;
156153#endif
157154
158- private static Expression ResolveBuiltIn ( string name , Simulation simulation , IEnumerator < Token > tokens , ref Token ? token , Func < string , object ? > getVariableValue )
155+ private static Expression ResolveBuiltIn ( string name , ParserContext context )
159156 {
160157 Span < char > uppercaseName = stackalloc char [ name . Length ] ;
161158 return name . ToUpperInvariant ( uppercaseName ) switch
162159 {
163160 3 => uppercaseName switch
164161 {
165- "ABS" => new AbsoluteValue ( simulation , tokens , ref token , getVariableValue ) ,
162+ "ABS" => new AbsoluteValue ( context ) ,
166163 _ => null
167164 } ,
168165 10 => uppercaseName switch
169166 {
170- "DATALENGTH" => new DataLength ( simulation , tokens , ref token , getVariableValue ) ,
167+ "DATALENGTH" => new DataLength ( context ) ,
171168 _ => null
172169 } ,
173170 _ => ( Expression ? ) null
@@ -228,9 +225,9 @@ public Value(Numeric value)
228225 {
229226 }
230227
231- public Value ( AtPrefixedString atPrefixed , Func < string , object ? > getVariableValue )
228+ public Value ( AtPrefixedString atPrefixed , ParserContext context )
232229 {
233- this . value = getVariableValue ( atPrefixed . Value ) ;
230+ this . value = context . GetVariableValue ( atPrefixed . Value ) ;
234231 }
235232
236233 public Value ( DoubleAtPrefixedString doubleAtPrefixedString )
@@ -304,12 +301,9 @@ public sealed class Reference(Name name) : Expression
304301 /// <summary>
305302 /// Encapsulates the SQL DATALENGTH command: https://learn.microsoft.com/en-us/sql/t-sql/functions/datalength-transact-sql
306303 /// </summary>
307- public sealed class DataLength : Expression
304+ public sealed class DataLength ( ParserContext context ) : Expression
308305 {
309- private readonly Expression source ;
310-
311- public DataLength ( Simulation simulation , IEnumerator < Token > tokens , ref Token ? token , Func < string , object ? > getVariableValue )
312- => this . source = Expression . Parse ( simulation , tokens , ref token , getVariableValue ) ;
306+ private readonly Expression source = Parse ( context ) ;
313307
314308 public override object ? Run ( Func < List < string > , object ? > getColumnValue ) => source . Run ( getColumnValue ) switch
315309 {
@@ -326,12 +320,9 @@ public DataLength(Simulation simulation, IEnumerator<Token> tokens, ref Token? t
326320 /// <summary>
327321 /// Encapsulates the SQL ABS command: https://learn.microsoft.com/en-us/sql/t-sql/functions/abs-transact-sql
328322 /// </summary>
329- public sealed class AbsoluteValue : Expression
323+ public sealed class AbsoluteValue ( ParserContext context ) : Expression
330324 {
331- private readonly Expression source ;
332-
333- public AbsoluteValue ( Simulation simulation , IEnumerator < Token > tokens , ref Token ? token , Func < string , object ? > getVariableValue )
334- => this . source = Expression . Parse ( simulation , tokens , ref token , getVariableValue ) ;
325+ private readonly Expression source = Parse ( context ) ;
335326
336327 public override object ? Run ( Func < List < string > , object ? > getColumnValue ) => source . Run ( getColumnValue ) switch
337328 {
0 commit comments