Skip to content

Commit 724abac

Browse files
committed
Implemented bitwise and, or, exclusive or.
1 parent c9b4b50 commit 724abac

3 files changed

Lines changed: 62 additions & 36 deletions

File tree

SqlServerSimulator.Tests/SelectTests.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ public void SelectParameterValue(string commandText, string name, object value)
5858
[DataRow("2 * 2", 4)]
5959
[DataRow("2 / 2", 1)]
6060
[DataRow("2 / 1", 2)]
61+
[DataRow("1 & 3", 1)]
62+
[DataRow("1 | 3", 3)]
63+
[DataRow("1 ^ 3", 2)]
6164
public void Expression(string commandText, object value)
6265
{
6366
using var reader = new Simulation().ExecuteReader($"select {commandText}");

SqlServerSimulator/Parser/Expression.cs

Lines changed: 58 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,18 @@ public static Expression Parse(ParserContext context)
8282
context.MoveNextRequired();
8383
expression = new Divide(expression, Parse(context));
8484
break;
85+
case Operator { Character: '&' }:
86+
context.MoveNextRequired();
87+
expression = new BitwiseAnd(expression, Parse(context));
88+
break;
89+
case Operator { Character: '|' }:
90+
context.MoveNextRequired();
91+
expression = new BitwiseOr(expression, Parse(context));
92+
break;
93+
case Operator { Character: '^' }:
94+
context.MoveNextRequired();
95+
expression = new BitwiseExclusiveOr(expression, Parse(context));
96+
break;
8597

8698
case Operator { Character: '.' }:
8799
{
@@ -225,71 +237,82 @@ public Value(DoubleAtPrefixedString doubleAtPrefixedString)
225237
#endif
226238
}
227239

228-
public sealed class Add(Expression left, Expression right) : Expression
240+
public abstract class TwoSidedExpression(Expression left, Expression right) : Expression
229241
{
230242
private readonly Expression left = left, right = right;
231243

232-
public override object? Run(Func<List<string>, object?> getColumnValue)
233-
{
234-
var leftValue = left.Run(getColumnValue);
235-
var rightValue = right.Run(getColumnValue);
244+
public sealed override object? Run(Func<List<string>, object?> getColumnValue)
245+
=> Run(left.Run(getColumnValue), right.Run(getColumnValue));
236246

237-
return (int)leftValue! + (int)rightValue!; // TODO: Handle varied input types here.
238-
}
247+
protected abstract object? Run(object? left, object? right);
239248

240249
#if DEBUG
241-
public override string ToString() => $"{left} + {right}";
250+
protected abstract char Operator { get; }
251+
252+
public sealed override string ToString() => $"{left} {Operator} {right}";
242253
#endif
243254
}
244255

245-
public sealed class Subtract(Expression left, Expression right) : Expression
256+
public sealed class Add(Expression left, Expression right) : TwoSidedExpression(left, right)
246257
{
247-
private readonly Expression left = left, right = right;
258+
protected override object? Run(object? left, object? right) => (int)left! + (int)right!;
248259

249-
public override object? Run(Func<List<string>, object?> getColumnValue)
250-
{
251-
var leftValue = left.Run(getColumnValue);
252-
var rightValue = right.Run(getColumnValue);
260+
#if DEBUG
261+
protected override char Operator => '+';
262+
#endif
263+
}
253264

254-
return (int)leftValue! - (int)rightValue!; // TODO: Handle varied input types here.
255-
}
265+
public sealed class Subtract(Expression left, Expression right) : TwoSidedExpression(left, right)
266+
{
267+
protected override object? Run(object? left, object? right) => (int)left! - (int)right!;
256268

257269
#if DEBUG
258-
public override string ToString() => $"{left} + {right}";
270+
protected override char Operator => '-';
259271
#endif
260272
}
261273

262-
public sealed class Multiply(Expression left, Expression right) : Expression
274+
public sealed class Multiply(Expression left, Expression right) : TwoSidedExpression(left, right)
263275
{
264-
private readonly Expression left = left, right = right;
276+
protected override object? Run(object? left, object? right) => (int)left! * (int)right!;
265277

266-
public override object? Run(Func<List<string>, object?> getColumnValue)
267-
{
268-
var leftValue = left.Run(getColumnValue);
269-
var rightValue = right.Run(getColumnValue);
278+
#if DEBUG
279+
protected override char Operator => '*';
280+
#endif
281+
}
270282

271-
return (int)leftValue! * (int)rightValue!; // TODO: Handle varied input types here.
272-
}
283+
public sealed class Divide(Expression left, Expression right) : TwoSidedExpression(left, right)
284+
{
285+
protected override object? Run(object? left, object? right) => (int)left! / (int)right!;
273286

274287
#if DEBUG
275-
public override string ToString() => $"{left} + {right}";
288+
protected override char Operator => '/';
276289
#endif
277290
}
278291

279-
public sealed class Divide(Expression left, Expression right) : Expression
292+
public sealed class BitwiseAnd(Expression left, Expression right) : TwoSidedExpression(left, right)
280293
{
281-
private readonly Expression left = left, right = right;
294+
protected override object? Run(object? left, object? right) => (int)left! & (int)right!;
282295

283-
public override object? Run(Func<List<string>, object?> getColumnValue)
284-
{
285-
var leftValue = left.Run(getColumnValue);
286-
var rightValue = right.Run(getColumnValue);
296+
#if DEBUG
297+
protected override char Operator => '&';
298+
#endif
299+
}
287300

288-
return (int)leftValue! / (int)rightValue!; // TODO: Handle varied input types here.
289-
}
301+
public sealed class BitwiseOr(Expression left, Expression right) : TwoSidedExpression(left, right)
302+
{
303+
protected override object? Run(object? left, object? right) => (int)left! | (int)right!;
304+
305+
#if DEBUG
306+
protected override char Operator => '|';
307+
#endif
308+
}
309+
310+
public sealed class BitwiseExclusiveOr(Expression left, Expression right) : TwoSidedExpression(left, right)
311+
{
312+
protected override object? Run(object? left, object? right) => (int)left! ^ (int)right!;
290313

291314
#if DEBUG
292-
public override string ToString() => $"{left} + {right}";
315+
protected override char Operator => '^';
293316
#endif
294317
}
295318

SqlServerSimulator/Parser/Tokenizer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ static class Tokenizer
2525
'-' => ParseMinusOrComment(command, ref index),
2626
'/' => ParseForwardSlashOrComment(command, ref index),
2727
'[' => ParseBracketDelimitedString(command, ref index),
28-
'+' or '*' or '(' or ')' or ',' or '.' or ';' or '=' => new Operator(command, index),
28+
'+' or '*' or '(' or ')' or ',' or '.' or ';' or '=' or '&' or '|' or '^' => new Operator(command, index),
2929
var c => throw SimulatedSqlException.SyntaxErrorNear(c) // Might throw on valid-but-unsupported syntax.
3030
};
3131

0 commit comments

Comments
 (0)