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
- ProviderUtil.cs
- CryptoKeySecurity.cs
- KeyNotFoundException.cs
- DefaultPerformanceCounters.cs
- SiteIdentityPermission.cs
- TextServicesLoader.cs
- ObfuscateAssemblyAttribute.cs
- ConfigDefinitionUpdates.cs
- PropertyMapper.cs
- DataViewManagerListItemTypeDescriptor.cs
- Sequence.cs
- JapaneseCalendar.cs
- FrameworkContentElementAutomationPeer.cs
- ColorAnimationBase.cs
- NativeDirectoryServicesQueryAPIs.cs
- CompilerErrorCollection.cs
- ObjectListCommand.cs
- InvalidOperationException.cs
- Baml2006KnownTypes.cs
- SkipQueryOptionExpression.cs
- OutputCacheSection.cs
- DynamicDiscoveryDocument.cs
- CultureSpecificStringDictionary.cs
- MatrixCamera.cs
- CompositeDataBoundControl.cs
- Vector3DCollection.cs
- OleDbMetaDataFactory.cs
- ItemCollection.cs
- BamlLocalizableResourceKey.cs
- DatasetMethodGenerator.cs
- ParallelLoopState.cs
- XmlElementCollection.cs
- MediaPlayer.cs
- X509CertificateChain.cs
- MessageQueueAccessControlEntry.cs
- TabControl.cs
- QuarticEase.cs
- ExtendLockCommand.cs
- DesignOnlyAttribute.cs
- JpegBitmapEncoder.cs
- QueryMath.cs
- Thumb.cs
- NameValueConfigurationCollection.cs
- EntitySetBaseCollection.cs
- SettingsPropertyNotFoundException.cs
- InheritablePropertyChangeInfo.cs
- WindowsPrincipal.cs
- Activator.cs
- RecognizedWordUnit.cs
- XamlInt32CollectionSerializer.cs
- DataGridViewColumnHeaderCell.cs
- MetadataHelper.cs
- TextModifierScope.cs
- ScrollItemProviderWrapper.cs
- Aes.cs
- SequenceNumber.cs
- SafeNativeMethods.cs
- DrawListViewSubItemEventArgs.cs
- CreateUserWizardStep.cs
- ExpressionEditorSheet.cs
- MimeMapping.cs
- X509Certificate2.cs
- WindowShowOrOpenTracker.cs
- XamlFxTrace.cs
- JavaScriptString.cs
- DescendantQuery.cs
- RecoverInstanceLocksCommand.cs
- TextParagraphView.cs
- TaiwanLunisolarCalendar.cs
- IncrementalHitTester.cs
- hebrewshape.cs
- FormatSettings.cs
- RepeatBehavior.cs
- HttpsTransportElement.cs
- ExpressionBuilderCollection.cs
- WebPartMenuStyle.cs
- DesignSurface.cs
- SqlPersonalizationProvider.cs
- SignedXml.cs
- baseaxisquery.cs
- SecurityPolicySection.cs
- GestureRecognitionResult.cs
- SQLInt16Storage.cs
- RC2CryptoServiceProvider.cs
- DataBindingExpressionBuilder.cs
- ThreadExceptionDialog.cs
- StandardTransformFactory.cs
- StringValidator.cs
- PolicyStatement.cs
- EditorBrowsableAttribute.cs
- SafeFileMappingHandle.cs
- TypeUsageBuilder.cs
- FileLoadException.cs
- FilteredDataSetHelper.cs
- ConstructorNeedsTagAttribute.cs
- InvalidWMPVersionException.cs
- WhereaboutsReader.cs
- BamlTreeUpdater.cs
- CounterCreationData.cs
- MultilineStringConverter.cs