示例#1
0
        public static ReturnNode Create(CodeBlockNode context, ExpressionNode expression, SequencePoint point)
        {
            var instance = new ReturnNode(point);

            instance.expression = expression;
            var returnType = context.GetMethod().MethodReturnType;

            if (expression != null)
            {
                if (returnType.TypeEquals(context.Parser.Void))
                {
                    ErrorCode.TypeMismatch.ReportAndThrow(instance.SequencePoint, "Cannot return a value in a void method");
                }

                if (!expression.ExpressionReturnType.IsAssignableTo(returnType))
                {
                    ErrorCode.TypeMismatch.ReportAndThrow(instance.SequencePoint, "Method returns {0}, cannot return {1}", returnType, expression.ExpressionReturnType);
                }

                if (!expression.IsGettable)
                {
                    ErrorCode.NotAnRValue.ReportAndThrow(point, "Returned expression must be gettable");
                }
            }
            else
            {
                if (!returnType.TypeEquals(context.Parser.Void))
                {
                    ErrorCode.TypeMismatch.ReportAndThrow(instance.SequencePoint, "Method returns {0}, must return a value", returnType);
                }
            }

            return(instance);
        }
        public static CodeBlockNode Parse(ContextNode context, IAbstractSyntaxTree lexerNode)
        {
            Contract.Requires(lexerNode.Type.IsCodeConstruct());
            CodeBlockNode instance = null;

            if (lexerNode.Type == Lexer.TokenType.CodeBlockNode)
            {
                instance = new CodeBlockNode(context, context.Parser.GetSequencePoint(lexerNode));
                foreach (var node in lexerNode.Children)
                {
                    try
                    {
                        switch (node.Type)
                        {
                        case Lexer.TokenType.LeftCurlyBrace:
                        case Lexer.TokenType.RightCurlyBrace:
                            break;

                        default:
                            instance.AddNode(node);
                            break;
                        }
                    }
                    catch (CompilerException) { }//recover, continue parsing
                }
            }
            else
            {
                instance = new CodeBlockNode(context, context.Parser.GetSequencePoint(lexerNode));
                instance.AddNode(lexerNode);
            }
            return(instance);
        }
 private ForLoopNode(CodeBlockNode init, ExpressionNode condition, CodeBlockNode increment, CodeBlockNode body, SequencePoint point)
     : base(point)
 {
     this.initializer = init;
     this.condition   = condition;
     this.increment   = increment;
     this.body        = body;
 }
        public static WhileBlock Parse(ContextNode context, IAbstractSyntaxTree lexerNode)
        {
            Contract.Requires(lexerNode.Type == TokenType.WhileLoop);
            var point     = context.Parser.GetSequencePoint(lexerNode);
            var condition = ExpressionNode.Parse(context, lexerNode.Children[2]);
            var block     = CodeBlockNode.Parse(context, lexerNode.Children[4]);

            return(Create(context, condition, block, point));
        }
 public void Emit()
 {
     parsedBody = CodeBlockNode.Parse(this, body);
     if (MethodReturnType.FullName != Parser.Void.FullName && !parsedBody.Returns)
     {
         ErrorCode.MissingReturn.ReportAndThrow(SequencePoint, "Not all control paths return a value");
     }
     if (Parser.ProjectParser.ShouldEmit)
     {
         emitter.ParseTree(parsedBody);
     }
 }
示例#6
0
        public static ReturnNode Parse(CodeBlockNode context, IAbstractSyntaxTree lexerNode)
        {
            Contract.Requires(lexerNode.Type == Lexer.TokenType.ReturnNode);
            var            point      = context.Parser.GetSequencePoint(lexerNode);
            var            returnType = context.GetMethod().MethodReturnType;
            ExpressionNode expression = null;

            if (lexerNode.Children.Count == 2)
            {
                expression = ExpressionNode.Parse(context, lexerNode.Children[1], returnType);
            }
            return(Create(context, expression, point));
        }
        public static ConditionBlockNode Parse(ContextNode context, IAbstractSyntaxTree lexerNode)
        {
            Contract.Requires(lexerNode.Type == TokenType.ConditionalSentence);
            Contract.Ensures(Contract.Result <ConditionBlockNode>() != null);
            var           point      = context.Parser.GetSequencePoint(lexerNode);
            var           condition  = ExpressionNode.Parse(context, lexerNode.Children[2]);
            var           trueBlock  = CodeBlockNode.Parse(context, lexerNode.Children[4]);
            CodeBlockNode falseBlock = null;

            if (lexerNode.Children.Count > 5)
            {
                falseBlock = CodeBlockNode.Parse(context, lexerNode.Children[6]);
            }
            return(Create(context, condition, trueBlock, falseBlock, point));
        }
        public CodeBlockNode AddNode(IAbstractSyntaxTree lexerNode)
        {
            switch (lexerNode.Type)
            {
            case Lexer.TokenType.WhileLoop:
                return(AddNode(WhileBlock.Parse(this, lexerNode)));

            case Lexer.TokenType.ConditionalSentence:
                return(AddNode(ConditionBlockNode.Parse(this, lexerNode)));

            case Lexer.TokenType.CodeBlockNode:
                return(AddNode(CodeBlockNode.Parse(this, lexerNode)));

            case Lexer.TokenType.ForLoop:
                return(AddNode(ForLoopNode.Parse(this, lexerNode)));

            case Lexer.TokenType.ForEachLoop:
                return(AddNode(ForEachNode.Parse(this, lexerNode)));

            case Lexer.TokenType.StatementWithEndOfLine:
                if (lexerNode.Children.Count == 2)
                {
                    return(AddStatement(lexerNode.Children[0]));
                }
                else
                {
                    //empty statement a.k.a ";"
                    return(this);
                }

            case Lexer.TokenType.UnknownNode:
                ErrorCode.InvalidStructure.ReportAndThrow(Parser.GetSequencePoint(lexerNode), "Could not parse as a statement");
                return(null);   //unreachable

            default:
                ErrorCode.InvalidStructure.ReportAndThrow(Parser.GetSequencePoint(lexerNode), "Unexpected node {0} in while parsing code block", lexerNode.Type);
                return(null);   //unreachable
            }
        }
        public static ForEachNode Parse(ContextNode context, IAbstractSyntaxTree lexerNode)
        {
            //For + LeftParenthesis + ForEachDeclaration + In + Value + RightParenthesis + CodeConstruct),
            Contract.Requires(lexerNode.Type == Lexer.TokenType.ForEachLoop);

            var instance = new ForEachNode(context, context.Parser.GetSequencePoint(lexerNode));

            var collection = ExpressionNode.Parse(context, lexerNode.Children[4]);

            if (!collection.IsGettable)
            {
                ErrorCode.NotAnRValue.ReportAndThrow(collection.SequencePoint, "collection must be a gettable expression");
            }
            if (collection.ExpressionReturnType.IsTypeless())
            {
                ErrorCode.InvalidForEachCollection.ReportAndThrow(collection.SequencePoint, "collection must not be a typeless expression");
            }
            var collectionElementType = collection.ExpressionReturnType.GetEnumerableElementType();

            if (collectionElementType == null)
            {
                ErrorCode.InvalidForEachCollection.ReportAndThrow(collection.SequencePoint, "Cannot iterate over expression type {0}", collection.ExpressionReturnType);
            }

            var declaration = LoopVariableDeclaration.Parse(context, lexerNode.Children[2], collectionElementType);

            if (!collectionElementType.IsAssignableTo(declaration.Variable.VariableType))
            {
                ErrorCode.TypeMismatch.ReportAndThrow(declaration.SequencePoint, "Cannot assign collection elements of type {0} to {1}", collectionElementType, declaration.Variable.VariableType);
            }

            instance.collection = collection;
            instance.variable   = declaration;

            instance.body = CodeBlockNode.Parse(instance, lexerNode.Children[6]);

            return(instance);
        }
        //context should be init block if init exists
        public static ForLoopNode Create(ContextNode context, CodeBlockNode init, ExpressionNode condition, CodeBlockNode increment, CodeBlockNode body, SequencePoint point)
        {
            if (init == null)
            {
                init = CodeBlockNode.Create(context, point);
            }

            if (condition == null)
            {
                condition = LiteralNode.Create(context, true, point);
            }

            if (increment == null)
            {
                increment = CodeBlockNode.Create(context, point);
            }

            if (!(condition.IsGettable && condition.ExpressionReturnType.IsAssignableTo(context.Parser.Bool)))
            {
                ErrorCode.InvalidCondition.ReportAndThrow(point, "Condition must be a gettable boolean expression");
            }

            return(new ForLoopNode(init, condition, increment, body, point));
        }
        public static ParserNode Parse(ContextNode context, IAbstractSyntaxTree lexerNode)
        {
            Contract.Requires(context != null);

            CodeBlockNode  init      = null;
            ExpressionNode condition = null;
            CodeBlockNode  increment = null;

            IAbstractSyntaxTree initNode      = lexerNode.Children[2];
            IAbstractSyntaxTree conditionNode = lexerNode.Children[4];
            IAbstractSyntaxTree incrementNode = lexerNode.Children[6];
            IAbstractSyntaxTree bodyNode      = lexerNode.Children[8];

            if (initNode.Type != TokenType.Empty)
            {
                init = CodeBlockNode.Create(context, context.Parser.GetSequencePoint(initNode));
                init.AddStatement(initNode);
                //makes init scope encompass for scope
                context = init;
            }

            if (conditionNode.Type != TokenType.Empty)
            {
                condition = ExpressionNode.Parse(context, conditionNode, context.Parser.Bool);
            }

            if (incrementNode.Type != TokenType.Empty)
            {
                increment = CodeBlockNode.Create(context, context.Parser.GetSequencePoint(incrementNode));
                increment.AddStatement(incrementNode);
            }

            var body = CodeBlockNode.Parse(context, bodyNode);

            return(ForLoopNode.Create(context, init, condition, increment, body, context.Parser.GetSequencePoint(lexerNode)));
        }
        public static ConditionBlockNode Create(ContextNode context, ExpressionNode condition, CodeBlockNode trueBlock, CodeBlockNode falseBlock, SequencePoint point)
        {
            var instance = new ConditionBlockNode(point);

            if (!condition.IsGettable || !condition.ExpressionReturnType.IsAssignableTo(context.Parser.Bool))
            {
                ErrorCode.InvalidCondition.ReportAndThrow(point, "Condition must be a gettable boolean expression");
            }
            instance.condition  = condition;
            instance.trueBlock  = trueBlock;
            instance.falseBlock = falseBlock;
            return(instance);
        }
        public static WhileBlock Create(ContextNode context, ExpressionNode condition, CodeBlockNode body, SequencePoint point)
        {
            var instance = new WhileBlock(point);

            if (!condition.IsGettable || !condition.ExpressionReturnType.TypeEquals(context.Parser.Bool))
            {
                ErrorCode.InvalidCondition.ReportAndThrow(point, "Condition must be a gettable boolean expression");
            }
            instance.condition = condition;
            instance.block     = body;
            return(instance);
        }