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
- SystemInfo.cs
- AssemblyResourceLoader.cs
- LicenseContext.cs
- ComplexBindingPropertiesAttribute.cs
- RuleSettings.cs
- SQLBytes.cs
- InvokePatternIdentifiers.cs
- ConstraintConverter.cs
- TypeBinaryExpression.cs
- UserNameServiceElement.cs
- ProtectedConfigurationProviderCollection.cs
- UTF8Encoding.cs
- PolygonHotSpot.cs
- LogStore.cs
- ReachUIElementCollectionSerializerAsync.cs
- EntityClassGenerator.cs
- RelatedView.cs
- EventMappingSettings.cs
- TextDecoration.cs
- Part.cs
- WhitespaceRuleLookup.cs
- VersionedStreamOwner.cs
- PathGradientBrush.cs
- EventHandlersStore.cs
- SimpleExpression.cs
- TextAdaptor.cs
- CurrencyManager.cs
- RevocationPoint.cs
- Peer.cs
- SoapSchemaExporter.cs
- XsltException.cs
- EventLogger.cs
- Rect3D.cs
- XmlReflectionImporter.cs
- DBConcurrencyException.cs
- CategoryNameCollection.cs
- SimpleTypeResolver.cs
- OleDbParameter.cs
- MachineKeySection.cs
- RootBrowserWindowProxy.cs
- PerformanceCounterPermissionAttribute.cs
- HandlerBase.cs
- DocumentViewer.cs
- CategoryAttribute.cs
- MimeMapping.cs
- EntityContainerEntitySet.cs
- IdentityModelDictionary.cs
- DeploymentSectionCache.cs
- UiaCoreProviderApi.cs
- SharedPersonalizationStateInfo.cs
- XmlWriterSettings.cs
- WaitHandleCannotBeOpenedException.cs
- COM2IDispatchConverter.cs
- BoundColumn.cs
- ExtensibleSyndicationObject.cs
- DesignUtil.cs
- AutomationAttributeInfo.cs
- WebRequestModulesSection.cs
- TreeViewImageIndexConverter.cs
- SQLStringStorage.cs
- SessionStateModule.cs
- IItemProperties.cs
- TitleStyle.cs
- FontCollection.cs
- StorageBasedPackageProperties.cs
- MruCache.cs
- CompiledXpathExpr.cs
- FamilyCollection.cs
- ChangeDirector.cs
- DataGridViewSelectedColumnCollection.cs
- DataKey.cs
- SudsParser.cs
- WebUtil.cs
- HMACSHA256.cs
- FileUpload.cs
- HelpKeywordAttribute.cs
- EntityContainer.cs
- TextDocumentView.cs
- FontFamily.cs
- Iis7Helper.cs
- FileDetails.cs
- SimpleMailWebEventProvider.cs
- Themes.cs
- CodeGenerator.cs
- EdmSchemaAttribute.cs
- IndexedDataBuffer.cs
- QilVisitor.cs
- ContentPresenter.cs
- XmlSchemaInfo.cs
- RawStylusInputReport.cs
- XPathNavigatorReader.cs
- safelink.cs
- SmiGettersStream.cs
- RSAPKCS1KeyExchangeFormatter.cs
- Run.cs
- OdbcInfoMessageEvent.cs
- ControlDesignerState.cs
- PermissionAttributes.cs
- Marshal.cs
- DataGrid.cs