Skip to content

Commit ba48adf

Browse files
committed
Tokens now always track their position in the source command and aways use this as the source for ToString.
1 parent 1ce55d6 commit ba48adf

20 files changed

Lines changed: 84 additions & 137 deletions

SqlServerSimulator/Parser/Token.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,26 @@
55
/// </summary>
66
abstract class Token
77
{
8-
private protected Token()
8+
/// <summary>
9+
/// The original SQL command that contains this token.
10+
/// </summary>
11+
private readonly string command;
12+
13+
private readonly int index, length;
14+
15+
private protected Token(string command, int index, int length)
916
{
17+
System.Diagnostics.Debug.Assert(index + length <= command.Length);
18+
this.command = command;
19+
this.index = index;
20+
this.length = length;
1021
}
1122

23+
/// <summary>
24+
/// Returns a span containing the portion of the original command this token is based upon.
25+
/// </summary>
26+
public ReadOnlySpan<char> Source => command.AsSpan(index, length);
27+
1228
// This is used for various error messages even though tokens are not directly accessible to user code.
13-
public abstract override string ToString();
29+
public sealed override string ToString() => command.Substring(index, length);
1430
}

SqlServerSimulator/Parser/Tokenizer.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using SqlServerSimulator.Parser.Tokens;
2-
using System.Text;
32

43
namespace SqlServerSimulator.Parser;
54

@@ -23,13 +22,13 @@ static class Tokenizer
2322
'@' => ParseAtOrDoubleAtPrefixedString(command, ref index),
2423
'-' => ParseMinusOrComment(command, ref index),
2524
'[' => ParseBracketDelimitedString(command, ref index),
26-
'+' => new Plus(),
27-
'*' => new Asterisk(),
28-
'(' => new OpenParentheses(),
29-
')' => new CloseParentheses(),
30-
',' => new Comma(),
31-
'.' => new Period(),
32-
';' => new StatementTerminator(),
25+
'+' => new Plus(command, index),
26+
'*' => new Asterisk(command, index),
27+
'(' => new OpenParentheses(command, index),
28+
')' => new CloseParentheses(command, index),
29+
',' => new Comma(command, index),
30+
'.' => new Period(command, index),
31+
';' => new StatementTerminator(command, index),
3332
_ => throw new NotSupportedException($"Simulated tokenizer doesn't know what to do with character '{command[index]}' at index {index}.")
3433
};
3534

@@ -80,7 +79,7 @@ private static Numeric ParseNumeric(string command, ref int index)
8079
break;
8180
}
8281

83-
return new(new StringBuilder(command, start, index - start, index-- - start));
82+
return new(command, start, index-- - start);
8483
}
8584

8685
private static Token ParseAtOrDoubleAtPrefixedString(string command, ref int index)
@@ -110,19 +109,20 @@ private static Token ParseAtOrDoubleAtPrefixedString(string command, ref int ind
110109
break;
111110
}
112111

113-
return doubleAt
114-
? new DoubleAtPrefixedString(new StringBuilder(command, start + 2, index-- - (start + 2), index - (start + 2) - 1))
115-
: new AtPrefixedString(new StringBuilder(command, start + 1, index-- - (start + 1), index - (start + 1) - 1));
112+
return doubleAt ?
113+
new DoubleAtPrefixedString(command, start, index-- - start) :
114+
new AtPrefixedString(command, start, index-- - start);
116115
}
117116

118117
private static Token ParseMinusOrComment(string command, ref int index)
119118
{
119+
var start = index;
120120
if (++index == command.Length)
121-
return new Minus();
121+
return new Minus(command, --index);
122122
if (command[index] != '-')
123123
{
124124
index--;
125-
return new Minus();
125+
return new Minus(command, index);
126126
}
127127

128128
while (++index < command.Length)
@@ -131,11 +131,11 @@ private static Token ParseMinusOrComment(string command, ref int index)
131131
{
132132
case '\r':
133133
case '\n':
134-
return new Comment();
134+
return new Comment(command, start, --index);
135135
}
136136
}
137137

138-
return new Comment();
138+
return new Comment(command, start, --index);
139139
}
140140

141141
private static BracketDelimitedString ParseBracketDelimitedString(string command, ref int index)
@@ -150,6 +150,6 @@ private static BracketDelimitedString ParseBracketDelimitedString(string command
150150
break;
151151
}
152152

153-
return new(new StringBuilder(command, start + 1, index - start - 2, index-- - start - 2));
153+
return new(command.Substring(start + 1, index - start - 2), command, start, index-- - start);
154154
}
155155
}
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
namespace SqlServerSimulator.Parser.Tokens;
22

3-
sealed class Asterisk : Token
3+
sealed class Asterisk(string command, int index) : Token(command, index, 1)
44
{
5-
public override string ToString() => "*";
65
}
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
using System.Text;
2-
1+

32
namespace SqlServerSimulator.Parser.Tokens;
43

5-
sealed class AtPrefixedString(StringBuilder buffer) : StringToken(buffer)
4+
sealed class AtPrefixedString(string command, int index, int length) : StringToken(command, index, length)
65
{
7-
public override string ToString() => $"@{Value}";
6+
public override ReadOnlySpan<char> Span => Source[1..];
87
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
using System.Text;
1+
namespace SqlServerSimulator.Parser.Tokens;
22

3-
namespace SqlServerSimulator.Parser.Tokens;
4-
5-
sealed class BracketDelimitedString(StringBuilder buffer) : Name(buffer)
3+
sealed class BracketDelimitedString(string value, string command, int index, int length) : Name(command, index, length)
64
{
7-
public override string ToString() => $"[{Value}]";
5+
public override ReadOnlySpan<char> Span => Value.AsSpan();
6+
7+
public override string Value { get; } = value;
88
}
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
namespace SqlServerSimulator.Parser.Tokens;
22

3-
sealed class CloseParentheses : Token
3+
sealed class CloseParentheses(string command, int index) : Token(command, index, 1)
44
{
5-
public override string ToString() => ")";
65
}
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
namespace SqlServerSimulator.Parser.Tokens;
22

3-
sealed class Comma : Token
3+
sealed class Comma(string command, int index) : Token(command, index, 1)
44
{
5-
public override string ToString() => ",";
65
}
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
namespace SqlServerSimulator.Parser.Tokens;
22

3-
sealed class Comment : Token
3+
sealed class Comment(string command, int index, int length) : Token(command, index, length)
44
{
5-
public override string ToString() => "/* Comment */";
65
}
Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
using System.Text;
1+
namespace SqlServerSimulator.Parser.Tokens;
22

3-
namespace SqlServerSimulator.Parser.Tokens;
4-
5-
sealed class DoubleAtPrefixedString(StringBuilder buffer) : StringToken(buffer)
3+
sealed class DoubleAtPrefixedString(string command, int index, int length) : StringToken(command, index, length)
64
{
7-
public AtAtKeyword Parse() => !Enum.TryParse<AtAtKeyword>(Value, true, out var result)
8-
? throw new NotSupportedException($"Simulated command processor doesn't know what to do with `{Value}`.")
9-
: result;
5+
public override ReadOnlySpan<char> Span => Source[2..];
106

11-
public override string ToString() => $"@@{Value}";
7+
public AtAtKeyword Parse() => !Enum.TryParse<AtAtKeyword>(Span, true, out var result)
8+
? throw new NotSupportedException($"Simulated command processor doesn't know what to do with `{Span}`.")
9+
: result;
1210
}
1311

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
namespace SqlServerSimulator.Parser.Tokens;
22

3-
sealed class Minus : Token
3+
sealed class Minus(string command, int index) : Token(command, index, 1)
44
{
5-
public override string ToString() => "-";
65
}

0 commit comments

Comments
 (0)