Skip to content

Commit bd0bba2

Browse files
committed
Added subtraction and number sign indicator support.
1 parent c755b89 commit bd0bba2

3 files changed

Lines changed: 76 additions & 21 deletions

File tree

SqlServerSimulator.Tests/SelectTests.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,18 @@ public void SelectParameterValue(string commandText, string name, object value)
4444
}
4545

4646
[TestMethod]
47-
public void Select1Plus1()
47+
[DataRow("1 + 1", 2)]
48+
[DataRow("1 - 1", 0)]
49+
[DataRow("-1", -1)]
50+
[DataRow("- 1", -1)]
51+
[DataRow("+1", 1)]
52+
[DataRow("+ 1", 1)]
53+
public void Expression(string commandText, object value)
4854
{
49-
var result = new Simulation().ExecuteScalar("select 1 + 1");
55+
using var reader = new Simulation().ExecuteReader($"select {commandText}");
5056

51-
Assert.AreEqual(2, result);
57+
Assert.IsTrue(reader.Read());
58+
Assert.AreEqual(value, reader[0]);
5259
}
5360

5461
[TestMethod]

SqlServerSimulator/Parser/Expression.cs

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,44 @@ public static Expression Parse(Simulation simulation, IEnumerator<Token> tokens,
5858
break;
5959
case Plus:
6060
if (expression is null)
61-
throw new NotSupportedException("Simulated expression parser doesn't know how to handle + at the start of an expression.");
61+
{
62+
token = tokens.RequireNext();
63+
expression = Expression.Parse(simulation, tokens, ref token, getVariableValue);
64+
break;
65+
}
66+
67+
token = tokens.RequireNext();
68+
69+
{
70+
var parsed = Parse(simulation, tokens, ref token, getVariableValue);
71+
expression = new Add(expression, parsed);
72+
if (parsed is NamedExpression named)
73+
expression = named.TransferName(expression);
74+
}
75+
76+
tokenWasRead = true;
77+
break;
78+
case Minus:
79+
if (expression is null)
80+
{
81+
token = tokens.RequireNext();
82+
expression = Expression.Parse(simulation, tokens, ref token, getVariableValue);
83+
expression = new Subtract(new Value(0), expression);
84+
break;
85+
}
6286

6387
token = tokens.RequireNext();
6488

65-
var parsed = Parse(simulation, tokens, ref token, getVariableValue);
66-
expression = new Add(expression, parsed);
67-
if (parsed is NamedExpression named)
68-
expression = named.TransferName(expression);
89+
{
90+
var parsed = Parse(simulation, tokens, ref token, getVariableValue);
91+
expression = new Subtract(expression, parsed);
92+
if (parsed is NamedExpression named)
93+
expression = named.TransferName(expression);
94+
}
6995

7096
tokenWasRead = true;
7197
break;
98+
7299
case Period:
73100
if (expression is null)
74101
throw new NotSupportedException("Simulated expression parser doesn't know how to handle '.' at the start of an expression.");
@@ -161,9 +188,11 @@ public Value()
161188
{
162189
}
163190

191+
public Value(object? value) => this.value = value;
192+
164193
public Value(Numeric value)
194+
: this(value.Value)
165195
{
166-
this.value = value.Value;
167196
}
168197

169198
public Value(AtPrefixedString atPrefixed, Func<string, object?> getVariableValue)
@@ -202,6 +231,23 @@ public sealed class Add(Expression left, Expression right) : Expression
202231
return (int)leftValue! + (int)rightValue!; // TODO: Handle varied input types here.
203232
}
204233

234+
#if DEBUG
235+
public override string ToString() => $"{left} + {right}";
236+
#endif
237+
}
238+
239+
public sealed class Subtract(Expression left, Expression right) : Expression
240+
{
241+
private readonly Expression left = left, right = right;
242+
243+
public override object? Run(Func<List<string>, object?> getColumnValue)
244+
{
245+
var leftValue = left.Run(getColumnValue);
246+
var rightValue = right.Run(getColumnValue);
247+
248+
return (int)leftValue! - (int)rightValue!; // TODO: Handle varied input types here.
249+
}
250+
205251
#if DEBUG
206252
public override string ToString() => $"{left} + {right}";
207253
#endif

SqlServerSimulator/Parser/Tokenizer.cs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public static IEnumerable<Token> Tokenize(string? command)
3030

3131
while (commandEnumerator.TryGetNext(out var c, ref index))
3232
{
33+
Switch:
3334
switch (c)
3435
{
3536
default:
@@ -178,22 +179,23 @@ public static IEnumerable<Token> Tokenize(string? command)
178179
continue;
179180
}
180181

181-
switch (c)
182+
if (c == '-')
182183
{
183-
case '-':
184-
while (commandEnumerator.TryGetNext(out c, ref index))
184+
while (commandEnumerator.TryGetNext(out c, ref index))
185+
{
186+
switch (c)
185187
{
186-
switch (c)
187-
{
188-
case '\r':
189-
case '\n':
190-
yield return new Comment();
191-
continue;
192-
}
188+
case '\r':
189+
case '\n':
190+
yield return new Comment();
191+
continue;
193192
}
194-
continue;
193+
}
194+
continue;
195195
}
196-
break;
196+
197+
yield return new Minus();
198+
goto Switch; // Can't immediately think of a better way to do this that doesn't involve new variables.
197199

198200
case '*':
199201
yield return new Asterisk();

0 commit comments

Comments
 (0)