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
- InternalBufferOverflowException.cs
- CodeConditionStatement.cs
- DataGridItemCollection.cs
- ActivityTypeDesigner.xaml.cs
- MobileUITypeEditor.cs
- SafeCertificateStore.cs
- TypeInitializationException.cs
- SafeMILHandle.cs
- DocumentEventArgs.cs
- HtmlContainerControl.cs
- BamlReader.cs
- NavigatorOutput.cs
- ModelItemExtensions.cs
- SystemThemeKey.cs
- SHA1.cs
- HttpDebugHandler.cs
- ArgIterator.cs
- HtmlInputSubmit.cs
- ZipIOExtraField.cs
- RichTextBox.cs
- AutoResizedEvent.cs
- EntityDataSourceEntityTypeFilterItem.cs
- SwitchAttribute.cs
- Pkcs9Attribute.cs
- ObjectDataSourceChooseMethodsPanel.cs
- ParserHooks.cs
- PackageStore.cs
- dataprotectionpermission.cs
- BamlVersionHeader.cs
- DbConnectionPoolOptions.cs
- OrderedEnumerableRowCollection.cs
- CornerRadiusConverter.cs
- DataGridLinkButton.cs
- MessageSecurityProtocol.cs
- StubHelpers.cs
- SQLByte.cs
- ComboBox.cs
- DelayedRegex.cs
- AtomMaterializer.cs
- PropertyMappingExceptionEventArgs.cs
- EventListener.cs
- DbModificationClause.cs
- rsa.cs
- TextTreeFixupNode.cs
- ComponentEditorForm.cs
- StreamGeometry.cs
- ExpressionBindings.cs
- HwndHost.cs
- PerfService.cs
- AQNBuilder.cs
- SelectionEditingBehavior.cs
- EnumUnknown.cs
- OneOfScalarConst.cs
- DateTimeUtil.cs
- AuthorizationRule.cs
- ResourceCategoryAttribute.cs
- ExpressionBinding.cs
- PrivilegedConfigurationManager.cs
- DataControlPagerLinkButton.cs
- GeometryCombineModeValidation.cs
- PrePrepareMethodAttribute.cs
- FixedTextContainer.cs
- cache.cs
- IDReferencePropertyAttribute.cs
- AssemblyCollection.cs
- ManagementClass.cs
- CodeArrayIndexerExpression.cs
- CollectionDataContractAttribute.cs
- followingsibling.cs
- IndependentAnimationStorage.cs
- InternalBufferManager.cs
- mediaeventshelper.cs
- DataReaderContainer.cs
- ConnectionManagementElement.cs
- PermissionSet.cs
- HitTestParameters3D.cs
- SQLBoolean.cs
- StringInfo.cs
- FontFamilyIdentifier.cs
- OneOfScalarConst.cs
- LocalValueEnumerator.cs
- ListViewGroup.cs
- BrowsableAttribute.cs
- X509ChainPolicy.cs
- PerformanceCounterNameAttribute.cs
- RewritingValidator.cs
- RunClient.cs
- FormViewPagerRow.cs
- SafeNativeMethodsCLR.cs
- TaskCanceledException.cs
- CodeDefaultValueExpression.cs
- SaveRecipientRequest.cs
- DateTimeStorage.cs
- QuestionEventArgs.cs
- WebPartChrome.cs
- DesignerRegionMouseEventArgs.cs
- ProfileServiceManager.cs
- CategoryAttribute.cs
- Misc.cs
- ApplicationSettingsBase.cs