Skip to content

Commit 81610d3

Browse files
committed
Consolidated parse parameters into ParserContext.
1 parent f9e6fba commit 81610d3

5 files changed

Lines changed: 276 additions & 244 deletions

File tree

SqlServerSimulator/Extensions.cs

Lines changed: 0 additions & 48 deletions
This file was deleted.

SqlServerSimulator/Parser/Expression.cs

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)