Ejemplo n.º 1
0
        // Parse nested types.
        private Type ParseNestedType(ParserContext parserContext, Type currentType)
        {
            System.Diagnostics.Debug.Assert(parserContext.CurrentToken.TokenID == TokenID.Dot);

            Type nestedType = null;

            while (parserContext.CurrentToken.TokenID == TokenID.Dot)
            {
                // Save the state of the scanner.  Since we can't tell if we're parsing a nested
                // type or a member, we'll need to backtrack if we go too far.
                int savedTokenState = parserContext.SaveCurrentToken();

                Token token = parserContext.NextToken();
                if (token.TokenID != TokenID.Identifier)
                {
                    if (parserContext.provideIntellisense && token.TokenID == TokenID.EndOfInput)
                    {
                        parserContext.SetTypeMemberCompletions(currentType, validation.ThisType, true, validation);
                        return null;
                    }
                    else
                    {
                        throw new RuleSyntaxException(ErrorNumbers.Error_MissingIdentifierAfterDot, Messages.Parser_MissingIdentifierAfterDot, parserContext.CurrentToken.StartPosition);
                    }
                }

                string name = (string)token.Value;

                BindingFlags bindingFlags = BindingFlags.Public;
                if (currentType.Assembly == validation.ThisType.Assembly)
                    bindingFlags |= BindingFlags.NonPublic;

                if (parserContext.NextToken().TokenID == TokenID.Less)
                {
                    // Might be a generic type.
                    List<Type> candidateGenericTypes = new List<Type>();

                    Type[] nestedTypes = currentType.GetNestedTypes(bindingFlags);
                    string prefix = name + "`";
                    for (int i = 0; i < nestedTypes.Length; ++i)
                    {
                        Type candidateType = nestedTypes[i];
                        if (candidateType.Name.StartsWith(prefix, StringComparison.Ordinal))
                            candidateGenericTypes.Add(candidateType);
                    }

                    if (candidateGenericTypes.Count == 0)
                    {
                        // It wasn't a generic type.  Reset the scanner to the saved state.
                        parserContext.RestoreCurrentToken(savedTokenState);
                        // Also reset the deepenst nested type.
                        nestedType = currentType;
                        break;
                    }

                    nestedType = ParseGenericType(parserContext, candidateGenericTypes, name);
                    currentType = nestedType;
                }
                else
                {
                    // Might be a non-generic type.
                    MemberInfo[] mi = currentType.GetMember(name, bindingFlags);
                    if (mi == null || mi.Length != 1 || (mi[0].MemberType != MemberTypes.NestedType && mi[0].MemberType != MemberTypes.TypeInfo))
                    {
                        // We went too far, reset the state.
                        parserContext.RestoreCurrentToken(savedTokenState);
                        // Also reset the deepest nested type.
                        nestedType = currentType;
                        break;
                    }

                    nestedType = (Type)mi[0];

                    if (currentType.IsGenericType && nestedType.IsGenericTypeDefinition)
                    {
                        // The outer type was generic (and bound), but the nested type is not.  We have
                        // to re-bind the generic arguments.
                        nestedType = nestedType.MakeGenericType(currentType.GetGenericArguments());
                    }

                    currentType = nestedType;
                }
            }

            return nestedType;
        }
Ejemplo n.º 2
0
        // Parse:
        //              unary-expression --> unary-operator unary-expression
        //                               --> postfix-expression
        private CodeExpression ParseUnaryExpression(ParserContext parserContext, bool assignIsEquality, ValueCheck check)
        {
            Token currentToken = parserContext.CurrentToken;

            CodeExpression unaryResult = null;
            if (currentToken.TokenID == TokenID.Not)
            {
                int notPosition = currentToken.StartPosition;
                parserContext.NextToken();

                unaryResult = ParseUnaryExpression(parserContext, true, check);

                // This becomes "subExpr == false"
                unaryResult = new CodeBinaryOperatorExpression(unaryResult, CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(false));
                parserContext.exprPositions[unaryResult] = notPosition;
                ValidateExpression(parserContext, unaryResult, assignIsEquality, check);
            }
            else if (currentToken.TokenID == TokenID.Minus)
            {
                int negativePosition = currentToken.StartPosition;
                parserContext.NextToken();

                unaryResult = ParseUnaryExpression(parserContext, true, check);

                // This becomes "0 - subExpr"
                unaryResult = new CodeBinaryOperatorExpression(new CodePrimitiveExpression(0), CodeBinaryOperatorType.Subtract, unaryResult);
                parserContext.exprPositions[unaryResult] = negativePosition;
                ValidateExpression(parserContext, unaryResult, assignIsEquality, check);
            }
            else if (currentToken.TokenID == TokenID.LParen)
            {
                int lparenPosition = currentToken.StartPosition;

                // Save the state.  This may actually be a parenthesized subexpression.
                int savedTokenState = parserContext.SaveCurrentToken();

                currentToken = parserContext.NextToken(); // Eat the '('

                Type type = TryParseTypeSpecifier(parserContext, assignIsEquality);

                if (type == null || parserContext.CurrentToken.TokenID != TokenID.RParen)
                {
                    // It wasn't a cast.
                    // In some cases it may have looked like a cast up to a point, such as:
                    //
                    //      (MyType.MyMember
                    //
                    // but "MyMember" is a static field, property, or enum.

                    // Reset the scanner state, and re-parse as a postfix-expr
                    parserContext.RestoreCurrentToken(savedTokenState);
                    unaryResult = ParsePostfixExpression(parserContext, assignIsEquality, check);
                }
                else
                {
                    // It is a cast.  It must have a balancing ')'.
                    if (parserContext.CurrentToken.TokenID != TokenID.RParen)
                        throw new RuleSyntaxException(ErrorNumbers.Error_MissingRParenInSubexpression, Messages.Parser_MissingRParenInSubexpression, parserContext.CurrentToken.StartPosition);

                    parserContext.NextToken();

                    unaryResult = ParseUnaryExpression(parserContext, true, check);

                    CodeTypeReference typeRef = new CodeTypeReference(type);
                    validation.AddTypeReference(typeRef, type);

                    unaryResult = new CodeCastExpression(typeRef, unaryResult);
                    parserContext.exprPositions[unaryResult] = lparenPosition;
                    ValidateExpression(parserContext, unaryResult, assignIsEquality, check);
                }
            }
            else
            {
                unaryResult = ParsePostfixExpression(parserContext, assignIsEquality, check);
            }

            return unaryResult;
        }
Ejemplo n.º 3
0
        // 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 Type ParseNestedType(ParserContext parserContext, Type currentType)
 {
     Type type = null;
     while (parserContext.CurrentToken.TokenID == TokenID.Dot)
     {
         int tokenValue = parserContext.SaveCurrentToken();
         Token token = parserContext.NextToken();
         if (token.TokenID != TokenID.Identifier)
         {
             if (!parserContext.provideIntellisense || (token.TokenID != TokenID.EndOfInput))
             {
                 throw new RuleSyntaxException(0x185, Messages.Parser_MissingIdentifierAfterDot, parserContext.CurrentToken.StartPosition);
             }
             parserContext.SetTypeMemberCompletions(currentType, this.validation.ThisType, true, this.validation);
             return null;
         }
         string typeName = (string) token.Value;
         BindingFlags @public = BindingFlags.Public;
         if (currentType.Assembly == this.validation.ThisType.Assembly)
         {
             @public |= BindingFlags.NonPublic;
         }
         if (parserContext.NextToken().TokenID == TokenID.Less)
         {
             List<Type> candidateGenericTypes = new List<Type>();
             Type[] nestedTypes = currentType.GetNestedTypes(@public);
             string str2 = typeName + "`";
             for (int i = 0; i < nestedTypes.Length; i++)
             {
                 Type item = nestedTypes[i];
                 if (item.Name.StartsWith(str2, StringComparison.Ordinal))
                 {
                     candidateGenericTypes.Add(item);
                 }
             }
             if (candidateGenericTypes.Count == 0)
             {
                 parserContext.RestoreCurrentToken(tokenValue);
                 return currentType;
             }
             type = this.ParseGenericType(parserContext, candidateGenericTypes, typeName);
             currentType = type;
         }
         else
         {
             MemberInfo[] member = currentType.GetMember(typeName, @public);
             if (((member == null) || (member.Length != 1)) || ((member[0].MemberType != MemberTypes.NestedType) && (member[0].MemberType != MemberTypes.TypeInfo)))
             {
                 parserContext.RestoreCurrentToken(tokenValue);
                 return currentType;
             }
             type = (Type) member[0];
             if (currentType.IsGenericType && type.IsGenericTypeDefinition)
             {
                 type = type.MakeGenericType(currentType.GetGenericArguments());
             }
             currentType = type;
         }
     }
     return type;
 }
 private CodeExpression ParseUnaryExpression(ParserContext parserContext, bool assignIsEquality, ValueCheck check)
 {
     Token currentToken = parserContext.CurrentToken;
     CodeExpression expression = null;
     if (currentToken.TokenID == TokenID.Not)
     {
         int startPosition = currentToken.StartPosition;
         parserContext.NextToken();
         expression = new CodeBinaryOperatorExpression(this.ParseUnaryExpression(parserContext, true, check), CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(false));
         parserContext.exprPositions[expression] = startPosition;
         this.ValidateExpression(parserContext, expression, assignIsEquality, check);
         return expression;
     }
     if (currentToken.TokenID == TokenID.Minus)
     {
         int num2 = currentToken.StartPosition;
         parserContext.NextToken();
         expression = this.ParseUnaryExpression(parserContext, true, check);
         expression = new CodeBinaryOperatorExpression(new CodePrimitiveExpression(0), CodeBinaryOperatorType.Subtract, expression);
         parserContext.exprPositions[expression] = num2;
         this.ValidateExpression(parserContext, expression, assignIsEquality, check);
         return expression;
     }
     if (currentToken.TokenID == TokenID.LParen)
     {
         int num3 = currentToken.StartPosition;
         int tokenValue = parserContext.SaveCurrentToken();
         currentToken = parserContext.NextToken();
         Type type = this.TryParseTypeSpecifier(parserContext, assignIsEquality);
         if ((type == null) || (parserContext.CurrentToken.TokenID != TokenID.RParen))
         {
             parserContext.RestoreCurrentToken(tokenValue);
             return this.ParsePostfixExpression(parserContext, assignIsEquality, check);
         }
         if (parserContext.CurrentToken.TokenID != TokenID.RParen)
         {
             throw new RuleSyntaxException(0x184, Messages.Parser_MissingRParenInSubexpression, parserContext.CurrentToken.StartPosition);
         }
         parserContext.NextToken();
         expression = this.ParseUnaryExpression(parserContext, true, check);
         CodeTypeReference typeRef = new CodeTypeReference(type);
         this.validation.AddTypeReference(typeRef, type);
         expression = new CodeCastExpression(typeRef, expression);
         parserContext.exprPositions[expression] = num3;
         this.ValidateExpression(parserContext, expression, assignIsEquality, check);
         return expression;
     }
     return this.ParsePostfixExpression(parserContext, assignIsEquality, check);
 }
 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;
 }