2 // SqlWhereClauseTokenizer.cs
5 // Juraj Skripsky (juraj@hotfeet.ch)
7 // (C) 2004 HotFeet GmbH (http://www.hotfeet.ch)
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System
.Collections
;
39 namespace Mono
.Data
.SqlExpressions
{
40 internal class Tokenizer
: yyParser
.yyInput
{
41 private static readonly IDictionary tokenMap
= new Hashtable ();
42 private static readonly Object
[] tokens
= {
51 Token
.PARENT
, "parent",
67 Token
.SUBSTRING
, "substring",
68 Token
.ISNULL
, "isnull",
71 Token
.CONVERT
, "convert"
81 for (int i
= 0; i
< tokens
.Length
; i
+= 2)
82 tokenMap
.Add (tokens
[i
+ 1], tokens
[i
]);
85 public Tokenizer (string strInput
)
87 input
= strInput
.ToCharArray ();
91 private char Current() {
96 if (pos
+ 1 >= input
.Length
)
98 return input
[pos
+ 1];
101 private void MoveNext() {
105 private void SkipWhiteSpace ()
107 while (Char
.IsWhiteSpace (Current ()))
111 private object ReadNumber ()
113 StringBuilder sb
= new StringBuilder ();
114 sb
.Append (Current ());
117 while (Char
.IsDigit (next
= Next ()) || next
== '.') {
122 string str
= sb
.ToString ();
124 if (str
.IndexOf(".") == -1)
125 return Int64
.Parse (str
);
127 return double.Parse (str
);
130 private char ProcessEscapes(char c
)
151 throw new SyntaxErrorException (String
.Format ("Invalid escape sequence: '\\{0}'.", c
));
157 private string ReadString (char terminator
)
159 StringBuilder sb
= new StringBuilder ();
161 while ((next
= Next ()) != terminator
) {
162 sb
.Append (ProcessEscapes (next
));
167 return sb
.ToString ();
170 private string ReadIdentifier ()
172 StringBuilder sb
= new StringBuilder ();
173 sb
.Append (Current ());
176 while ((next
= Next ()) == '_' || Char
.IsLetterOrDigit (next
) || next
== '\\') {
177 sb
.Append (ProcessEscapes (next
));
181 return sb
.ToString ();
184 private int ParseIdentifier ()
186 string strToken
= ReadIdentifier ();
187 object tokenObj
= tokenMap
[strToken
.ToLower()];
190 return (int)tokenObj
;
193 return Token
.Identifier
;
196 private int ParseToken ()
199 switch (cur
= Current ()) {
201 return Token
.PAROPEN
;
204 return Token
.PARCLOSE
;
237 val
= ReadString (']');
238 return Token
.Identifier
;
241 string date
= ReadString ('#');
242 val
= DateTime
.Parse (date
);
243 return Token
.DateLiteral
;
247 val
= ReadString (cur
);
248 return Token
.StringLiteral
;
251 if (Char
.IsDigit (cur
)) {
253 return Token
.NumberLiteral
;
254 } else if (Char
.IsLetter (cur
) || cur
== '_')
255 return ParseIdentifier ();
258 throw new Exception ("invalid token: '" + cur
+ "'");
261 ///////////////////////////
262 // yyParser.yyInput methods
263 ///////////////////////////
265 /** move on to next token.
266 @return false if positioned beyond tokens.
267 @throws IOException on input error.
269 public bool advance ()
280 } catch(IndexOutOfRangeException
) {
285 /** classifies current token.
286 Should not be called if advance() returned false.
287 @return current %token or single character.
294 /** associated with current token.
295 Should not be called if advance() returned false.
296 @return value for token().
298 public Object
value ()