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
- Helper.cs
- SafeUserTokenHandle.cs
- Line.cs
- Header.cs
- Types.cs
- InstanceKeyNotReadyException.cs
- VarRemapper.cs
- SizeConverter.cs
- DataGridViewDataConnection.cs
- WmlPanelAdapter.cs
- BamlLocalizableResourceKey.cs
- SqlCacheDependency.cs
- Maps.cs
- Int16.cs
- BuildResultCache.cs
- ProjectionCamera.cs
- DataGridViewRow.cs
- DispatchWrapper.cs
- WorkflowMarkupSerializationManager.cs
- ContentFilePart.cs
- UserNameSecurityTokenProvider.cs
- WindowsFont.cs
- DataControlFieldHeaderCell.cs
- EndpointDiscoveryElement.cs
- SqlResolver.cs
- CompositeFontFamily.cs
- CreateUserWizardStep.cs
- PropertyMapper.cs
- FtpWebResponse.cs
- Rijndael.cs
- safesecurityhelperavalon.cs
- HealthMonitoringSectionHelper.cs
- HttpWebResponse.cs
- BindingManagerDataErrorEventArgs.cs
- SafeFileMappingHandle.cs
- AtomEntry.cs
- FatalException.cs
- HotCommands.cs
- SQLBinaryStorage.cs
- TransactionFilter.cs
- BitmapImage.cs
- OrthographicCamera.cs
- WorkflowNamespace.cs
- RichTextBox.cs
- NumberFunctions.cs
- DefaultShape.cs
- precedingsibling.cs
- DefaultValueTypeConverter.cs
- Stacktrace.cs
- formatter.cs
- Signature.cs
- FileLoadException.cs
- DefaultBindingPropertyAttribute.cs
- NativeMethods.cs
- WindowsTooltip.cs
- XmlCustomFormatter.cs
- KeyValueConfigurationCollection.cs
- WebPartDisplayModeEventArgs.cs
- DependencyObjectPropertyDescriptor.cs
- ConnectionStringSettings.cs
- ReferencedAssembly.cs
- KnownBoxes.cs
- CodeTypeParameter.cs
- LocationInfo.cs
- TransformConverter.cs
- BinaryFormatterWriter.cs
- SQLDateTime.cs
- ConfigurationManager.cs
- StrokeNodeData.cs
- Activity.cs
- ClientUtils.cs
- CharacterHit.cs
- EntityDataSourceContainerNameItem.cs
- XappLauncher.cs
- Canonicalizers.cs
- TypeExtensionConverter.cs
- WebPartEditorCancelVerb.cs
- IPipelineRuntime.cs
- ActivityMarkupSerializer.cs
- DataServiceKeyAttribute.cs
- SystemNetworkInterface.cs
- RemotingAttributes.cs
- XMLSyntaxException.cs
- ControlCollection.cs
- UpdateTracker.cs
- LinqDataSourceView.cs
- ValidationErrorCollection.cs
- StrongName.cs
- CommandLineParser.cs
- DiscriminatorMap.cs
- basenumberconverter.cs
- ReflectionPermission.cs
- IconHelper.cs
- WpfKnownMember.cs
- ResourcePart.cs
- VirtualPath.cs
- WebPartZoneAutoFormat.cs
- Membership.cs
- EntityDataSourceWrapperCollection.cs
- TemplatedEditableDesignerRegion.cs