private XPathAxis CheckAxis() { this.kind = LexKind.Axis; switch (name) { case "ancestor": return(XPathAxis.Ancestor); case "ancestor-or-self": return(XPathAxis.AncestorOrSelf); case "attribute": return(XPathAxis.Attribute); case "child": return(XPathAxis.Child); case "descendant": return(XPathAxis.Descendant); case "descendant-or-self": return(XPathAxis.DescendantOrSelf); case "following": return(XPathAxis.Following); case "following-sibling": return(XPathAxis.FollowingSibling); case "namespace": return(XPathAxis.Namespace); case "parent": return(XPathAxis.Parent); case "preceding": return(XPathAxis.Preceding); case "preceding-sibling": return(XPathAxis.PrecedingSibling); case "self": return(XPathAxis.Self); default: this.kind = LexKind.Name; return(XPathAxis.Unknown); } }
public XPathScanner(string xpathExpr, int startFrom) { Debug.Assert(xpathExpr != null); this.xpathExpr = xpathExpr; this.kind = LexKind.Unknown; SetSourceIndex(startFrom); NextLex(); }
// Six possible causes of exceptions in the builder: // 1. Undefined prefix in a node test. // 2. Undefined prefix in a variable reference, or unknown variable. // 3. Undefined prefix in a function call, or unknown function, or wrong number/types of arguments. // 4. Argument of Union operator is not a node-set. // 5. First argument of Predicate is not a node-set. // 6. Argument of Axis is not a node-set. public Node Parse(XPathScanner scanner, IXPathBuilder <Node> builder, LexKind endLex) { Debug.Assert(this.scanner == null && this.builder == null); Debug.Assert(scanner != null && builder != null); Node result = default(Node); this.scanner = scanner; this.builder = builder; this.posInfo.Clear(); try { builder.StartBuild(); result = ParseExpr(); scanner.CheckToken(endLex); } catch (XPathCompileException e) { if (e.queryString == null) { e.queryString = scanner.Source; PopPosInfo(out e.startChar, out e.endChar); } throw; } finally { result = builder.EndBuild(result); #if DEBUG this.builder = null; this.scanner = null; #endif } Debug.Assert(posInfo.Count == 0, "PushPosInfo() and PopPosInfo() calls have been unbalanced"); return(result); }
private void ScanNumber() { Debug.Assert(xmlCharType.IsDigit(curChar)); int start = curIndex; while (xmlCharType.IsDigit(curChar)) { NextChar(); } if (curChar == '.') { NextChar(); while (xmlCharType.IsDigit(curChar)) { NextChar(); } } if ((curChar & (~0x20)) == 'E') { NextChar(); if (curChar == '+' || curChar == '-') { NextChar(); } while (xmlCharType.IsDigit(curChar)) { NextChar(); } throw CreateException(Res.XPath_ScientificNotation); } this.kind = LexKind.Number; this.numberValue = XPathConvert.StringToDouble(xpathExpr.Substring(start, curIndex - start)); }
// May be called for the following tokens: Name, String, Eof, Comma, LParens, RParens, LBracket, RBracket, RBrace private string LexKindToString(LexKind t) { if (!(LexKind.FirstStringable <= t)) { throw new Exception("XPath error: Unexpected xpathExpr = null"); } if (LexKind.LastNonChar < t) { if (!("()[].@,*/$}".IndexOf((char)t) >= 0)) { throw new Exception("XPath error: missing last non char ()[].@,*/$} : " + (char)t); } return(new string((char)t, 1)); } switch (t) { case LexKind.Name: return("<name>"); case LexKind.String: return("<string literal>"); case LexKind.Eof: return("<eof>"); default: Debug.Fail("Unexpected LexKind: " + t.ToString()); return(string.Empty); } }
private void ListAdd(string str, LexKind kind) { if (kind >= LexKind.Symbol00 && kind <= LexKind.Symbol11 && Expansions.ContainsKey(str)) { object o; Expansions.TryGetValue(str, out o); if (o is string) { string so = o as string; o = LexList.Get(so); } if (o is LexList) { for (int i = 0; i < ((LexList)o).Count; i++) { LexToken tok = ((LexList)o)[i]; bool toPrevious = (kind == LexKind.Symbol10 || kind == LexKind.Symbol11) && i == 0; bool toNext = (kind == LexKind.Symbol01 || kind == LexKind.Symbol11) && i == ((LexList)o).Count - 1; ListAddToken(toPrevious, new LexToken(tok), toNext); } } else { LexToken token = new LexToken(o, List, List.Count); List.Add(token); } } else { ListAddToken(kind == LexKind.Symbol10 || kind == LexKind.Symbol11, new LexToken(str, kind, List, List.Count), kind == LexKind.Symbol01 || kind == LexKind.Symbol11); } }
public LexToken(LexToken tok) { Str = tok.Str; Kind = tok.Kind; ErrorLocation = ""; ActualObject = tok.ActualObject; LinkOther = -1; }
private bool CheckOperator(bool star) { LexKind opKind; if (star) { opKind = LexKind.Multiply; } else { Debug.Assert(_prefix != null); Debug.Assert(_name != null); if (_prefix.Length != 0 || _name.Length > 3) { return(false); } switch (_name) { case "or": opKind = LexKind.Or; break; case "and": opKind = LexKind.And; break; case "div": opKind = LexKind.Divide; break; case "mod": opKind = LexKind.Modulo; break; default: return(false); } } // If there is a preceding token and the preceding token is not one of '@', '::', '(', '[', ',' or an Operator, // then a '*' must be recognized as a MultiplyOperator and an NCName must be recognized as an OperatorName. if (_prevKind <= LexKind.LastOperator) { return(false); } switch (_prevKind) { case LexKind.Slash: case LexKind.SlashSlash: case LexKind.At: case LexKind.ColonColon: case LexKind.LParens: case LexKind.LBracket: case LexKind.Comma: case LexKind.Dollar: return(false); } _kind = opKind; return(true); }
/**************************************************************************************************/ /* Location paths and node tests */ /**************************************************************************************************/ private static bool IsStep(LexKind lexKind) { return( lexKind == LexKind.Dot || lexKind == LexKind.DotDot || lexKind == LexKind.At || lexKind == LexKind.Axis || lexKind == LexKind.Star || lexKind == LexKind.Name // NodeTest is also Name ); }
public XPathScanner(string xpathExpr, int startFrom) { if (xpathExpr == null) { throw new Exception("XPath error: Unexpected xpathExpr = null"); } this.xpathExpr = xpathExpr; this.kind = LexKind.Unknown; SetSourceIndex(startFrom); NextLex(); }
private void ScanFraction() { Debug.Assert(xmlCharType.IsDigit(curChar)); int start = curIndex - 1; Debug.Assert(0 <= start && xpathExpr[start] == '.'); while (xmlCharType.IsDigit(curChar)) { NextChar(); } this.kind = LexKind.Number; this.numberValue = XPathConvert.StringToDouble(xpathExpr.Substring(start, curIndex - start)); }
public static bool IsBinaryOperator(LexKind lexKind) { switch (lexKind) { case LexKind.Add: case LexKind.Sub: case LexKind.Mul: case LexKind.Div: return(true); default: return(false); } }
public void CheckToken(LexKind t) { if (kind != t) { if (t == LexKind.Eof) { throw CreateException(Res.XPath_EofExpected, RawValue); } else { throw CreateException(Res.XPath_TokenExpected, LexKindToString(t), RawValue); } } }
public LexToken(object value, List <LexToken> list, int index) { if (value == null) { throw new LexTokenException("LexToken called with a null value."); } Str = value.ToString(); ActualObject = value; Type theType = value.GetType(); if (theType == typeof(double)) { Kind = LexKind.Double; } else if (theType == typeof(int)) { Kind = LexKind.Int; } else if (theType == typeof(float)) { Kind = LexKind.Float; } else if (theType == typeof(long)) { Kind = LexKind.Long; } else if (theType == typeof(bool)) { Kind = LexKind.Bool; } else if (theType == typeof(char)) { Kind = LexKind.Char; Str = "'" + Str + "'"; } else if (value is Type) { Kind = LexKind.Type; Str = ((Type)value).Name; } else if (theType.IsEnum) { Kind = LexKind.Identifier; } else { throw new LexTokenException("LexToken cannot be called with the type of '" + value.GetType().Name + "'"); } }
public void CheckToken(LexKind t) { Debug.Assert(LexKind.FirstStringable <= t); if (_kind != t) { if (t == LexKind.Eof) { throw CreateException(SR.XPath_EofExpected, RawValue); } else { throw CreateException(SR.XPath_TokenExpected, LexKindToString(t), RawValue); } } }
public void CheckToken(LexKind t) { Debug.Assert(LexKind.FirstStringable <= t); if (kind != t) { if (t == LexKind.Eof) { throw EofExpectedException(RawValue); } else { throw TokenExpectedException(LexKindToString(t), RawValue); } } }
private void ScanString() { char endChar = curChar; int start = curIndex + 1; do { if (!NextChar()) { throw CreateException(Res.XPath_UnclosedString); } } while (curChar != endChar); this.kind = LexKind.String; this.stringValue = xpathExpr.Substring(start, curIndex - start); NextChar(); }
public void CheckToken(LexKind t) { if (!(LexKind.FirstStringable <= t)) { throw new Exception("XPath error: Unexpected xpathExpr = null"); } if (kind != t) { if (t == LexKind.Eof) { throw EofExpectedException(RawValue); } else { throw TokenExpectedException(LexKindToString(t), RawValue); } } }
/// <summary> /// Checks that the LexKind of the current token agrees with the parameter. /// If the Index is at one past the last token, then the LexKind of that non-existent token is assumed to be LexKind.End. /// </summary> public void CheckKind(LexKind kind) { if (Index >= TheTopCount) { if (kind != LexKind.End) { TheList[TheTopCount - 1].ThrowException("Expected a token of kind '" + kind + "' here.", this); } } else if (kind == LexKind.End && Index < TheTopCount) { TheList[Index].ThrowException("Expected the end of text here.", this); } else { if (kind != TheList[Index].Kind) { TheList[Index].ThrowException("Expected a token of kind '" + kind + "' here.", this); } } }
// May be called for the following tokens: Name, String, Eof, Comma, LParens, RParens, LBracket, RBracket, RBrace private string LexKindToString(LexKind t) { Debug.Assert(LexKind.FirstStringable <= t); if (LexKind.LastNonChar < t) { Debug.Assert("()[].@,*/$}".IndexOf((char)t) >= 0); return(new string((char)t, 1)); } switch (t) { case LexKind.Name: return("<name>"); case LexKind.String: return("<string literal>"); case LexKind.Eof: return("<eof>"); default: throw new Exception("Unexpected LexKind: " + t.ToString()); } }
public string LexKindToString(LexKind t) { const string OneCharLexemes = ",/@.()[]{}*+-=<>!$|"; if (OneCharLexemes.IndexOf((char)t) >= 0) { return(((char)t).ToString()); } switch (t) { case LexKind.Ne: return("!="); case LexKind.Le: return("<="); case LexKind.Ge: return(">="); case LexKind.DotDot: return(".."); case LexKind.SlashSlash: return("//"); case LexKind.Name: return("<name>"); case LexKind.String: return("<string literal>"); case LexKind.Number: return("<number literal>"); case LexKind.Axis: return("<axis>"); case LexKind.Unknown: return("<unknown>"); case LexKind.Eof: return("<eof>"); default: Debug.Fail("Must not get here"); return(string.Empty); } }
// May be called for the following tokens: Name, String, Eof, Comma, LParens, RParens, LBracket, RBracket, RBrace private static string LexKindToString(LexKind t) { Debug.Assert(LexKind.FirstStringable <= t); if (LexKind.LastNonChar < t) { Debug.Assert("()[].@,*/$}".Contains((char)t)); return(char.ToString((char)t)); } switch (t) { case LexKind.Name: return("<name>"); case LexKind.String: return("<string literal>"); case LexKind.Eof: return("<eof>"); default: Debug.Fail($"Unexpected LexKind: {t}"); return(string.Empty); } }
private bool CheckOperator(bool star) { LexKind opKind; if (star) { opKind = LexKind.Multiply; } else { if (prefix.Length != 0 || name.Length > 3) return false; switch (name) { case "or" : opKind = LexKind.Or; break; case "and": opKind = LexKind.And; break; case "div": opKind = LexKind.Divide; break; case "mod": opKind = LexKind.Modulo; break; default : return false; } } // If there is a preceding token and the preceding token is not one of '@', '::', '(', '[', ',' or an Operator, // then a '*' must be recognized as a MultiplyOperator and an NCName must be recognized as an OperatorName. if (prevKind <= LexKind.LastOperator) return false; switch (prevKind) { case LexKind.Slash: case LexKind.SlashSlash: case LexKind.At: case LexKind.ColonColon: case LexKind.LParens: case LexKind.LBracket: case LexKind.Comma: case LexKind.Dollar: return false; } this.kind = opKind; return true; }
public void PassToken(LexKind t) { CheckToken(t); NextLex(); }
private XPathAxis CheckAxis() { this.kind = LexKind.Axis; switch (name) { case "ancestor" : return XPathAxis.Ancestor; case "ancestor-or-self" : return XPathAxis.AncestorOrSelf; case "attribute" : return XPathAxis.Attribute; case "child" : return XPathAxis.Child; case "descendant" : return XPathAxis.Descendant; case "descendant-or-self" : return XPathAxis.DescendantOrSelf; case "following" : return XPathAxis.Following; case "following-sibling" : return XPathAxis.FollowingSibling; case "namespace" : return XPathAxis.Namespace; case "parent" : return XPathAxis.Parent; case "preceding" : return XPathAxis.Preceding; case "preceding-sibling" : return XPathAxis.PrecedingSibling; case "self" : return XPathAxis.Self; default : this.kind = LexKind.Name; return XPathAxis.Unknown; } }
public void NextLex() { prevLexEnd = curIndex; prevKind = kind; SkipSpace(); lexStart = curIndex; switch (curChar) { case '\0': kind = LexKind.Eof; return; case '(': case ')': case '[': case ']': case '@': case ',': case '$': case '}': kind = (LexKind)curChar; NextChar(); break; case '.': NextChar(); if (curChar == '.') { kind = LexKind.DotDot; NextChar(); } else if (IsAsciiDigit(curChar)) { SetSourceIndex(lexStart); goto case '0'; } else { kind = LexKind.Dot; } break; case ':': NextChar(); if (curChar == ':') { kind = LexKind.ColonColon; NextChar(); } else { kind = LexKind.Unknown; } break; case '*': kind = LexKind.Star; NextChar(); CheckOperator(true); break; case '/': NextChar(); if (curChar == '/') { kind = LexKind.SlashSlash; NextChar(); } else { kind = LexKind.Slash; } break; case '|': kind = LexKind.Union; NextChar(); break; case '+': kind = LexKind.Plus; NextChar(); break; case '-': kind = LexKind.Minus; NextChar(); break; case '=': kind = LexKind.Eq; NextChar(); break; case '!': NextChar(); if (curChar == '=') { kind = LexKind.Ne; NextChar(); } else { kind = LexKind.Unknown; } break; case '<': NextChar(); if (curChar == '=') { kind = LexKind.Le; NextChar(); } else { kind = LexKind.Lt; } break; case '>': NextChar(); if (curChar == '=') { kind = LexKind.Ge; NextChar(); } else { kind = LexKind.Gt; } break; case '"': case '\'': kind = LexKind.String; ScanString(); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': kind = LexKind.Number; ScanNumber(); break; default: this.name = ScanNCName(); if (this.name != null) { kind = LexKind.Name; this.prefix = string.Empty; this.canBeFunction = false; this.axis = XPathAxis.Unknown; bool colonColon = false; int saveSourceIndex = curIndex; // "foo:bar" or "foo:*" -- one lexeme (no spaces allowed) // "foo::" or "foo ::" -- two lexemes, reported as one (AxisName) // "foo:?" or "foo :?" -- lexeme "foo" reported if (curChar == ':') { NextChar(); if (curChar == ':') { // "foo::" -> OperatorName, AxisName NextChar(); colonColon = true; SetSourceIndex(saveSourceIndex); } else { // "foo:bar", "foo:*" or "foo:?" if (curChar == '*') { NextChar(); this.prefix = this.name; this.name = "*"; } else { string ncName = ScanNCName(); if (ncName != null) { this.prefix = this.name; this.name = ncName; // Look ahead for '(' to determine whether QName can be a FunctionName saveSourceIndex = curIndex; SkipSpace(); this.canBeFunction = (curChar == '('); SetSourceIndex(saveSourceIndex); } else { // "foo:?" -> OperatorName, NameTest // Return "foo" and leave ":" to be reported later as an unknown lexeme SetSourceIndex(saveSourceIndex); } } } } else { SkipSpace(); if (curChar == ':') { // "foo ::" or "foo :?" NextChar(); if (curChar == ':') { NextChar(); colonColon = true; } SetSourceIndex(saveSourceIndex); } else { this.canBeFunction = (curChar == '('); } } if (!CheckOperator(false) && colonColon) { this.axis = CheckAxis(); } } else { kind = LexKind.Unknown; NextChar(); } break; } }
public bool NextLex() { this.SkipSpace(); switch (this.CurerntChar) { case '[': case ']': case '|': case '#': case '$': case '(': case ')': case '*': case '+': case ',': case '-': case '=': case '@': this.kind = (LexKind) Convert.ToInt32(this.CurerntChar, CultureInfo.InvariantCulture); this.NextChar(); break; case '!': this.kind = LexKind.Bang; this.NextChar(); if (this.CurerntChar == '=') { this.kind = LexKind.Ne; this.NextChar(); } break; case '"': case '\'': this.kind = LexKind.String; this.stringValue = this.ScanString(); break; case '.': this.kind = LexKind.Dot; this.NextChar(); if (this.CurerntChar != '.') { if (XmlCharType.IsDigit(this.CurerntChar)) { this.kind = LexKind.Number; this.numberValue = this.ScanFraction(); } } else { this.kind = LexKind.DotDot; this.NextChar(); } break; case '/': this.kind = LexKind.Slash; this.NextChar(); if (this.CurerntChar == '/') { this.kind = LexKind.SlashSlash; this.NextChar(); } break; case '<': this.kind = LexKind.Lt; this.NextChar(); if (this.CurerntChar == '=') { this.kind = LexKind.Le; this.NextChar(); } break; case '>': this.kind = LexKind.Gt; this.NextChar(); if (this.CurerntChar == '=') { this.kind = LexKind.Ge; this.NextChar(); } break; case '\0': this.kind = LexKind.Eof; return false; default: if (XmlCharType.IsDigit(this.CurerntChar)) { this.kind = LexKind.Number; this.numberValue = this.ScanNumber(); } else { if (!this.xmlCharType.IsStartNCNameSingleChar(this.CurerntChar)) { throw XPathException.Create("Xp_InvalidToken", this.SourceText); } this.kind = LexKind.Name; this.name = this.ScanName(); this.prefix = string.Empty; if (this.CurerntChar == ':') { this.NextChar(); if (this.CurerntChar != ':') { this.prefix = this.name; if (this.CurerntChar != '*') { if (!this.xmlCharType.IsStartNCNameSingleChar(this.CurerntChar)) { throw XPathException.Create("Xp_InvalidName", this.SourceText); } this.name = this.ScanName(); } else { this.NextChar(); this.name = "*"; } } else { this.NextChar(); this.kind = LexKind.Axe; } } else { this.SkipSpace(); if (this.CurerntChar == ':') { this.NextChar(); if (this.CurerntChar != ':') { throw XPathException.Create("Xp_InvalidName", this.SourceText); } this.NextChar(); this.kind = LexKind.Axe; } } this.SkipSpace(); this.canBeFunction = this.CurerntChar == '('; } break; } return true; }
public bool NextLex() { SkipSpace(); switch (this.CurerntChar) { case '\0': kind = LexKind.Eof; return(false); case ',': case '@': case '(': case ')': case '|': case '*': case '[': case ']': case '+': case '-': case '=': case '#': case '$': kind = (LexKind)Convert.ToInt32(this.CurerntChar); NextChar(); break; case '<': kind = LexKind.Lt; NextChar(); if (this.CurerntChar == '=') { kind = LexKind.Le; NextChar(); } break; case '>': kind = LexKind.Gt; NextChar(); if (this.CurerntChar == '=') { kind = LexKind.Ge; NextChar(); } break; case '!': kind = LexKind.Bang; NextChar(); if (this.CurerntChar == '=') { kind = LexKind.Ne; NextChar(); } break; case '.': kind = LexKind.Dot; NextChar(); if (this.CurerntChar == '.') { kind = LexKind.DotDot; NextChar(); } else if (XmlCharType.IsDigit(this.CurerntChar)) { kind = LexKind.Number; numberValue = ScanFraction(); } break; case '/': kind = LexKind.Slash; NextChar(); if (this.CurerntChar == '/') { kind = LexKind.SlashSlash; NextChar(); } break; case '"': case '\'': this.kind = LexKind.String; this.stringValue = ScanString(); break; default: if (XmlCharType.IsDigit(this.CurerntChar)) { kind = LexKind.Number; numberValue = ScanNumber(); } else if (XmlCharType.IsStartNCNameChar(this.CurerntChar)) { kind = LexKind.Name; this.name = ScanName(); this.prefix = string.Empty; // "foo:bar" is one lexem not three because it doesn't allow spaces in between // We should distinct it from "foo::" and need process "foo ::" as well if (this.CurerntChar == ':') { NextChar(); // can be "foo:bar" or "foo::" if (this.CurerntChar == ':') // "foo::" { NextChar(); kind = LexKind.Axe; } else // "foo:*", "foo:bar" or "foo: " { this.prefix = this.name; if (this.CurerntChar == '*') { NextChar(); this.name = "*"; } else if (XmlCharType.IsStartNCNameChar(this.CurerntChar)) { this.name = ScanName(); } else { throw new XPathException(Res.Xp_InvalidName, SourceText); } } } else { SkipSpace(); if (this.CurerntChar == ':') { NextChar(); // it can be "foo ::" or just "foo :" if (this.CurerntChar == ':') { NextChar(); kind = LexKind.Axe; } else { throw new XPathException(Res.Xp_InvalidName, SourceText); } } } SkipSpace(); this.canBeFunction = (this.CurerntChar == '('); } else { throw new XPathException(Res.Xp_InvalidToken, SourceText); } break; } return(true); }
public bool NextLexeme() { switch (_currChar) { case '\0': _kind = LexKind.Eof; return false; case '(': case ')': case '=': case '/': _kind = (LexKind)Convert.ToInt32(_currChar); NextChar(); break; case '^': NextChar(); if (_currChar == '^' || _currChar == '(' || _currChar == ')') { _kind = LexKind.EscapedData; NextChar(); } else throw new XPointerSyntaxException(Properties.Resources.CircumflexCharMustBeEscaped); break; default: if (Char.IsDigit(_currChar)) { _kind = LexKind.Number; int start = _ptrIndex - 1; int len = 0; while (Char.IsDigit(_currChar)) { NextChar(); len++; } _number = XmlConvert.ToInt32(_ptr.Substring(start, len)); break; } else if (LexUtils.IsStartNameChar(_currChar)) { _kind = LexKind.NCName; _prefix = String.Empty; _ncname = ParseName(); if (_currChar == ':') { //QName? NextChar(); _prefix = _ncname; _kind = LexKind.QName; if (LexUtils.IsStartNCNameChar(_currChar)) _ncname = ParseName(); else throw new XPointerSyntaxException(String.Format(CultureInfo.CurrentCulture, Properties.Resources.InvalidNameToken, _prefix, _currChar)); } _canBeSchemaName = _currChar == '('; break; } else if (LexUtils.IsWhitespace(_currChar)) { _kind = LexKind.Space; while (LexUtils.IsWhitespace(_currChar)) NextChar(); break; } else { _kind = LexKind.EscapedData; break; } } return true; }
public void NextLex() { prevLexEnd = curIndex; prevKind = kind; SkipSpace(); lexStart = curIndex; switch (curChar) { case '\0': kind = LexKind.Eof; return; case '(': case ')': case '[': case ']': case '@': case ',': case '$': case '}': kind = (LexKind)curChar; NextChar(); break; case '.': NextChar(); if (curChar == '.') { kind = LexKind.DotDot; NextChar(); } else if (IsAsciiDigit(curChar)) { SetSourceIndex(lexStart); goto case '0'; } else { kind = LexKind.Dot; } break; case ':': NextChar(); if (curChar == ':') { kind = LexKind.ColonColon; NextChar(); } else { kind = LexKind.Unknown; } break; case '*': kind = LexKind.Star; NextChar(); CheckOperator(true); break; case '/': NextChar(); if (curChar == '/') { kind = LexKind.SlashSlash; NextChar(); } else { kind = LexKind.Slash; } break; case '|': kind = LexKind.Union; NextChar(); break; case '+': kind = LexKind.Plus; NextChar(); break; case '-': kind = LexKind.Minus; NextChar(); break; case '=': kind = LexKind.Eq; NextChar(); break; case '!': NextChar(); if (curChar == '=') { kind = LexKind.Ne; NextChar(); } else { kind = LexKind.Unknown; } break; case '<': NextChar(); if (curChar == '=') { kind = LexKind.Le; NextChar(); } else { kind = LexKind.Lt; } break; case '>': NextChar(); if (curChar == '=') { kind = LexKind.Ge; NextChar(); } else { kind = LexKind.Gt; } break; case '"': case '\'': kind = LexKind.String; ScanString(); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': kind = LexKind.Number; ScanNumber(); break; default: if (xmlCharType.IsStartNCNameSingleChar(curChar) #if XML10_FIFTH_EDITION || xmlCharType.IsNCNameHighSurrogateChar(curChar) #endif ) { kind = LexKind.Name; this.name = ScanNCName(); this.prefix = string.Empty; this.canBeFunction = false; this.axis = XPathAxis.Unknown; bool colonColon = false; int saveSourceIndex = curIndex; // "foo:bar" or "foo:*" -- one lexeme (no spaces allowed) // "foo::" or "foo ::" -- two lexemes, reported as one (AxisName) // "foo:?" or "foo :?" -- lexeme "foo" reported if (curChar == ':') { NextChar(); if (curChar == ':') // "foo::" -> OperatorName, AxisName { NextChar(); colonColon = true; SetSourceIndex(saveSourceIndex); } else // "foo:bar", "foo:*" or "foo:?" { if (curChar == '*') { NextChar(); this.prefix = this.name; this.name = "*"; } else if (xmlCharType.IsStartNCNameSingleChar(curChar) #if XML10_FIFTH_EDITION || xmlCharType.IsNCNameHighSurrogateChar(curChar) #endif ) { this.prefix = this.name; this.name = ScanNCName(); // Look ahead for '(' to determine whether QName can be a FunctionName saveSourceIndex = curIndex; SkipSpace(); this.canBeFunction = (curChar == '('); SetSourceIndex(saveSourceIndex); } else // "foo:?" -> OperatorName, NameTest // Return "foo" and leave ":" to be reported later as an unknown lexeme { SetSourceIndex(saveSourceIndex); } } } else { SkipSpace(); if (curChar == ':') // "foo ::" or "foo :?" { NextChar(); if (curChar == ':') { NextChar(); colonColon = true; } SetSourceIndex(saveSourceIndex); } else { this.canBeFunction = (curChar == '('); } } if (!CheckOperator(false) && colonColon) { this.axis = CheckAxis(); } } else { kind = LexKind.Unknown; NextChar(); } break; } }
public LexToken(string str, LexKind kind, List <LexToken> list, int index) { Str = str; Kind = kind; }
public LexTokenList Analyze() { LexTokenList LexTokens = new LexTokenList(); StringBuilder sb = new StringBuilder(); int Line = 1; for (int i = 0; i < Input.Length; i++) { LexKind kind = LexKind.Terminal; string value = ""; switch (Input[i]) { case '(': kind = LexKind.ParentheseOpen; break; case ')': kind = LexKind.ParentheseClose; break; case '[': kind = LexKind.BracketOpen; break; case ']': kind = LexKind.BracketClose; break; case '{': kind = LexKind.BraceOpen; break; case '}': kind = LexKind.BraceClose; break; case '<': kind = LexKind.ChevronOpen; break; case '>': kind = LexKind.ChevronClose; break; case ':': kind = LexKind.Colon; break; case ';': kind = LexKind.Semicolon; break; case ',': kind = LexKind.Comma; break; case '"': { i++; while (Input[i] != '"') { if (Input[i] == '\\' && Input[i + 1] == '"') { i++; } sb.Append(Input[i]); i++; } value = sb.ToString(); kind = LexKind.String; sb.Clear(); break; } case '=': kind = LexKind.Equals; break; case ' ': // Discard case '\r': case '\t': break; case '\n': Line++; break; case '?': { kind = LexKind.Question; break; } case '!': { kind = LexKind.Exclamation; break; } case '+': { kind = LexKind.Add; break; } case '-': { kind = LexKind.Sub; break; } case '*': { kind = LexKind.Mul; break; } case '/': { if (Input.Length > i + 1 && Input[i + 1] == '/') { i += 2; for (; Input[i] != '\n' && i < Input.Length; i++) { sb.Append(Input[i]); } value = sb.ToString(); kind = LexKind.Comment; sb.Clear(); Line++; } else { kind = LexKind.Div; } break; } default: { if (Char.IsLetterOrDigit(Input[i]) || Input[i] == '.') { while (Input.Length > i && (Char.IsLetterOrDigit(Input[i]) || Input[i] == '.')) { sb.Append(Input[i++]); } i--; } value = sb.ToString(); kind = Identify(value); sb.Clear(); break; } } if (kind != LexKind.Terminal) { LexTokens.Add(new LexToken() { Kind = kind, Value = value, Line = Line }); } } LexTokens.Add(new LexToken() { Kind = LexKind.Terminal }); LexTokens.Add(new LexToken() { Kind = LexKind.EOF }); return(LexTokens); }
public LexToken(string str, LexKind kind, LexList list) : this(str, kind, list.CopyList(), list.Index) { }
public bool NextLex() { prevLexEnd = curIndex; SkipSpace(); lexStart = curIndex; switch (curChar) { case '\0': kind = LexKind.Eof; return false; case ',': case '@': case '(': case ')': case '|': case '*': case '[': case ']': case '+': case '-': case '=': case '#': case '$': case '{': case '}': kind = (LexKind)curChar; NextChar(); break; case '<': kind = LexKind.Lt; NextChar(); if (curChar == '=') { kind = LexKind.Le; NextChar(); } break; case '>': kind = LexKind.Gt; NextChar(); if (curChar == '=') { kind = LexKind.Ge; NextChar(); } break; case '!': kind = LexKind.Bang; NextChar(); if (curChar == '=') { kind = LexKind.Ne; NextChar(); } break; case '.': kind = LexKind.Dot; NextChar(); if (curChar == '.') { kind = LexKind.DotDot; NextChar(); } else if (xmlCharType.IsDigit(curChar)) { ScanFraction(); } break; case '/': kind = LexKind.Slash; NextChar(); if (curChar == '/') { kind = LexKind.SlashSlash; NextChar(); } break; case '"': case '\'': ScanString(); break; default: if (xmlCharType.IsDigit(curChar)) { ScanNumber(); } else if (xmlCharType.IsStartNCNameChar(curChar)) { kind = LexKind.Name; this.name = ScanNCName(); this.prefix = string.Empty; int saveSourceIndex = curIndex; // "foo:bar" is one lexem not three because it doesn't allow spaces in between // We should distinct it from "foo::" and need process "foo ::" as well if (curChar == ':') { NextChar(); // can be "foo:bar" or "foo::" if (curChar == ':') { // "foo::" NextChar(); kind = LexKind.Axis; } else { // "foo:*", "foo:bar" or "foo: " if (curChar == '*') { NextChar(); this.prefix = this.name; this.name = "*"; } else if (xmlCharType.IsStartNCNameChar(curChar)) { this.prefix = this.name; this.name = ScanNCName(); } else { // this lex is something like "foo:?". Let's it be recognized as name "foo" // and leave ":-" to be scaned late as unknown lex. SetSourceIndex(saveSourceIndex); } } } else { SkipSpace(); if (curChar == ':') { NextChar(); // it can be "foo ::" or just "foo :" if (curChar == ':') { NextChar(); kind = LexKind.Axis; } else { // this lex is something like "foo :?". Let's it be recognized as name "foo" // and leave ":-" to be scaned late as unknown lex. SetSourceIndex(saveSourceIndex); } } } // look ahead for '('. I don't want curIndex to be moved by SkipSpace() here to be able to detect presize lexem size. saveSourceIndex = curIndex; SkipSpace(); this.canBeFunction = (curChar == '('); SetSourceIndex(saveSourceIndex); } else { kind = LexKind.Unknown; NextChar(); } break; } return true; }
// May be called for the following tokens: Name, String, Eof, Comma, LParens, RParens, LBracket, RBracket, RBrace private string LexKindToString(LexKind t) { Debug.Assert(LexKind.FirstStringable <= t); if (LexKind.LastNonChar < t) { Debug.Assert("()[].@,*/$}".IndexOf((char)t) >= 0); return new string((char)t, 1); } switch (t) { case LexKind.Name : return "<name>"; case LexKind.String : return "<string literal>"; case LexKind.Eof : return "<eof>"; default: Debug.Fail("Unexpected LexKind: " + t.ToString()); return string.Empty; } }
public void NextLex() { _prevLexEnd = _curIndex; _prevKind = _kind; SkipSpace(); _lexStart = _curIndex; switch (_curChar) { case '\0': _kind = LexKind.Eof; return; case '(': case ')': case '[': case ']': case '@': case ',': case '$': case '}': _kind = (LexKind)_curChar; NextChar(); break; case '.': NextChar(); if (_curChar == '.') { _kind = LexKind.DotDot; NextChar(); } else if (IsAsciiDigit(_curChar)) { SetSourceIndex(_lexStart); goto case '0'; } else { _kind = LexKind.Dot; } break; case ':': NextChar(); if (_curChar == ':') { _kind = LexKind.ColonColon; NextChar(); } else { _kind = LexKind.Unknown; } break; case '*': _kind = LexKind.Star; NextChar(); CheckOperator(true); break; case '/': NextChar(); if (_curChar == '/') { _kind = LexKind.SlashSlash; NextChar(); } else { _kind = LexKind.Slash; } break; case '|': _kind = LexKind.Union; NextChar(); break; case '+': _kind = LexKind.Plus; NextChar(); break; case '-': _kind = LexKind.Minus; NextChar(); break; case '=': _kind = LexKind.Eq; NextChar(); break; case '!': NextChar(); if (_curChar == '=') { _kind = LexKind.Ne; NextChar(); } else { _kind = LexKind.Unknown; } break; case '<': NextChar(); if (_curChar == '=') { _kind = LexKind.Le; NextChar(); } else { _kind = LexKind.Lt; } break; case '>': NextChar(); if (_curChar == '=') { _kind = LexKind.Ge; NextChar(); } else { _kind = LexKind.Gt; } break; case '"': case '\'': _kind = LexKind.String; ScanString(); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': _kind = LexKind.Number; ScanNumber(); break; default: if (_xmlCharType.IsStartNCNameSingleChar(_curChar) #if XML10_FIFTH_EDITION || xmlCharType.IsNCNameHighSurrogateChar(curChar) #endif ) { _kind = LexKind.Name; _name = ScanNCName(); _prefix = string.Empty; _canBeFunction = false; _axis = XPathAxis.Unknown; bool colonColon = false; int saveSourceIndex = _curIndex; // "foo:bar" or "foo:*" -- one lexeme (no spaces allowed) // "foo::" or "foo ::" -- two lexemes, reported as one (AxisName) // "foo:?" or "foo :?" -- lexeme "foo" reported if (_curChar == ':') { NextChar(); if (_curChar == ':') { // "foo::" -> OperatorName, AxisName NextChar(); colonColon = true; SetSourceIndex(saveSourceIndex); } else { // "foo:bar", "foo:*" or "foo:?" if (_curChar == '*') { NextChar(); _prefix = _name; _name = "*"; } else if (_xmlCharType.IsStartNCNameSingleChar(_curChar) #if XML10_FIFTH_EDITION || xmlCharType.IsNCNameHighSurrogateChar(curChar) #endif ) { _prefix = _name; _name = ScanNCName(); // Look ahead for '(' to determine whether QName can be a FunctionName saveSourceIndex = _curIndex; SkipSpace(); _canBeFunction = (_curChar == '('); SetSourceIndex(saveSourceIndex); } else { // "foo:?" -> OperatorName, NameTest // Return "foo" and leave ":" to be reported later as an unknown lexeme SetSourceIndex(saveSourceIndex); } } } else { SkipSpace(); if (_curChar == ':') { // "foo ::" or "foo :?" NextChar(); if (_curChar == ':') { NextChar(); colonColon = true; } SetSourceIndex(saveSourceIndex); } else { _canBeFunction = (_curChar == '('); } } if (!CheckOperator(false) && colonColon) { _axis = CheckAxis(); } } else { _kind = LexKind.Unknown; NextChar(); } break; } }
public bool NextLexeme() { switch (_currChar) { case '\0': _kind = LexKind.Eof; return(false); case '(': case ')': case '=': case '/': _kind = (LexKind)Convert.ToInt32(_currChar); NextChar(); break; case '^': NextChar(); if (_currChar == '^' || _currChar == '(' || _currChar == ')') { _kind = LexKind.EscapedData; NextChar(); } else { throw new XPointerSyntaxException(Resources.CircumflexCharMustBeEscaped); } break; default: if (Char.IsDigit(_currChar)) { _kind = LexKind.Number; var start = _ptrIndex - 1; var len = 0; while (Char.IsDigit(_currChar)) { NextChar(); len++; } Number = XmlConvert.ToInt32(_ptr.Substring(start, len)); break; } if (LexUtils.IsStartNameChar(_currChar)) { _kind = LexKind.NcName; Prefix = String.Empty; NcName = ParseName(); if (_currChar == ':') { //QName? NextChar(); Prefix = NcName; _kind = LexKind.QName; if (LexUtils.IsStartNcNameChar(_currChar)) { NcName = ParseName(); } else { throw new XPointerSyntaxException(String.Format(CultureInfo.CurrentCulture, Resources.InvalidNameToken, Prefix, _currChar)); } } CanBeSchemaName = _currChar == '('; break; } if (LexUtils.IsWhitespace(_currChar)) { _kind = LexKind.Space; while (LexUtils.IsWhitespace(_currChar)) { NextChar(); } break; } _kind = LexKind.EscapedData; break; } return(true); }
public bool NextLex() { SkipSpace(); switch (this.CurerntChar) { case '\0' : kind = LexKind.Eof; return false; case ',': case '@': case '(': case ')': case '|': case '*': case '[': case ']': case '+': case '-': case '=': case '#': case '$': kind = (LexKind) Convert.ToInt32(this.CurerntChar, CultureInfo.InvariantCulture); NextChar(); break; case '<': kind = LexKind.Lt; NextChar(); if (this.CurerntChar == '=') { kind = LexKind.Le; NextChar(); } break; case '>': kind = LexKind.Gt; NextChar(); if (this.CurerntChar == '=') { kind = LexKind.Ge; NextChar(); } break; case '!': kind = LexKind.Bang; NextChar(); if (this.CurerntChar == '=') { kind = LexKind.Ne; NextChar(); } break; case '.': kind = LexKind.Dot; NextChar(); if (this.CurerntChar == '.') { kind = LexKind.DotDot; NextChar(); } else if (XmlCharType.IsDigit(this.CurerntChar)) { kind = LexKind.Number; numberValue = ScanFraction(); } break; case '/': kind = LexKind.Slash; NextChar(); if (this.CurerntChar == '/') { kind = LexKind.SlashSlash; NextChar(); } break; case '"': case '\'': this.kind = LexKind.String; this.stringValue = ScanString(); break; default: if (XmlCharType.IsDigit(this.CurerntChar)) { kind = LexKind.Number; numberValue = ScanNumber(); } else if (xmlCharType.IsStartNCNameSingleChar(this.CurerntChar) #if XML10_FIFTH_EDITION || xmlCharType.IsNCNameHighSurrogateChar(this.CurerntChar) #endif ) { kind = LexKind.Name; this.name = ScanName(); this.prefix = string.Empty; // "foo:bar" is one lexem not three because it doesn't allow spaces in between // We should distinct it from "foo::" and need process "foo ::" as well if (this.CurerntChar == ':') { NextChar(); // can be "foo:bar" or "foo::" if (this.CurerntChar == ':') { // "foo::" NextChar(); kind = LexKind.Axe; } else { // "foo:*", "foo:bar" or "foo: " this.prefix = this.name; if (this.CurerntChar == '*') { NextChar(); this.name = "*"; } else if (xmlCharType.IsStartNCNameSingleChar(this.CurerntChar) #if XML10_FIFTH_EDITION || xmlCharType.IsNCNameHighSurrogateChar(this.CurerntChar) #endif ) { this.name = ScanName(); } else { throw XPathException.Create(Res.Xp_InvalidName, SourceText); } } } else { SkipSpace(); if (this.CurerntChar == ':') { NextChar(); // it can be "foo ::" or just "foo :" if (this.CurerntChar == ':') { NextChar(); kind = LexKind.Axe; } else { throw XPathException.Create(Res.Xp_InvalidName, SourceText); } } } SkipSpace(); this.canBeFunction = (this.CurerntChar == '('); } else { throw XPathException.Create(Res.Xp_InvalidToken, SourceText); } break; } return true; }
public string LexKindToString(LexKind t) { const string OneCharLexemes = ",/@.()[]{}*+-=<>!$|"; if (OneCharLexemes.IndexOf((char)t) >= 0) { return ((char)t).ToString(); } switch (t) { case LexKind.Ne : return "!="; case LexKind.Le : return "<="; case LexKind.Ge : return ">="; case LexKind.DotDot : return ".."; case LexKind.SlashSlash : return "//"; case LexKind.Name : return "<name>"; case LexKind.String : return "<string literal>"; case LexKind.Number : return "<number literal>"; case LexKind.Axis : return "<axis>"; case LexKind.Unknown : return "<unknown>"; case LexKind.Eof : return "<eof>"; default: Debug.Fail("Must not get here"); return string.Empty; } }
public bool NextLex() { SkipSpace(); switch (CurrentChar) { case '\0': _kind = LexKind.Eof; return(false); case ',': case '@': case '(': case ')': case '|': case '*': case '[': case ']': case '+': case '-': case '=': case '#': case '$': _kind = (LexKind)Convert.ToInt32(CurrentChar, CultureInfo.InvariantCulture); NextChar(); break; case '<': _kind = LexKind.Lt; NextChar(); if (CurrentChar == '=') { _kind = LexKind.Le; NextChar(); } break; case '>': _kind = LexKind.Gt; NextChar(); if (CurrentChar == '=') { _kind = LexKind.Ge; NextChar(); } break; case '!': _kind = LexKind.Bang; NextChar(); if (CurrentChar == '=') { _kind = LexKind.Ne; NextChar(); } break; case '.': _kind = LexKind.Dot; NextChar(); if (CurrentChar == '.') { _kind = LexKind.DotDot; NextChar(); } else if (XmlCharType.IsDigit(CurrentChar)) { _kind = LexKind.Number; _numberValue = ScanFraction(); } break; case '/': _kind = LexKind.Slash; NextChar(); if (CurrentChar == '/') { _kind = LexKind.SlashSlash; NextChar(); } break; case '"': case '\'': _kind = LexKind.String; _stringValue = ScanString(); break; default: if (XmlCharType.IsDigit(CurrentChar)) { _kind = LexKind.Number; _numberValue = ScanNumber(); } else if (XmlCharType.IsStartNCNameSingleChar(CurrentChar)) { _kind = LexKind.Name; _name = ScanName(); _prefix = string.Empty; // "foo:bar" is one lexeme not three because it doesn't allow spaces in between // We should distinct it from "foo::" and need process "foo ::" as well if (CurrentChar == ':') { NextChar(); // can be "foo:bar" or "foo::" if (CurrentChar == ':') { // "foo::" NextChar(); _kind = LexKind.Axe; } else { // "foo:*", "foo:bar" or "foo: " _prefix = _name; if (CurrentChar == '*') { NextChar(); _name = "*"; } else if (XmlCharType.IsStartNCNameSingleChar(CurrentChar)) { _name = ScanName(); } else { throw XPathException.Create(SR.Xp_InvalidName, SourceText); } } } else { SkipSpace(); if (CurrentChar == ':') { NextChar(); // it can be "foo ::" or just "foo :" if (CurrentChar == ':') { NextChar(); _kind = LexKind.Axe; } else { throw XPathException.Create(SR.Xp_InvalidName, SourceText); } } } SkipSpace(); _canBeFunction = (CurrentChar == '('); } else { throw XPathException.Create(SR.Xp_InvalidToken, SourceText); } break; } return(true); }
public bool NextLex() { SkipSpace(); switch (this.CurerntChar) { case '\0' : kind = LexKind.Eof; return false; case ',': case '@': case '(': case ')': case '|': case '*': case '[': case ']': case '+': case '-': case '=': case '#': case '$': kind = (LexKind) Convert.ToInt32(this.CurerntChar); NextChar(); break; case '<': kind = LexKind.Lt; NextChar(); if (this.CurerntChar == '=') { kind = LexKind.Le; NextChar(); } break; case '>': kind = LexKind.Gt; NextChar(); if (this.CurerntChar == '=') { kind = LexKind.Ge; NextChar(); } break; case '!': kind = LexKind.Bang; NextChar(); if (this.CurerntChar == '=') { kind = LexKind.Ne; NextChar(); } break; case '.': kind = LexKind.Dot; NextChar(); if (this.CurerntChar == '.') { kind = LexKind.DotDot; NextChar(); } else if (XmlCharType.IsDigit(this.CurerntChar)) { kind = LexKind.Number; numberValue = ScanFraction(); } break; case '/': kind = LexKind.Slash; NextChar(); if (this.CurerntChar == '/') { kind = LexKind.SlashSlash; NextChar(); } break; case '"': case '\'': this.kind = LexKind.String; this.stringValue = ScanString(); break; default: if (XmlCharType.IsDigit(this.CurerntChar)) { kind = LexKind.Number; numberValue = ScanNumber(); } else if (XmlCharType.IsStartNCNameChar(this.CurerntChar)) { kind = LexKind.Name; this.name = ScanName(); this.prefix = string.Empty; // "foo:bar" is one lexem not three because it doesn't allow spaces in between // We should distinct it from "foo::" and need process "foo ::" as well if (this.CurerntChar == ':') { NextChar(); // can be "foo:bar" or "foo::" if (this.CurerntChar == ':') { // "foo::" NextChar(); kind = LexKind.Axe; } else { // "foo:*", "foo:bar" or "foo: " this.prefix = this.name; if (this.CurerntChar == '*') { NextChar(); this.name = "*"; } else if (XmlCharType.IsStartNCNameChar(this.CurerntChar)) { this.name = ScanName(); } else { throw new XPathException(String.Format("'{0}' has an invalid qualified name.", SourceText)); } } } else { SkipSpace(); if (this.CurerntChar == ':') { NextChar(); // it can be "foo ::" or just "foo :" if (this.CurerntChar == ':') { NextChar(); kind = LexKind.Axe; } else { throw new XPathException(String.Format("'{0}' has an invalid qualified name.", SourceText)); } } } SkipSpace(); this.canBeFunction = (this.CurerntChar == '('); } else { throw new XPathException(String.Format("'{0}' has an invalid token.", SourceText)); } break; } return true; }