Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / XmlUtils / System / Xml / Xsl / XPath / XPathScanner.cs / 1 / XPathScanner.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System.Diagnostics; //using System.Globalization; //using System.Text; namespace System.Xml.Xsl.XPath { using Res = System.Xml.Utils.Res; internal enum LexKind { Comma = ',', Slash = '/', At = '@', Dot = '.', LParens = '(', RParens = ')', LBracket = '[', RBracket = ']', LBrace = '{', RBrace = '}', Star = '*', Plus = '+', Minus = '-', Eq = '=', Lt = '<', Gt = '>', Bang = '!', Dollar = '$', Union = '|', Ne = 'N', // != Le = 'L', // <= Ge = 'G', // >= DotDot = 'D', // .. SlashSlash = 'S', // // Name = 'n', // Name String = 's', // String literal Number = 'd', // Numeric literal Axis = 'a', // Axis Unknown = 'U', // Unknown char Eof = 'E', }; sealed internal class XPathScanner { private string xpathExpr; private int curIndex; private char curChar; private LexKind kind; private string name; private string prefix; private string stringValue; private double numberValue = double.NaN; private bool canBeFunction; private int lexStart; private int prevLexEnd; private XmlCharType xmlCharType = XmlCharType.Instance; public XPathScanner(string xpathExpr) : this(xpathExpr, 0) {} public XPathScanner(string xpathExpr, int startFrom) { Debug.Assert(xpathExpr != null); this.xpathExpr = xpathExpr; SetSourceIndex(startFrom); NextLex(); } public string Source { get { return xpathExpr; } } public LexKind Kind { get { return kind; } } public int LexStart { get { return lexStart; } } public int LexSize { get { return curIndex - lexStart; } } public int PrevLexEnd { get { return prevLexEnd; } } private void SetSourceIndex(int index) { curIndex = index - 1; NextChar(); } private bool NextChar() { Debug.Assert(-1 <= curIndex && curIndex < xpathExpr.Length); curIndex++; if (curIndex < xpathExpr.Length) { curChar = xpathExpr[curIndex]; return true; } else { Debug.Assert(curIndex == xpathExpr.Length); curChar = '\0'; return false; } } public string Name { get { Debug.Assert(kind == LexKind.Name || kind == LexKind.Axis); Debug.Assert(name != null); return name; } } public string Prefix { get { Debug.Assert(kind == LexKind.Name); Debug.Assert(prefix != null); return prefix; } } public bool IsKeyword(string keyword) { return ( kind == LexKind.Name && prefix.Length == 0 && name.Equals(keyword) ); } public string RawValue { get { if (kind == LexKind.Eof) { return LexKindToString(kind); } else { return xpathExpr.Substring(lexStart, curIndex - lexStart); } } } public string StringValue { get { Debug.Assert(kind == LexKind.String); Debug.Assert(stringValue != null); return stringValue; } } public double NumberValue { get { Debug.Assert(kind == LexKind.Number); Debug.Assert(numberValue != double.NaN); return numberValue; } } // To parse PathExpr we need a way to distinct name from function. // THis distinction can't be done without context: "or (1 != 0)" this this a function or 'or' in OrExp public bool CanBeFunction { get { Debug.Assert(kind == LexKind.Name); return canBeFunction; } } void SkipSpace() { while (xmlCharType.IsWhiteSpace(curChar) && NextChar()) { } } 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; } 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)); } 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)); } 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(); } private string ScanNCName() { Debug.Assert(xmlCharType.IsStartNCNameChar(curChar)); int start = curIndex; while (xmlCharType.IsNCNameChar(curChar)) { NextChar(); } return xpathExpr.Substring(start, curIndex - start); } public void PassToken(LexKind t) { CheckToken(t); NextLex(); } 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 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 ""; case LexKind.String : return " "; case LexKind.Number : return " "; case LexKind.Axis : return " "; case LexKind.Unknown : return " "; case LexKind.Eof : return " "; default: Debug.Fail("Must not get here"); return string.Empty; } } public XPathCompileException CreateException(string resId, params string[] args) { return new XPathCompileException(xpathExpr, lexStart, curIndex, resId, args); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- using System.Diagnostics; //using System.Globalization; //using System.Text; namespace System.Xml.Xsl.XPath { using Res = System.Xml.Utils.Res; internal enum LexKind { Comma = ',', Slash = '/', At = '@', Dot = '.', LParens = '(', RParens = ')', LBracket = '[', RBracket = ']', LBrace = '{', RBrace = '}', Star = '*', Plus = '+', Minus = '-', Eq = '=', Lt = '<', Gt = '>', Bang = '!', Dollar = '$', Union = '|', Ne = 'N', // != Le = 'L', // <= Ge = 'G', // >= DotDot = 'D', // .. SlashSlash = 'S', // // Name = 'n', // Name String = 's', // String literal Number = 'd', // Numeric literal Axis = 'a', // Axis Unknown = 'U', // Unknown char Eof = 'E', }; sealed internal class XPathScanner { private string xpathExpr; private int curIndex; private char curChar; private LexKind kind; private string name; private string prefix; private string stringValue; private double numberValue = double.NaN; private bool canBeFunction; private int lexStart; private int prevLexEnd; private XmlCharType xmlCharType = XmlCharType.Instance; public XPathScanner(string xpathExpr) : this(xpathExpr, 0) {} public XPathScanner(string xpathExpr, int startFrom) { Debug.Assert(xpathExpr != null); this.xpathExpr = xpathExpr; SetSourceIndex(startFrom); NextLex(); } public string Source { get { return xpathExpr; } } public LexKind Kind { get { return kind; } } public int LexStart { get { return lexStart; } } public int LexSize { get { return curIndex - lexStart; } } public int PrevLexEnd { get { return prevLexEnd; } } private void SetSourceIndex(int index) { curIndex = index - 1; NextChar(); } private bool NextChar() { Debug.Assert(-1 <= curIndex && curIndex < xpathExpr.Length); curIndex++; if (curIndex < xpathExpr.Length) { curChar = xpathExpr[curIndex]; return true; } else { Debug.Assert(curIndex == xpathExpr.Length); curChar = '\0'; return false; } } public string Name { get { Debug.Assert(kind == LexKind.Name || kind == LexKind.Axis); Debug.Assert(name != null); return name; } } public string Prefix { get { Debug.Assert(kind == LexKind.Name); Debug.Assert(prefix != null); return prefix; } } public bool IsKeyword(string keyword) { return ( kind == LexKind.Name && prefix.Length == 0 && name.Equals(keyword) ); } public string RawValue { get { if (kind == LexKind.Eof) { return LexKindToString(kind); } else { return xpathExpr.Substring(lexStart, curIndex - lexStart); } } } public string StringValue { get { Debug.Assert(kind == LexKind.String); Debug.Assert(stringValue != null); return stringValue; } } public double NumberValue { get { Debug.Assert(kind == LexKind.Number); Debug.Assert(numberValue != double.NaN); return numberValue; } } // To parse PathExpr we need a way to distinct name from function. // THis distinction can't be done without context: "or (1 != 0)" this this a function or 'or' in OrExp public bool CanBeFunction { get { Debug.Assert(kind == LexKind.Name); return canBeFunction; } } void SkipSpace() { while (xmlCharType.IsWhiteSpace(curChar) && NextChar()) { } } 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; } 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)); } 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)); } 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(); } private string ScanNCName() { Debug.Assert(xmlCharType.IsStartNCNameChar(curChar)); int start = curIndex; while (xmlCharType.IsNCNameChar(curChar)) { NextChar(); } return xpathExpr.Substring(start, curIndex - start); } public void PassToken(LexKind t) { CheckToken(t); NextLex(); } 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 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 ""; case LexKind.String : return " "; case LexKind.Number : return " "; case LexKind.Axis : return " "; case LexKind.Unknown : return " "; case LexKind.Eof : return " "; default: Debug.Fail("Must not get here"); return string.Empty; } } public XPathCompileException CreateException(string resId, params string[] args) { return new XPathCompileException(xpathExpr, lexStart, curIndex, resId, args); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CodeBlockBuilder.cs
- MultipleViewProviderWrapper.cs
- UriScheme.cs
- HtmlLink.cs
- RightsManagementLicense.cs
- SecurityToken.cs
- ModuleBuilderData.cs
- SessionStateContainer.cs
- _WinHttpWebProxyDataBuilder.cs
- MimeReflector.cs
- IgnoreSectionHandler.cs
- CompoundFileReference.cs
- _DomainName.cs
- ErrorHandler.cs
- Socket.cs
- WhitespaceRuleLookup.cs
- RequestQueue.cs
- MultipartContentParser.cs
- Focus.cs
- ResolveRequestResponseAsyncResult.cs
- TokenFactoryBase.cs
- CodeSnippetStatement.cs
- baseaxisquery.cs
- SortQuery.cs
- BamlReader.cs
- Quad.cs
- DataGridViewLayoutData.cs
- AsymmetricAlgorithm.cs
- TripleDES.cs
- UIPermission.cs
- DataGridViewRowHeaderCell.cs
- WebPartEditorApplyVerb.cs
- PatternMatcher.cs
- ReadOnlyCollectionBuilder.cs
- PackagePart.cs
- Lease.cs
- Calendar.cs
- SafePEFileHandle.cs
- DockPanel.cs
- FigureParagraph.cs
- PickDesigner.xaml.cs
- PrintingPermission.cs
- UndirectedGraph.cs
- DriveInfo.cs
- RowVisual.cs
- OdbcTransaction.cs
- DocumentOutline.cs
- CompiledAction.cs
- SqlWriter.cs
- ValueType.cs
- WorkflowControlClient.cs
- JsonServiceDocumentSerializer.cs
- ExpressionVisitor.cs
- NoPersistProperty.cs
- LockCookie.cs
- AttributeEmitter.cs
- AttributeQuery.cs
- XmlTextReader.cs
- SiteMapDataSourceView.cs
- XmlElement.cs
- HandlerWithFactory.cs
- PointHitTestParameters.cs
- Helper.cs
- Trace.cs
- PasswordDeriveBytes.cs
- TextElementCollection.cs
- TreeWalkHelper.cs
- SimpleBitVector32.cs
- LinearGradientBrush.cs
- TextBoxLine.cs
- TableHeaderCell.cs
- EntityFunctions.cs
- ManualResetEvent.cs
- XmlSchemaAppInfo.cs
- ToolZone.cs
- ScrollBarRenderer.cs
- XPathAncestorQuery.cs
- TabletDevice.cs
- Configuration.cs
- DefaultMemberAttribute.cs
- GlyphRun.cs
- ProcessHostMapPath.cs
- SocketInformation.cs
- WebPartPersonalization.cs
- Evidence.cs
- SmiRecordBuffer.cs
- XmlNamespaceMappingCollection.cs
- ClientUrlResolverWrapper.cs
- NavigationService.cs
- GridPatternIdentifiers.cs
- MetadataArtifactLoaderCompositeFile.cs
- GroupBox.cs
- FormsAuthenticationConfiguration.cs
- Config.cs
- XmlDataContract.cs
- BackoffTimeoutHelper.cs
- TaskHelper.cs
- StringArrayConverter.cs
- FontStretches.cs
- ItemCollection.cs