Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Xml / System / Xml / XPath / Internal / XPathScanner.cs / 1305376 / XPathScanner.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- namespace MS.Internal.Xml.XPath { using System; using System.Xml; using System.Xml.XPath; using System.Diagnostics; using System.Globalization; using System.Text; using System.Collections; internal sealed class XPathScanner { private string xpathExpr; private int xpathExprIndex; private LexKind kind; private char currentChar; private string name; private string prefix; private string stringValue; private double numberValue = double.NaN; private bool canBeFunction; private XmlCharType xmlCharType = XmlCharType.Instance; public XPathScanner(string xpathExpr) { if (xpathExpr == null) { throw XPathException.Create(Res.Xp_ExprExpected, string.Empty); } this.xpathExpr = xpathExpr; NextChar(); NextLex(); } public string SourceText { get { return this.xpathExpr; } } private char CurerntChar { get { return currentChar; } } private bool NextChar() { Debug.Assert(0 <= xpathExprIndex && xpathExprIndex <= xpathExpr.Length); if (xpathExprIndex < xpathExpr.Length) { currentChar = xpathExpr[xpathExprIndex ++]; return true; } else { currentChar = '\0'; return false; } } #if XML10_FIFTH_EDITION private char PeekNextChar() { Debug.Assert(0 <= xpathExprIndex && xpathExprIndex <= xpathExpr.Length); if (xpathExprIndex < xpathExpr.Length) { return xpathExpr[xpathExprIndex]; } else { Debug.Assert(xpathExprIndex == xpathExpr.Length); return '\0'; } } #endif public LexKind Kind { get { return this.kind; } } public string Name { get { Debug.Assert(this.kind == LexKind.Name || this.kind == LexKind.Axe); Debug.Assert(this.name != null); return this.name; } } public string Prefix { get { Debug.Assert(this.kind == LexKind.Name); Debug.Assert(this.prefix != null); return this.prefix; } } public string StringValue { get { Debug.Assert(this.kind == LexKind.String); Debug.Assert(this.stringValue != null); return this.stringValue; } } public double NumberValue { get { Debug.Assert(this.kind == LexKind.Number); Debug.Assert(this.numberValue != double.NaN); return this.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(this.kind == LexKind.Name); return this.canBeFunction; } } void SkipSpace() { while (xmlCharType.IsWhiteSpace(this.CurerntChar) && NextChar()) ; } 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; } private double ScanNumber() { Debug.Assert(this.CurerntChar == '.' || XmlCharType.IsDigit(this.CurerntChar)); int start = xpathExprIndex - 1; int len = 0; while (XmlCharType.IsDigit(this.CurerntChar)) { NextChar(); len ++; } if (this.CurerntChar == '.') { NextChar(); len ++; while (XmlCharType.IsDigit(this.CurerntChar)) { NextChar(); len ++; } } return XmlConvert.ToXPathDouble(this.xpathExpr.Substring(start, len)); } private double ScanFraction() { Debug.Assert(XmlCharType.IsDigit(this.CurerntChar)); int start = xpathExprIndex - 2; Debug.Assert(0 <= start && this.xpathExpr[start] == '.'); int len = 1; // '.' while (XmlCharType.IsDigit(this.CurerntChar)) { NextChar(); len ++; } return XmlConvert.ToXPathDouble(this.xpathExpr.Substring(start, len)); } private string ScanString() { char endChar = this.CurerntChar; NextChar(); int start = xpathExprIndex - 1; int len = 0; while(this.CurerntChar != endChar) { if (! NextChar()) { throw XPathException.Create(Res.Xp_UnclosedString); } len ++; } Debug.Assert(this.CurerntChar == endChar); NextChar(); return this.xpathExpr.Substring(start, len); } private string ScanName() { Debug.Assert(xmlCharType.IsStartNCNameSingleChar(this.CurerntChar) #if XML10_FIFTH_EDITION || xmlCharType.IsNCNameHighSurrogateChar(this.CurerntChar) #endif ); int start = xpathExprIndex - 1; int len = 0; for (;;) { if (xmlCharType.IsNCNameSingleChar(this.CurerntChar)) { NextChar(); len ++; } #if XML10_FIFTH_EDITION else if (xmlCharType.IsNCNameSurrogateChar(this.PeekNextChar(), this.CurerntChar)) { NextChar(); NextChar(); len += 2; } #endif else { break; } } return this.xpathExpr.Substring(start, len); } public enum LexKind { Comma = ',', Slash = '/', At = '@', Dot = '.', LParens = '(', RParens = ')', LBracket = '[', RBracket = ']', Star = '*', Plus = '+', Minus = '-', Eq = '=', Lt = '<', Gt = '>', Bang = '!', Dollar = '$', Apos = '\'', Quote = '"', Union = '|', Ne = 'N', // != Le = 'L', // <= Ge = 'G', // >= And = 'A', // && Or = 'O', // || DotDot = 'D', // .. SlashSlash = 'S', // // Name = 'n', // XML _Name String = 's', // Quoted string constant Number = 'd', // _Number constant Axe = 'a', // Axe (like child::) Eof = 'E', }; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //----------------------------------------------------------------------------- namespace MS.Internal.Xml.XPath { using System; using System.Xml; using System.Xml.XPath; using System.Diagnostics; using System.Globalization; using System.Text; using System.Collections; internal sealed class XPathScanner { private string xpathExpr; private int xpathExprIndex; private LexKind kind; private char currentChar; private string name; private string prefix; private string stringValue; private double numberValue = double.NaN; private bool canBeFunction; private XmlCharType xmlCharType = XmlCharType.Instance; public XPathScanner(string xpathExpr) { if (xpathExpr == null) { throw XPathException.Create(Res.Xp_ExprExpected, string.Empty); } this.xpathExpr = xpathExpr; NextChar(); NextLex(); } public string SourceText { get { return this.xpathExpr; } } private char CurerntChar { get { return currentChar; } } private bool NextChar() { Debug.Assert(0 <= xpathExprIndex && xpathExprIndex <= xpathExpr.Length); if (xpathExprIndex < xpathExpr.Length) { currentChar = xpathExpr[xpathExprIndex ++]; return true; } else { currentChar = '\0'; return false; } } #if XML10_FIFTH_EDITION private char PeekNextChar() { Debug.Assert(0 <= xpathExprIndex && xpathExprIndex <= xpathExpr.Length); if (xpathExprIndex < xpathExpr.Length) { return xpathExpr[xpathExprIndex]; } else { Debug.Assert(xpathExprIndex == xpathExpr.Length); return '\0'; } } #endif public LexKind Kind { get { return this.kind; } } public string Name { get { Debug.Assert(this.kind == LexKind.Name || this.kind == LexKind.Axe); Debug.Assert(this.name != null); return this.name; } } public string Prefix { get { Debug.Assert(this.kind == LexKind.Name); Debug.Assert(this.prefix != null); return this.prefix; } } public string StringValue { get { Debug.Assert(this.kind == LexKind.String); Debug.Assert(this.stringValue != null); return this.stringValue; } } public double NumberValue { get { Debug.Assert(this.kind == LexKind.Number); Debug.Assert(this.numberValue != double.NaN); return this.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(this.kind == LexKind.Name); return this.canBeFunction; } } void SkipSpace() { while (xmlCharType.IsWhiteSpace(this.CurerntChar) && NextChar()) ; } 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; } private double ScanNumber() { Debug.Assert(this.CurerntChar == '.' || XmlCharType.IsDigit(this.CurerntChar)); int start = xpathExprIndex - 1; int len = 0; while (XmlCharType.IsDigit(this.CurerntChar)) { NextChar(); len ++; } if (this.CurerntChar == '.') { NextChar(); len ++; while (XmlCharType.IsDigit(this.CurerntChar)) { NextChar(); len ++; } } return XmlConvert.ToXPathDouble(this.xpathExpr.Substring(start, len)); } private double ScanFraction() { Debug.Assert(XmlCharType.IsDigit(this.CurerntChar)); int start = xpathExprIndex - 2; Debug.Assert(0 <= start && this.xpathExpr[start] == '.'); int len = 1; // '.' while (XmlCharType.IsDigit(this.CurerntChar)) { NextChar(); len ++; } return XmlConvert.ToXPathDouble(this.xpathExpr.Substring(start, len)); } private string ScanString() { char endChar = this.CurerntChar; NextChar(); int start = xpathExprIndex - 1; int len = 0; while(this.CurerntChar != endChar) { if (! NextChar()) { throw XPathException.Create(Res.Xp_UnclosedString); } len ++; } Debug.Assert(this.CurerntChar == endChar); NextChar(); return this.xpathExpr.Substring(start, len); } private string ScanName() { Debug.Assert(xmlCharType.IsStartNCNameSingleChar(this.CurerntChar) #if XML10_FIFTH_EDITION || xmlCharType.IsNCNameHighSurrogateChar(this.CurerntChar) #endif ); int start = xpathExprIndex - 1; int len = 0; for (;;) { if (xmlCharType.IsNCNameSingleChar(this.CurerntChar)) { NextChar(); len ++; } #if XML10_FIFTH_EDITION else if (xmlCharType.IsNCNameSurrogateChar(this.PeekNextChar(), this.CurerntChar)) { NextChar(); NextChar(); len += 2; } #endif else { break; } } return this.xpathExpr.Substring(start, len); } public enum LexKind { Comma = ',', Slash = '/', At = '@', Dot = '.', LParens = '(', RParens = ')', LBracket = '[', RBracket = ']', Star = '*', Plus = '+', Minus = '-', Eq = '=', Lt = '<', Gt = '>', Bang = '!', Dollar = '$', Apos = '\'', Quote = '"', Union = '|', Ne = 'N', // != Le = 'L', // <= Ge = 'G', // >= And = 'A', // && Or = 'O', // || DotDot = 'D', // .. SlashSlash = 'S', // // Name = 'n', // XML _Name String = 's', // Quoted string constant Number = 'd', // _Number constant Axe = 'a', // Axe (like child::) Eof = 'E', }; } } // 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
- AnnotationResource.cs
- BasicHttpBinding.cs
- FullTextState.cs
- GlyphRun.cs
- Utilities.cs
- TrackBar.cs
- CompressStream.cs
- EmissiveMaterial.cs
- ArcSegment.cs
- ToolStripDropDownClosedEventArgs.cs
- TextElementEditingBehaviorAttribute.cs
- DmlSqlGenerator.cs
- CodeArrayIndexerExpression.cs
- MaskedTextBox.cs
- WebContext.cs
- GenericEnumConverter.cs
- Win32MouseDevice.cs
- InputBindingCollection.cs
- DocumentApplicationState.cs
- PenContext.cs
- GeneralTransform.cs
- ValidationContext.cs
- PrinterUnitConvert.cs
- DocumentPageView.cs
- Lease.cs
- TreeViewEvent.cs
- PointAnimation.cs
- StrokeNodeEnumerator.cs
- SHA384Cng.cs
- MouseBinding.cs
- XmlNodeChangedEventArgs.cs
- ExtendedProperty.cs
- CustomCategoryAttribute.cs
- SemaphoreFullException.cs
- Point.cs
- DNS.cs
- UIAgentRequest.cs
- GridViewCancelEditEventArgs.cs
- Int64Storage.cs
- FunctionImportMapping.cs
- HTMLTagNameToTypeMapper.cs
- ParserOptions.cs
- TextSelectionHelper.cs
- CfgSemanticTag.cs
- QueryPageSettingsEventArgs.cs
- ScrollEventArgs.cs
- IpcClientManager.cs
- CultureSpecificStringDictionary.cs
- DeclarativeCatalogPart.cs
- UIElementHelper.cs
- ErrorFormatter.cs
- XmlSecureResolver.cs
- FilterUserControlBase.cs
- Canvas.cs
- ConfigurationSettings.cs
- CollectionType.cs
- EventProviderWriter.cs
- XPathNodeList.cs
- SafeViewOfFileHandle.cs
- DocumentOrderComparer.cs
- XamlTypeMapper.cs
- SoapExtensionImporter.cs
- SecurityManager.cs
- ThemeInfoAttribute.cs
- Automation.cs
- ItemCheckEvent.cs
- LockedAssemblyCache.cs
- Graph.cs
- ConvertTextFrag.cs
- GeneralTransform3DTo2D.cs
- ImageCodecInfoPrivate.cs
- RemotingSurrogateSelector.cs
- SiteMembershipCondition.cs
- FontUnitConverter.cs
- ContractMapping.cs
- Drawing.cs
- PageVisual.cs
- WebPartChrome.cs
- BoundPropertyEntry.cs
- IsolatedStoragePermission.cs
- FormatConvertedBitmap.cs
- GlyphsSerializer.cs
- ImageIndexConverter.cs
- QilName.cs
- CopyNodeSetAction.cs
- ButtonColumn.cs
- CommentEmitter.cs
- MatrixKeyFrameCollection.cs
- Control.cs
- QueryPageSettingsEventArgs.cs
- ServiceModelConfiguration.cs
- WSMessageEncoding.cs
- Int32EqualityComparer.cs
- WebPartConnectVerb.cs
- WebBrowserHelper.cs
- PropertyValueEditor.cs
- Matrix3DConverter.cs
- WsdlBuildProvider.cs
- RegexCode.cs
- RuntimeArgumentHandle.cs