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
- Quaternion.cs
- DecimalSumAggregationOperator.cs
- OdbcCommand.cs
- DataBoundControl.cs
- UpdateException.cs
- ListViewGroupCollectionEditor.cs
- SafeHandles.cs
- HttpFileCollectionWrapper.cs
- SqlUserDefinedTypeAttribute.cs
- _LocalDataStore.cs
- HttpCapabilitiesBase.cs
- AttributeCollection.cs
- MLangCodePageEncoding.cs
- SafeLibraryHandle.cs
- TypeListConverter.cs
- TextLineBreak.cs
- SchemaMerger.cs
- PartialTrustVisibleAssemblyCollection.cs
- PhysicalAddress.cs
- BitmapEffectGroup.cs
- SmtpNtlmAuthenticationModule.cs
- TypeDependencyAttribute.cs
- ResourceExpressionEditorSheet.cs
- ToolStripContentPanelRenderEventArgs.cs
- ProviderManager.cs
- QilStrConcat.cs
- TransportConfigurationTypeElementCollection.cs
- NonParentingControl.cs
- MethodCallTranslator.cs
- ControlLocalizer.cs
- Binding.cs
- DataGridTableCollection.cs
- TypedReference.cs
- SmiRequestExecutor.cs
- StringCollection.cs
- Mapping.cs
- PersonalizationEntry.cs
- ResourcePermissionBase.cs
- VectorCollectionValueSerializer.cs
- StorageModelBuildProvider.cs
- SrgsSubset.cs
- TypefaceCollection.cs
- XmlPreloadedResolver.cs
- FixedTextPointer.cs
- Attributes.cs
- Preprocessor.cs
- panel.cs
- SoapEnvelopeProcessingElement.cs
- SQLResource.cs
- VisualStateGroup.cs
- Point.cs
- PolyLineSegment.cs
- StringHandle.cs
- RequestStatusBarUpdateEventArgs.cs
- SchemaObjectWriter.cs
- ToolStripEditorManager.cs
- AnnotationHighlightLayer.cs
- OleDbEnumerator.cs
- RequestCachingSection.cs
- ObjectComplexPropertyMapping.cs
- CodeAttributeDeclaration.cs
- PublishLicense.cs
- EventlogProvider.cs
- SpeakInfo.cs
- ReflectionServiceProvider.cs
- RenderTargetBitmap.cs
- URLIdentityPermission.cs
- XmlILAnnotation.cs
- UnauthorizedWebPart.cs
- Publisher.cs
- EDesignUtil.cs
- SoapIncludeAttribute.cs
- Thumb.cs
- ToolTip.cs
- XmlDeclaration.cs
- AbandonedMutexException.cs
- ChildTable.cs
- X509ThumbprintKeyIdentifierClause.cs
- PrintDialogException.cs
- ToolStripDropTargetManager.cs
- FrameworkName.cs
- Int32AnimationBase.cs
- XamlLoadErrorInfo.cs
- ManagementPath.cs
- WhitespaceRule.cs
- ButtonBaseDesigner.cs
- BamlRecordWriter.cs
- FlowDocumentPageViewerAutomationPeer.cs
- ColumnBinding.cs
- GroupQuery.cs
- TextBoxAutoCompleteSourceConverter.cs
- NestPullup.cs
- XmlAggregates.cs
- CharacterBuffer.cs
- RelationshipDetailsRow.cs
- InstancePersistenceCommandException.cs
- OleDbConnectionFactory.cs
- CLSCompliantAttribute.cs
- columnmapkeybuilder.cs
- PropertyChangedEventArgs.cs