Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / Activities / Rules / Parser / Intellisense.cs / 1305376 / Intellisense.cs
using System;
using System.Collections.Generic;
using System.Collections;
using System.Workflow.Activities.Rules;
namespace System.Workflow.Activities.Rules
{
internal class IntellisenseParser
{
private List tokens = new List();
private int tokenIndex;
internal IntellisenseParser(string inputString)
{
Scanner scanner = new Scanner(inputString);
// Tokenize the input, but insert a marker at the beginning.
tokens.Add(new Token(TokenID.EndOfInput, 0, null));
scanner.TokenizeForIntellisense(tokens);
}
private Token CurrentToken
{
get { return tokens[tokenIndex]; }
}
private Token PrevToken()
{
if (tokenIndex > 0)
--tokenIndex;
return CurrentToken;
}
internal ParserContext BackParse()
{
tokenIndex = tokens.Count - 1;
if (tokenIndex < 0)
return null;
Token token = CurrentToken;
bool valid = false;
// Skip past the right-most EndOfIput. For our backparsing, we've inserted an
// EndOfInput at the start.
if (token.TokenID == TokenID.EndOfInput)
token = PrevToken();
int endTokenIndex = tokenIndex;
if (token.TokenID == TokenID.Identifier && ((string)token.Value).Length == 1 && PrevToken().TokenID != TokenID.Dot)
{
// Assume this is the start of a root identifier
valid = true;
}
else if (token.TokenID == TokenID.Dot)
{
// Assume it's a member selection operator.
valid = BackParsePostfix();
}
else if (token.TokenID == TokenID.LParen)
{
// Assume it's the start of a method call argument list.
if (PrevToken().TokenID == TokenID.Identifier)
{
if (PrevToken().TokenID == TokenID.Dot)
{
// The tail looked like ".identifier(", so now we continue as in
// the member selection operator reverse parse above.
valid = BackParsePostfix();
}
else
{
// The tail looked like "identifier(", with no preceeding ".", so
// we're actually done.
valid = true;
}
if (valid)
{
// Back up over the "new" if there is one.
if (CurrentToken.TokenID == TokenID.New)
PrevToken();
}
}
}
if (!valid)
return null;
// We successfully backward-parsed a postfix expression. Create a
// ParserContext for the real parser, giving it the subrange of tokens
// that comprise the postfix expression.
List postfixTokens = tokens.GetRange(tokenIndex + 1, endTokenIndex - tokenIndex);
postfixTokens.Add(new Token(TokenID.EndOfInput, 0, null));
ParserContext parserContext = new ParserContext(postfixTokens);
return parserContext;
}
private bool BackParsePostfix()
{
while (CurrentToken.TokenID == TokenID.Dot)
{
Token token = PrevToken();
switch (token.TokenID)
{
case TokenID.Identifier:
case TokenID.TypeName:
PrevToken(); // eat the token
break;
case TokenID.This:
PrevToken(); // eat the "this"
// This is the start of the expression.
return true;
case TokenID.RParen:
// This may be the argument list of a method call,
// or it may be a parenthesized expression.
if (!BackParseMatchingDelimiter(TokenID.LParen))
return false;
if (CurrentToken.TokenID == TokenID.Identifier)
{
// It was a method call.
PrevToken(); // eat the method identifier
}
else
{
// It was a parenthesized subexpression. We are finished,
// we have found the start of the subexpression.
return true;
}
break;
case TokenID.RBracket:
// Loop backward over all [..][..]
do
{
if (!BackParseMatchingDelimiter(TokenID.LBracket))
return false;
} while (CurrentToken.TokenID == TokenID.RBracket);
// Preceeding the indexers might be an identifier, or a method call.
if (CurrentToken.TokenID == TokenID.Identifier)
{
// It was an identifier. Eat it and continue.
PrevToken(); // eat the identifier.
}
else if (CurrentToken.TokenID == TokenID.RParen)
{
// This may be the argument list of a method call,
// or it may be a parenthesized expression.
if (!BackParseMatchingDelimiter(TokenID.LParen))
return false;
if (CurrentToken.TokenID == TokenID.Identifier)
{
// It was a method call.
PrevToken(); // eat the method identifier
}
else
{
// It was a parenthesized subexpression. We are finished,
// we have found the start of the subexpression.
return true;
}
}
else
{
// It's not valid.
return false;
}
break;
case TokenID.Greater:
if (!BackParseMatchingDelimiter(TokenID.Less))
return false;
if (CurrentToken.TokenID == TokenID.Identifier)
{
// It was a generic type
PrevToken(); // Eat the type identifier
}
else
{
// This wasn't valid... it was a type argument list, but wasn't
// preceeded by an identifier.
return false;
}
break;
default:
// We saw a "." that wasn't preceeded by a useful token.
return false;
}
}
// If an identifier or type name is preceeded by "new", keep that.
if (CurrentToken.TokenID == TokenID.New)
PrevToken();
return true;
}
// Having parsed a closing delimiter, eat tokens until the matching open delimiter
// is found.
private bool BackParseMatchingDelimiter(TokenID openDelimiter)
{
TokenID closeDelimiter = CurrentToken.TokenID;
int level = 1;
Token token = PrevToken(); // Eat the close delimiter
while (token.TokenID != TokenID.EndOfInput)
{
if (token.TokenID == closeDelimiter)
{
++level;
}
else if (token.TokenID == openDelimiter)
{
--level;
if (level == 0)
{
PrevToken(); // eat the open delimiter
break;
}
}
token = PrevToken();
}
// Back parse was successful if we matched all delimiters.
return level == 0;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TraceSwitch.cs
- HttpProxyCredentialType.cs
- AccessViolationException.cs
- PageWrapper.cs
- XmlSchemaExporter.cs
- OdbcCommandBuilder.cs
- SystemIPv4InterfaceProperties.cs
- ContextStack.cs
- HttpCacheParams.cs
- SchemaAttDef.cs
- Byte.cs
- NativeMethods.cs
- ReferentialConstraint.cs
- UInt32Storage.cs
- mansign.cs
- DesignerActionHeaderItem.cs
- CompilerTypeWithParams.cs
- XPathChildIterator.cs
- SqlNotificationEventArgs.cs
- EventBuilder.cs
- CodeObject.cs
- CompilerGeneratedAttribute.cs
- WindowsToolbarItemAsMenuItem.cs
- TaskDesigner.cs
- FlowDocumentView.cs
- KnownTypesHelper.cs
- TextFragmentEngine.cs
- TextReader.cs
- ObjectListFieldCollection.cs
- basecomparevalidator.cs
- IPGlobalProperties.cs
- KeyValuePairs.cs
- CatalogPart.cs
- BufferedGenericXmlSecurityToken.cs
- ControlCachePolicy.cs
- RowParagraph.cs
- PageContentAsyncResult.cs
- MdImport.cs
- PrintingPermissionAttribute.cs
- Model3D.cs
- ObjectItemAttributeAssemblyLoader.cs
- IQueryable.cs
- Pkcs7Recipient.cs
- HtmlInputText.cs
- ContainerVisual.cs
- TargetConverter.cs
- Lease.cs
- storepermissionattribute.cs
- AnnotationMap.cs
- BlockingCollection.cs
- PrinterUnitConvert.cs
- HtmlTableRow.cs
- StoreItemCollection.cs
- XmlImplementation.cs
- AuditLevel.cs
- URLAttribute.cs
- UnionCqlBlock.cs
- WebPartConnectionCollection.cs
- CreateUserErrorEventArgs.cs
- Parsers.cs
- HttpRequestTraceRecord.cs
- Imaging.cs
- SqlDeflator.cs
- LoginName.cs
- Rect3D.cs
- RouteItem.cs
- MembershipAdapter.cs
- XmlSerializer.cs
- MainMenu.cs
- StreamGeometryContext.cs
- TypeKeyValue.cs
- OleDbRowUpdatingEvent.cs
- AutomationTextAttribute.cs
- TreeViewImageGenerator.cs
- PersonalizationDictionary.cs
- DLinqDataModelProvider.cs
- SettingsContext.cs
- UriParserTemplates.cs
- PageRequestManager.cs
- BamlRecordReader.cs
- DataTableMapping.cs
- SqlReferenceCollection.cs
- PathHelper.cs
- DoubleAnimationBase.cs
- WebPartUserCapability.cs
- _NegoStream.cs
- FormViewDeleteEventArgs.cs
- GenericUriParser.cs
- CommunicationException.cs
- ZeroOpNode.cs
- NonParentingControl.cs
- TypeInitializationException.cs
- SplineKeyFrames.cs
- HttpAsyncResult.cs
- Wizard.cs
- HiddenFieldPageStatePersister.cs
- UICuesEvent.cs
- AsyncCompletedEventArgs.cs
- ArraySet.cs
- StateBag.cs