Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
XPathScanner.cs
Go to the documentation of this file.
2
3internal sealed class XPathScanner
4{
5 private readonly string _xpathExpr;
6
7 private int _curIndex;
8
9 private char _curChar;
10
11 private LexKind _kind;
12
13 private string _name;
14
15 private string _prefix;
16
17 private string _stringValue;
18
19 private bool _canBeFunction;
20
21 private int _lexStart;
22
23 private int _prevLexEnd;
24
26
28
29 public string Source => _xpathExpr;
30
31 public LexKind Kind => _kind;
32
33 public int LexStart => _lexStart;
34
35 public int LexSize => _curIndex - _lexStart;
36
37 public int PrevLexEnd => _prevLexEnd;
38
39 public string Name => _name;
40
41 public string Prefix => _prefix;
42
43 public string RawValue
44 {
45 get
46 {
47 if (_kind == LexKind.Eof)
48 {
49 return LexKindToString(_kind);
50 }
51 return _xpathExpr.Substring(_lexStart, _curIndex - _lexStart);
52 }
53 }
54
55 public string StringValue => _stringValue;
56
58
59 public XPathAxis Axis => _axis;
60
61 public XPathScanner(string xpathExpr)
62 : this(xpathExpr, 0)
63 {
64 }
65
66 public XPathScanner(string xpathExpr, int startFrom)
67 {
69 _kind = LexKind.Unknown;
71 NextLex();
72 }
73
74 private void SetSourceIndex(int index)
75 {
76 _curIndex = index - 1;
77 NextChar();
78 }
79
80 private void NextChar()
81 {
82 _curIndex++;
83 if (_curIndex < _xpathExpr.Length)
84 {
86 }
87 else
88 {
89 _curChar = '\0';
90 }
91 }
92
93 private void SkipSpace()
94 {
96 {
97 NextChar();
98 }
99 }
100
101 private static bool IsAsciiDigit(char ch)
102 {
103 return (uint)(ch - 48) <= 9u;
104 }
105
106 public void NextLex()
107 {
110 SkipSpace();
112 switch (_curChar)
113 {
114 case '\0':
115 _kind = LexKind.Eof;
116 return;
117 case '$':
118 case '(':
119 case ')':
120 case ',':
121 case '@':
122 case '[':
123 case ']':
124 case '}':
126 NextChar();
127 return;
128 case '.':
129 NextChar();
130 if (_curChar == '.')
131 {
132 _kind = LexKind.DotDot;
133 NextChar();
134 return;
135 }
137 {
139 goto case '0';
140 }
141 _kind = LexKind.Dot;
142 return;
143 case ':':
144 NextChar();
145 if (_curChar == ':')
146 {
147 _kind = LexKind.ColonColon;
148 NextChar();
149 }
150 else
151 {
152 _kind = LexKind.Unknown;
153 }
154 return;
155 case '*':
156 _kind = LexKind.Star;
157 NextChar();
158 CheckOperator(star: true);
159 return;
160 case '/':
161 NextChar();
162 if (_curChar == '/')
163 {
164 _kind = LexKind.SlashSlash;
165 NextChar();
166 }
167 else
168 {
169 _kind = LexKind.Slash;
170 }
171 return;
172 case '|':
173 _kind = LexKind.Union;
174 NextChar();
175 return;
176 case '+':
177 _kind = LexKind.Plus;
178 NextChar();
179 return;
180 case '-':
181 _kind = LexKind.Minus;
182 NextChar();
183 return;
184 case '=':
185 _kind = LexKind.Eq;
186 NextChar();
187 return;
188 case '!':
189 NextChar();
190 if (_curChar == '=')
191 {
192 _kind = LexKind.Ne;
193 NextChar();
194 }
195 else
196 {
197 _kind = LexKind.Unknown;
198 }
199 return;
200 case '<':
201 NextChar();
202 if (_curChar == '=')
203 {
204 _kind = LexKind.Le;
205 NextChar();
206 }
207 else
208 {
209 _kind = LexKind.Lt;
210 }
211 return;
212 case '>':
213 NextChar();
214 if (_curChar == '=')
215 {
216 _kind = LexKind.Ge;
217 NextChar();
218 }
219 else
220 {
221 _kind = LexKind.Gt;
222 }
223 return;
224 case '"':
225 case '\'':
226 _kind = LexKind.String;
227 ScanString();
228 return;
229 case '0':
230 case '1':
231 case '2':
232 case '3':
233 case '4':
234 case '5':
235 case '6':
236 case '7':
237 case '8':
238 case '9':
239 _kind = LexKind.Number;
240 ScanNumber();
241 return;
242 }
244 {
245 _kind = LexKind.Name;
246 _name = ScanNCName();
247 _prefix = string.Empty;
248 _canBeFunction = false;
249 _axis = XPathAxis.Unknown;
250 bool flag = false;
251 int curIndex = _curIndex;
252 if (_curChar == ':')
253 {
254 NextChar();
255 if (_curChar == ':')
256 {
257 NextChar();
258 flag = true;
260 }
261 else if (_curChar == '*')
262 {
263 NextChar();
264 _prefix = _name;
265 _name = "*";
266 }
268 {
269 _prefix = _name;
270 _name = ScanNCName();
272 SkipSpace();
273 _canBeFunction = _curChar == '(';
275 }
276 else
277 {
279 }
280 }
281 else
282 {
283 SkipSpace();
284 if (_curChar == ':')
285 {
286 NextChar();
287 if (_curChar == ':')
288 {
289 NextChar();
290 flag = true;
291 }
293 }
294 else
295 {
296 _canBeFunction = _curChar == '(';
297 }
298 }
299 if (!CheckOperator(star: false) && flag)
300 {
301 _axis = CheckAxis();
302 }
303 }
304 else
305 {
306 _kind = LexKind.Unknown;
307 NextChar();
308 }
309 }
310
311 private bool CheckOperator(bool star)
312 {
313 LexKind kind;
314 if (star)
315 {
316 kind = LexKind.Multiply;
317 }
318 else
319 {
320 if (_prefix.Length != 0 || _name.Length > 3)
321 {
322 return false;
323 }
324 switch (_name)
325 {
326 case "or":
327 kind = LexKind.Or;
328 break;
329 case "and":
330 kind = LexKind.And;
331 break;
332 case "div":
333 kind = LexKind.Divide;
334 break;
335 case "mod":
336 kind = LexKind.Modulo;
337 break;
338 default:
339 return false;
340 }
341 }
342 if (_prevKind <= LexKind.Union)
343 {
344 return false;
345 }
346 switch (_prevKind)
347 {
348 case LexKind.ColonColon:
349 case LexKind.SlashSlash:
350 case LexKind.Dollar:
351 case LexKind.LParens:
352 case LexKind.Comma:
353 case LexKind.Slash:
354 case LexKind.At:
355 case LexKind.LBracket:
356 return false;
357 default:
358 _kind = kind;
359 return true;
360 }
361 }
362
364 {
365 _kind = LexKind.Axis;
366 switch (_name)
367 {
368 case "ancestor":
369 return XPathAxis.Ancestor;
370 case "ancestor-or-self":
371 return XPathAxis.AncestorOrSelf;
372 case "attribute":
373 return XPathAxis.Attribute;
374 case "child":
375 return XPathAxis.Child;
376 case "descendant":
377 return XPathAxis.Descendant;
378 case "descendant-or-self":
379 return XPathAxis.DescendantOrSelf;
380 case "following":
381 return XPathAxis.Following;
382 case "following-sibling":
383 return XPathAxis.FollowingSibling;
384 case "namespace":
385 return XPathAxis.Namespace;
386 case "parent":
387 return XPathAxis.Parent;
388 case "preceding":
389 return XPathAxis.Preceding;
390 case "preceding-sibling":
391 return XPathAxis.PrecedingSibling;
392 case "self":
393 return XPathAxis.Self;
394 default:
395 _kind = LexKind.Name;
396 return XPathAxis.Unknown;
397 }
398 }
399
400 private void ScanNumber()
401 {
402 while (IsAsciiDigit(_curChar))
403 {
404 NextChar();
405 }
406 if (_curChar == '.')
407 {
408 NextChar();
409 while (IsAsciiDigit(_curChar))
410 {
411 NextChar();
412 }
413 }
414 if ((_curChar & -33) == 69)
415 {
416 NextChar();
417 if (_curChar == '+' || _curChar == '-')
418 {
419 NextChar();
420 }
421 while (IsAsciiDigit(_curChar))
422 {
423 NextChar();
424 }
426 }
427 }
428
429 private void ScanString()
430 {
431 int num = _curIndex + 1;
432 int num2 = _xpathExpr.IndexOf(_curChar, num);
433 if (num2 < 0)
434 {
437 }
438 _stringValue = _xpathExpr.Substring(num, num2 - num);
439 SetSourceIndex(num2 + 1);
440 }
441
442 private string ScanNCName()
443 {
444 int curIndex = _curIndex;
446 {
447 NextChar();
448 }
449 return _xpathExpr.Substring(curIndex, _curIndex - curIndex);
450 }
451
452 public void PassToken(LexKind t)
453 {
454 CheckToken(t);
455 NextLex();
456 }
457
458 public void CheckToken(LexKind t)
459 {
460 if (_kind != t)
461 {
462 if (t == LexKind.Eof)
463 {
465 }
467 }
468 }
469
470 private string LexKindToString(LexKind t)
471 {
472 if (LexKind.Eof < t)
473 {
474 return char.ToString((char)t);
475 }
476 return t switch
477 {
478 LexKind.Name => "<name>",
479 LexKind.String => "<string literal>",
480 LexKind.Eof => "<eof>",
481 _ => string.Empty,
482 };
483 }
484
489}
static string XPath_EofExpected
Definition SR.cs:1836
static string XPath_ScientificNotation
Definition SR.cs:1830
static string XPath_UnclosedString
Definition SR.cs:1828
static string XPath_TokenExpected
Definition SR.cs:1838
Definition SR.cs:7
static bool IsStartNCNameSingleChar(char ch)
static bool IsNCNameSingleChar(char ch)
static bool IsWhiteSpace(char ch)
XPathCompileException CreateException(string resId, params string[] args)
static bool IsAsciiDigit(char ch)
XPathScanner(string xpathExpr, int startFrom)