Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / 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
- PocoPropertyAccessorStrategy.cs
- UnsettableComboBox.cs
- ListChangedEventArgs.cs
- securitycriticaldata.cs
- AlgoModule.cs
- WebPartTransformer.cs
- InvokeBinder.cs
- ComplexType.cs
- HttpModulesSection.cs
- _SecureChannel.cs
- CultureInfo.cs
- IDictionary.cs
- PeerResolverBindingElement.cs
- SymmetricKeyWrap.cs
- DataListCommandEventArgs.cs
- DataServices.cs
- DiagnosticTrace.cs
- InvokeBase.cs
- HttpBrowserCapabilitiesWrapper.cs
- XmlSchema.cs
- Utils.cs
- WebPart.cs
- AssociationType.cs
- MimeMultiPart.cs
- DateTimeConstantAttribute.cs
- MenuScrollingVisibilityConverter.cs
- PointCollectionConverter.cs
- MethodBuilderInstantiation.cs
- BuiltInPermissionSets.cs
- MessageBox.cs
- RIPEMD160.cs
- ToolStripDropDownItem.cs
- UnsafeNativeMethodsMilCoreApi.cs
- NamedPermissionSet.cs
- WasAdminWrapper.cs
- xdrvalidator.cs
- Number.cs
- RoutedEventArgs.cs
- DescendentsWalkerBase.cs
- XmlSchemaObjectCollection.cs
- PersonalizablePropertyEntry.cs
- ViewPort3D.cs
- StandardToolWindows.cs
- SafeNativeMethodsCLR.cs
- mongolianshape.cs
- CheckBox.cs
- X509AsymmetricSecurityKey.cs
- AppSettingsSection.cs
- RtfControls.cs
- WebAdminConfigurationHelper.cs
- TablePattern.cs
- PropertyMappingExceptionEventArgs.cs
- IApplicationTrustManager.cs
- ServiceThrottlingBehavior.cs
- ObfuscateAssemblyAttribute.cs
- IgnoreDataMemberAttribute.cs
- ToolStripItemClickedEventArgs.cs
- _ListenerResponseStream.cs
- SynchronousChannelMergeEnumerator.cs
- SqlInfoMessageEvent.cs
- PeerNearMe.cs
- Enum.cs
- HttpDebugHandler.cs
- XmlValidatingReader.cs
- DefaultWorkflowTransactionService.cs
- DataKeyCollection.cs
- ComplexBindingPropertiesAttribute.cs
- DataObjectMethodAttribute.cs
- UIElement3D.cs
- ScriptingJsonSerializationSection.cs
- ConfigurationElementProperty.cs
- IdleTimeoutMonitor.cs
- NamespaceDisplay.xaml.cs
- CodeMethodInvokeExpression.cs
- DependencyObject.cs
- SourceElementsCollection.cs
- KeyboardDevice.cs
- ConfigurationFileMap.cs
- DecoratedNameAttribute.cs
- AssemblySettingAttributes.cs
- TemplatedMailWebEventProvider.cs
- BaseCollection.cs
- FilterFactory.cs
- BaseDataList.cs
- _LocalDataStore.cs
- WpfSharedBamlSchemaContext.cs
- DbConnectionPoolGroup.cs
- WebPartRestoreVerb.cs
- InfoCardRSAPKCS1KeyExchangeFormatter.cs
- XmlSchemaFacet.cs
- WebBrowserBase.cs
- ReadOnlyHierarchicalDataSource.cs
- GridViewColumnCollection.cs
- TypedTableGenerator.cs
- COM2ExtendedUITypeEditor.cs
- AddInSegmentDirectoryNotFoundException.cs
- DeclaredTypeValidatorAttribute.cs
- ViewBase.cs
- StringBuilder.cs
- SafeRegistryKey.cs