// Parse:
        //              statement       --> assign-statement
        //                              --> update-statement
        //                              --> HALT
        //
        //              update-statement --> UPDATE ( "path" )
        //                               --> UPDATE ( postfix-expr )
        private RuleAction ParseStatement(ParserContext parserContext)
        {
            RuleAction action = null;
            Token statementToken = parserContext.CurrentToken;
            if (statementToken.TokenID == TokenID.Halt)
            {
                parserContext.NextToken(); // eat the "halt"
                action = new RuleHaltAction();
                parserContext.exprPositions[action] = statementToken.StartPosition;
                ValidateAction(parserContext, action);
            }
            else if (statementToken.TokenID == TokenID.Update)
            {
                string message;

                parserContext.NextToken(); // eat the "update"

                if (parserContext.CurrentToken.TokenID != TokenID.LParen)
                {
                    message = string.Format(CultureInfo.CurrentCulture, Messages.Parser_MissingLparenAfterCommand, "UPDATE");
                    throw new RuleSyntaxException(ErrorNumbers.Error_MissingLparenAfterCommand, message, parserContext.CurrentToken.StartPosition);
                }

                parserContext.NextToken(); // Eat the "("

                string pathString = null;

                Token updateArgToken = parserContext.CurrentToken;
                if (updateArgToken.TokenID == TokenID.StringLiteral)
                {
                    // Treat UPDATE("foo/bar") as a literal path.
                    pathString = (string)updateArgToken.Value;
                    parserContext.NextToken(); // Eat the path string.
                }
                else
                {
                    CodeExpression pathExpr = ParsePostfixExpression(parserContext, true, ValueCheck.Read);

                    RuleAnalysis analysis = new RuleAnalysis(validation, true);
                    RuleExpressionWalker.AnalyzeUsage(analysis, pathExpr, false, true, null);
                    ICollection<string> paths = analysis.GetSymbols();

                    if (paths.Count == 0 || paths.Count > 1)
                    {
                        // The expression did not modify anything, or it modified more than one.
                        throw new RuleSyntaxException(ErrorNumbers.Error_InvalidUpdateExpression, Messages.Parser_InvalidUpdateExpression, updateArgToken.StartPosition);
                    }
                    else
                    {
                        IEnumerator<string> enumerator = paths.GetEnumerator();
                        enumerator.MoveNext();
                        pathString = enumerator.Current;
                    }
                }

                if (parserContext.CurrentToken.TokenID != TokenID.RParen)
                    throw new RuleSyntaxException(ErrorNumbers.Error_MissingRParenAfterArgumentList, Messages.Parser_MissingRParenAfterArgumentList, parserContext.CurrentToken.StartPosition);

                parserContext.NextToken(); // Eat the ")"

                action = new RuleUpdateAction((string)pathString);
                parserContext.exprPositions[action] = statementToken.StartPosition;
                ValidateAction(parserContext, action);
            }
            else
            {
                // Try to parse a custom RuleAction.

                int savedTokenState = parserContext.SaveCurrentToken();

                Type type = TryParseTypeSpecifier(parserContext, false);

                if (type != null &&
                    parserContext.CurrentToken.TokenID == TokenID.LParen &&
                    TypeProvider.IsAssignable(typeof(RuleAction), type))
                {
                    // The statement started with a "type (", and the type derived from RuleAction.
                    // This is a custom rule action.

                    int lparenPosition = parserContext.CurrentToken.StartPosition;
                    parserContext.NextToken(); // Eat the '('

                    List<CodeExpression> arguments = ParseArgumentList(parserContext);

                    action = (RuleAction)ConstructCustomType(type, arguments, lparenPosition);

                    parserContext.exprPositions[action] = statementToken.StartPosition;
                    ValidateAction(parserContext, action);
                }
                else
                {
                    // It wasn't a custom action.
                    // In some cases it may have looked like one up to a point, such as:
                    //
                    //      MyType.MyMember(
                    //
                    // but "MyMember" is a static method.

                    // Reset the scanner state, and re-parse as an assignment.
                    parserContext.RestoreCurrentToken(savedTokenState);

                    CodeStatement statement = ParseAssignmentStatement(parserContext);
                    if (statement != null)
                    {
                        // Create a rule statement action around it.  No need to validate it, as
                        // the underlying CodeDom statement has been validated already.
                        action = new RuleStatementAction(statement);
                    }
                }
            }

            return action;
        }
 private RuleAction ParseStatement(ParserContext parserContext)
 {
     RuleAction action = null;
     Token currentToken = parserContext.CurrentToken;
     if (currentToken.TokenID == TokenID.Halt)
     {
         parserContext.NextToken();
         action = new RuleHaltAction();
         parserContext.exprPositions[action] = currentToken.StartPosition;
         this.ValidateAction(parserContext, action);
         return action;
     }
     if (currentToken.TokenID == TokenID.Update)
     {
         parserContext.NextToken();
         if (parserContext.CurrentToken.TokenID != TokenID.LParen)
         {
             string message = string.Format(CultureInfo.CurrentCulture, Messages.Parser_MissingLparenAfterCommand, new object[] { "UPDATE" });
             throw new RuleSyntaxException(0x180, message, parserContext.CurrentToken.StartPosition);
         }
         parserContext.NextToken();
         string path = null;
         Token token2 = parserContext.CurrentToken;
         if (token2.TokenID == TokenID.StringLiteral)
         {
             path = (string) token2.Value;
             parserContext.NextToken();
         }
         else
         {
             CodeExpression expression = this.ParsePostfixExpression(parserContext, true, ValueCheck.Read);
             RuleAnalysis analysis = new RuleAnalysis(this.validation, true);
             RuleExpressionWalker.AnalyzeUsage(analysis, expression, false, true, null);
             ICollection<string> symbols = analysis.GetSymbols();
             if ((symbols.Count == 0) || (symbols.Count > 1))
             {
                 throw new RuleSyntaxException(0x181, Messages.Parser_InvalidUpdateExpression, token2.StartPosition);
             }
             IEnumerator<string> enumerator = symbols.GetEnumerator();
             enumerator.MoveNext();
             path = enumerator.Current;
         }
         if (parserContext.CurrentToken.TokenID != TokenID.RParen)
         {
             throw new RuleSyntaxException(0x182, Messages.Parser_MissingRParenAfterArgumentList, parserContext.CurrentToken.StartPosition);
         }
         parserContext.NextToken();
         action = new RuleUpdateAction(path);
         parserContext.exprPositions[action] = currentToken.StartPosition;
         this.ValidateAction(parserContext, action);
         return action;
     }
     int tokenValue = parserContext.SaveCurrentToken();
     Type fromType = this.TryParseTypeSpecifier(parserContext, false);
     if (((fromType != null) && (parserContext.CurrentToken.TokenID == TokenID.LParen)) && TypeProvider.IsAssignable(typeof(RuleAction), fromType))
     {
         int startPosition = parserContext.CurrentToken.StartPosition;
         parserContext.NextToken();
         List<CodeExpression> arguments = this.ParseArgumentList(parserContext);
         action = (RuleAction) this.ConstructCustomType(fromType, arguments, startPosition);
         parserContext.exprPositions[action] = currentToken.StartPosition;
         this.ValidateAction(parserContext, action);
         return action;
     }
     parserContext.RestoreCurrentToken(tokenValue);
     CodeStatement codeDomStatement = this.ParseAssignmentStatement(parserContext);
     if (codeDomStatement != null)
     {
         action = new RuleStatementAction(codeDomStatement);
     }
     return action;
 }