11using System . Collections . Frozen ;
22using System . Data . Common ;
3- using System . Diagnostics ;
4- using System . Diagnostics . CodeAnalysis ;
53
64namespace SqlServerSimulator . Parser ;
75
@@ -16,7 +14,7 @@ internal sealed class ParserContext : IDisposable
1614#else
1715 private readonly IEnumerator < Token > tokens ;
1816#endif
19- public Token ? Token ;
17+ public Token ? Token { get ; private set ; }
2018 private readonly FrozenDictionary < string , ( string Name , ( DataType type , object ? Value ) TypeValue ) > variables ;
2119
2220 public ParserContext ( SimulatedDbCommand command )
@@ -54,45 +52,84 @@ public ParserContext(SimulatedDbCommand command)
5452 ? value . TypeValue . Value
5553 : throw new SimulatedSqlException ( $ "Must declare the scalar variable \" @{ name } \" .") ;
5654
55+ /// <summary>
56+ /// Advances <see cref="Token"/> to the next token, if one exists.
57+ /// </summary>
58+ public void MoveNextOptional ( )
59+ {
60+ var enumerator = this . tokens ;
61+ this . Token = enumerator . MoveNext ( ) ? enumerator . Current : null ;
62+ }
5763
5864 /// <summary>
59- /// Moves to the next item in an enumeration (if possible) and transfers <see cref="IEnumerator{T}.Current"/> to <paramref name="current"/>.
65+ /// Returns the next token in the enumeration, or null.
66+ /// Also updates <see cref="Token"/> to the new value.
6067 /// </summary>
61- /// <param name="current">Receives the <see cref="IEnumerator{T}.Current"/> value, or the types default if advancement isn't possible.</param>
62- /// <returns>True if the enumerator was advanced, otherwise false.</returns>
63- public bool TryMoveNext ( [ NotNullWhen ( true ) ] out Token ? current )
68+ /// <returns>The next token if the enumerator was advanced, otherwise null.</returns>
69+ public Token ? GetNextOptional ( )
6470 {
6571 var enumerator = this . tokens ;
66- bool moved ;
67- current = ( moved = enumerator . MoveNext ( ) ) ? enumerator . Current : default ;
68- return moved ;
72+ return this . Token = enumerator . MoveNext ( ) ? enumerator . Current : null ;
6973 }
7074
7175 /// <summary>
7276 /// 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.
7378 /// </summary>
7479 /// <returns>The next token.</returns>
7580 /// <exception cref="SimulatedSqlException">Incorrect syntax near '{token}'.</exception>
76- public Token RequireNext ( )
81+ public Token GetNextRequired ( )
7782 {
7883 var enumerator = this . tokens ;
79- Debug . Assert ( enumerator . Current is not null ) ;
8084 var previous = enumerator . Current ;
81- return enumerator . MoveNext ( ) ? enumerator . Current : throw SimulatedSqlException . SyntaxErrorNear ( previous ) ;
85+ return enumerator . MoveNext ( ) ? this . Token = enumerator . Current : throw SimulatedSqlException . SyntaxErrorNear ( previous ) ;
8286 }
8387
8488 /// <summary>
8589 /// Returns the next token in the enumeration, throwing an exception if the end was reached instead or the token is the wrong type.
90+ /// Also updates <see cref="Token"/> to the new value.
8691 /// </summary>
92+ /// <typeparam name="T">The expected type of the new token.</typeparam>
8793 /// <returns>The next token.</returns>
8894 /// <exception cref="SimulatedSqlException">Incorrect syntax near '{token}'.</exception>
89- public T RequireNext < T > ( )
95+ public T GetNextRequired < T > ( )
9096 where T : Token
9197 {
9298 var enumerator = this . tokens ;
93- Debug . Assert ( enumerator . Current is not null ) ;
9499 var previous = enumerator . Current ;
95- return enumerator . MoveNext ( ) && enumerator . Current is T current ? current : throw SimulatedSqlException . SyntaxErrorNear ( previous ) ;
100+
101+ if ( enumerator . MoveNext ( ) && enumerator . Current is T current )
102+ {
103+ this . Token = current ;
104+ return current ;
105+ }
106+
107+ throw SimulatedSqlException . SyntaxErrorNear ( previous ) ;
108+ }
109+
110+ /// <summary>
111+ /// 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.
112+ /// </summary>
113+ /// <typeparam name="T">The expected type of the new token.</typeparam>
114+ /// <exception cref="SimulatedSqlException">Incorrect syntax near '{token}'.</exception>
115+ public void MoveNextRequired < T > ( )
116+ where T : Token
117+ {
118+ var enumerator = this . tokens ;
119+ var previous = enumerator . Current ;
120+
121+ this . Token = enumerator . MoveNext ( ) && enumerator . Current is T current ? ( Token ) current : throw SimulatedSqlException . SyntaxErrorNear ( previous ) ;
122+ }
123+
124+ /// <summary>
125+ /// Advances <see cref="Token"/> to the next token in the enumeration, throwing an exception if the end was reached instead.
126+ /// </summary>
127+ /// <exception cref="SimulatedSqlException">Incorrect syntax near '{token}'.</exception>
128+ public void MoveNextRequired ( )
129+ {
130+ var enumerator = this . tokens ;
131+ var previous = enumerator . Current ;
132+ this . Token = enumerator . MoveNext ( ) ? enumerator . Current : throw SimulatedSqlException . SyntaxErrorNear ( previous ) ;
96133 }
97134
98135 private bool isDisposed ;
0 commit comments