2 // System.Xml.XPath.XPathScanner
\r
5 // Jason Diamond (jason@injektilo.org)
\r
7 // (C) 2002 Jason Diamond http://injektilo.org/
\r
14 // [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::'
\r
22 // | VariableReference
\r
23 // [29] Literal ::= '"' [^"]* '"'
\r
25 // [30] Number ::= Digits ('.' Digits?)?
\r
27 // [31] Digits ::= [0-9]+
\r
28 // [32] Operator ::= OperatorName
\r
29 // | MultiplyOperator
\r
30 // | '/' | '//' | '|' | '+' | '-' | '=' | '!=' | '<' | '<=' | '>' | '>='
\r
31 // [33] OperatorName ::= 'and' | 'or' | 'mod' | 'div'
\r
32 // [34] MultiplyOperator ::= '*'
\r
33 // [35] FunctionName ::= QName - NodeType
\r
34 // [36] VariableReference ::= '$' QName
\r
35 // [37] NameTest ::= '*'
\r
38 // [38] NodeType ::= 'comment'
\r
40 // | 'processing-instruction'
\r
42 // [39] ExprWhitespace ::= S
\r
44 namespace System.Xml.XPath
\r
46 public enum XPathTokenType
\r
70 public sealed class XPathScanner
\r
72 private string xpath;
\r
74 private XPathTokenType tokenType;
\r
75 private string value;
\r
76 private XPathTokenType precedingTokenType;
\r
78 public XPathScanner (string xpath)
\r
82 tokenType = XPathTokenType.Start;
\r
85 public XPathTokenType TokenType {
\r
91 public string Value {
\r
105 private int Peek ()
\r
107 if (index < xpath.Length)
\r
108 return xpath[index];
\r
112 private int Peek2 ()
\r
114 if (index + 1 < xpath.Length)
\r
115 return xpath[index + 1];
\r
119 private void MoveNext ()
\r
124 private void MovePrevious ()
\r
130 public XPathTokenType Scan ()
\r
132 precedingTokenType = tokenType;
\r
137 tokenType = XPathTokenType.End;
\r
139 } else if (c != ':' && XmlChar.IsFirstNameChar (c)) {
\r
140 StringBuilder builder = new StringBuilder ();
\r
141 builder.Append ((char) c);
\r
142 while (Peek () != ':' && XmlChar.IsNameChar (Peek ())) {
\r
143 builder.Append ((char) Read ());
\r
145 if (Peek () == ':' && Peek2 () != ':') {
\r
147 if (XmlChar.IsFirstNameChar (Peek ())) {
\r
148 builder.Append (':');
\r
149 builder.Append ((char) Read ());
\r
150 while (XmlChar.IsNameChar (Peek ())) {
\r
151 builder.Append ((char) Read ());
\r
153 tokenType = XPathTokenType.NameTest;
\r
154 } else if (Peek () == '*') {
\r
155 builder.Append (':');
\r
156 builder.Append ((char) Read ());
\r
157 tokenType = XPathTokenType.NameTest;
\r
158 value = builder.ToString ();
\r
161 tokenType = XPathTokenType.Error;
\r
165 value = builder.ToString ();
\r
166 if (precedingTokenType != XPathTokenType.Start &&
\r
167 precedingTokenType != XPathTokenType.At &&
\r
168 precedingTokenType != XPathTokenType.ColonColon &&
\r
169 precedingTokenType != XPathTokenType.LeftParen &&
\r
170 precedingTokenType != XPathTokenType.LeftBracket &&
\r
171 precedingTokenType != XPathTokenType.Operator)
\r
172 tokenType = XPathTokenType.Operator;
\r
173 else if (Peek () == '(') {
\r
174 if (value == "comment" ||
\r
175 value == "node" ||
\r
176 value == "processing-instruction" ||
\r
178 tokenType = XPathTokenType.NodeType;
\r
180 tokenType = XPathTokenType.FunctionName;
\r
182 if (Peek () == ':' && Peek2 () == ':')
\r
183 tokenType = XPathTokenType.AxisName;
\r
185 tokenType = XPathTokenType.NameTest;
\r
187 value = builder.ToString ();
\r
191 tokenType = XPathTokenType.LeftParen;
\r
195 tokenType = XPathTokenType.RightParen;
\r
199 tokenType = XPathTokenType.LeftBracket;
\r
202 tokenType = XPathTokenType.RightBracket;
\r
205 if (Peek () != '.') {
\r
206 tokenType = XPathTokenType.Dot;
\r
210 tokenType = XPathTokenType.DotDot;
\r
215 tokenType = XPathTokenType.At;
\r
219 tokenType = XPathTokenType.Comma;
\r
222 if (Peek () == ':') {
\r
224 tokenType = XPathTokenType.ColonColon;
\r
227 tokenType = XPathTokenType.Error;
\r
230 if (precedingTokenType != XPathTokenType.Start &&
\r
231 precedingTokenType != XPathTokenType.At &&
\r
232 precedingTokenType != XPathTokenType.ColonColon &&
\r
233 precedingTokenType != XPathTokenType.LeftParen &&
\r
234 precedingTokenType != XPathTokenType.LeftBracket &&
\r
235 precedingTokenType != XPathTokenType.Operator) {
\r
236 tokenType = XPathTokenType.Operator;
\r
239 tokenType = XPathTokenType.NameTest;
\r
245 tokenType = XPathTokenType.Operator;
\r
246 if (Peek () != '/')
\r