Skip to content

Commit 23f8eb9

Browse files
committed
Parser advance-then-pass pattern simplified via helper function.
1 parent 23da3b6 commit 23f8eb9

7 files changed

Lines changed: 28 additions & 73 deletions

File tree

SqlServerSimulator/Parser/BooleanExpression.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@ private protected BooleanExpression(Expression left, Expression right)
1616
}
1717

1818
private protected BooleanExpression(Expression left, ParserContext context)
19+
: this(left, Expression.Parse(context.MoveNextRequiredReturnSelf()))
1920
{
20-
this.left = left;
21-
context.MoveNextRequired();
22-
this.right = Expression.Parse(context);
2321
}
2422

2523
public static BooleanExpression Parse(Expression left, ParserContext context) => context.Token switch

SqlServerSimulator/Parser/Expression.cs

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -34,38 +34,18 @@ private protected Expression()
3434
/// <exception cref="NotSupportedException">A condition was encountered that may be valid but can't currently be parsed.</exception>
3535
public static Expression Parse(ParserContext context)
3636
{
37-
Expression expression;
38-
39-
switch (context.Token)
37+
var expression = context.Token switch
4038
{
41-
case Numeric number:
42-
expression = new Value(number.Value);
43-
break;
44-
case AtPrefixedString atPrefixed:
45-
expression = new Value(atPrefixed, context);
46-
break;
47-
case DoubleAtPrefixedString doubleAtPrefixedString:
48-
expression = new Value(doubleAtPrefixedString);
49-
break;
50-
case ReservedKeyword { Keyword: Keyword.Null }:
51-
expression = new Value();
52-
break;
53-
case Name name:
54-
expression = new Reference(name);
55-
break;
56-
case Operator { Character: '+' }:
57-
context.MoveNextRequired();
58-
expression = Expression.Parse(context);
59-
break;
60-
case Operator { Character: '-' }:
61-
expression = new Subtract(new Value(new DataValue(0, DataType.BuiltInDbInt32)), context);
62-
break;
63-
case Operator { Character: '(' }:
64-
expression = new Parenthesized(context);
65-
break;
66-
default:
67-
throw SimulatedSqlException.SyntaxErrorNear(context);
68-
}
39+
Numeric number => new Value(number.Value),
40+
AtPrefixedString atPrefixed => new Value(atPrefixed, context),
41+
DoubleAtPrefixedString doubleAtPrefixedString => new Value(doubleAtPrefixedString),
42+
ReservedKeyword { Keyword: Keyword.Null } => new Value(),
43+
Name name => new Reference(name),
44+
Operator { Character: '+' } => Expression.Parse(context.MoveNextRequiredReturnSelf()),
45+
Operator { Character: '-' } => new Subtract(new Value(new DataValue(0, DataType.BuiltInDbInt32)), context),
46+
Operator { Character: '(' } => new Parenthesized(context),
47+
_ => throw SimulatedSqlException.SyntaxErrorNear(context)
48+
};
6949

7050
while (true)
7151
{

SqlServerSimulator/Parser/Expressions/Parenthesized.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,9 @@
33
/// <summary>
44
/// An expression that's wrapped in parentheses, potentially affecting the order of operations.
55
/// </summary>
6-
internal sealed class Parenthesized : Expression
6+
internal sealed class Parenthesized(ParserContext context) : Expression
77
{
8-
private readonly Expression wrapped;
9-
10-
public Parenthesized(ParserContext context)
11-
{
12-
context.MoveNextRequired();
13-
this.wrapped = Parse(context);
14-
}
8+
private readonly Expression wrapped = Parse(context.MoveNextRequiredReturnSelf());
159

1610
public override DataValue Run(Func<List<string>, DataValue> getColumnValue) => wrapped.Run(getColumnValue);
1711

SqlServerSimulator/Parser/Expressions/TwoSidedExpression.cs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,8 @@
11
namespace SqlServerSimulator.Parser.Expressions;
22

3-
internal abstract class TwoSidedExpression : Expression
3+
internal abstract class TwoSidedExpression(Expression left, ParserContext context) : Expression
44
{
5-
private Expression left, right;
6-
7-
public TwoSidedExpression(Expression left, ParserContext context)
8-
{
9-
this.left = left;
10-
11-
context.MoveNextRequired();
12-
this.right = Parse(context);
13-
}
5+
private Expression left = left, right = Parse(context.MoveNextRequiredReturnSelf());
146

157
public TwoSidedExpression AdjustForPrecedence()
168
{

SqlServerSimulator/Parser/ParserContext.cs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ public void MoveNextOptional()
6464

6565
/// <summary>
6666
/// Returns the next token in the enumeration, or null.
67-
/// Also updates <see cref="Token"/> to the new value.
6867
/// </summary>
6968
/// <returns>The next token if the enumerator was advanced, otherwise null.</returns>
7069
public Token? GetNextOptional()
@@ -74,7 +73,6 @@ public void MoveNextOptional()
7473

7574
/// <summary>
7675
/// Returns the next token in the enumeration, throwing an exception if the end was reached instead.
77-
/// Also updates <see cref="Token"/> to the new value.
7876
/// </summary>
7977
/// <returns>The next token.</returns>
8078
/// <exception cref="SimulatedSqlException">Incorrect syntax near '{token}'.</exception>
@@ -86,7 +84,6 @@ public Token GetNextRequired()
8684

8785
/// <summary>
8886
/// Returns the next token in the enumeration, throwing an exception if the end was reached instead or the token is the wrong type.
89-
/// Also updates <see cref="Token"/> to the new value.
9087
/// </summary>
9188
/// <typeparam name="T">The expected type of the new token.</typeparam>
9289
/// <returns>The next token.</returns>
@@ -100,17 +97,15 @@ public T GetNextRequired<T>()
10097
}
10198

10299
/// <summary>
103-
/// Advances <see cref="Token"/> to the next token in the enumeration, throwing an exception if the end was reached instead or the token is the wrong type.
100+
/// Advances <see cref="Token"/> to the next token in the enumeration, throwing an exception if the end was reached instead.
101+
/// The <see cref="ParserContext"/> used for this call is returned.
104102
/// </summary>
105-
/// <typeparam name="T">The expected type of the new token.</typeparam>
103+
/// <returns>This instance.</returns>
106104
/// <exception cref="SimulatedSqlException">Incorrect syntax near '{token}'.</exception>
107-
public void MoveNextRequired<T>()
108-
where T : Token
105+
public ParserContext MoveNextRequiredReturnSelf()
109106
{
110-
var previous = this.Token;
111-
112-
if (!MoveNext() || this.Token is not T)
113-
throw SimulatedSqlException.SyntaxErrorNear(previous);
107+
this.MoveNextRequired();
108+
return this;
114109
}
115110

116111
/// <summary>

SqlServerSimulator/Parser/Selection.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,13 @@ internal sealed class Selection
2121
/// <exception cref="NotSupportedException">A condition was encountered that may be valid but can't currently be parsed.</exception>
2222
public static Selection Parse(ParserContext context, uint depth)
2323
{
24-
context.MoveNextRequired();
25-
2624
int? topCount = null;
2725

28-
if (context.Token is ReservedKeyword { Keyword: Keyword.Top })
26+
if (context.GetNextRequired() is ReservedKeyword { Keyword: Keyword.Top })
2927
{
30-
context.MoveNextRequired();
31-
32-
var resolvedExpression = Expression.Parse(context).Run(name => throw SimulatedSqlException.ColumnReferenceNotAllowed(name));
28+
var resolvedExpression = Expression
29+
.Parse(context.MoveNextRequiredReturnSelf())
30+
.Run(name => throw SimulatedSqlException.ColumnReferenceNotAllowed(name));
3331
topCount = resolvedExpression.Value is int unboxed ? unboxed : throw SimulatedSqlException.TopFetchRequiresInteger();
3432
}
3533

@@ -157,8 +155,7 @@ [.. expressions.Select(x => x.Run(columnName => getColumnValueFromRow(row, colum
157155
throw SimulatedSqlException.SyntaxErrorNear(context);
158156

159157
case ReservedKeyword { Keyword: Keyword.Where }:
160-
context.MoveNextRequired();
161-
excluders.Add(BooleanExpression.Parse(Expression.Parse(context), context));
158+
excluders.Add(BooleanExpression.Parse(Expression.Parse(context.MoveNextRequiredReturnSelf()), context));
162159
continue;
163160
}
164161

SqlServerSimulator/Simulation.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,7 @@ internal IEnumerable<SimulatedStatementOutcome> CreateResultSetsForCommand(Simul
6666

6767
var nullable = true;
6868

69-
context.MoveNextRequired();
70-
if (context.Token is ReservedKeyword next)
69+
if (context.GetNextRequired() is ReservedKeyword next)
7170
{
7271
switch (next.Keyword)
7372
{

0 commit comments

Comments
 (0)