public void BooleanAND()
 {
     AST root = new AST(new Token(Token.TokenType.OPERATOR, "&&"));
     AST lhs = new AST(new Token(Token.TokenType.NUMBER, "1"));
     AST rhs = new AST(new Token(Token.TokenType.NUMBER, "0"));
     root.addChild(lhs);
     root.addChild(rhs);
     ExpressionEvaluator e = new ExpressionEvaluator(root);
     Assert.AreEqual(0, e.getValue());
 }
 public void BooleanGREATEROREQUALS2()
 {
     AST root = new AST(new Token(Token.TokenType.OPERATOR, ">="));
     AST lhs = new AST(new Token(Token.TokenType.NUMBER, "4"));
     AST rhs = new AST(new Token(Token.TokenType.NUMBER, "3"));
     root.addChild(lhs);
     root.addChild(rhs);
     ExpressionEvaluator e = new ExpressionEvaluator(root);
     Assert.AreEqual(1, e.getValue());
 }
예제 #3
0
        private AST createParameterDefinition(string typeName, string variableName)
        {
            AST parameter = new AST(new Token(Token.TokenType.PARAMETER, "<PARAMETER>"));

            AST declaration = new AST_VariableDeclaration(new Token(Token.TokenType.VAR_DECLARATION, "<PARAMETER_DECLARATION>"), ReturnValue.getReturnValueTypeFromString(typeName), variableName);
            AST assigment = new AST_Assignment(new Token(Token.TokenType.ASSIGNMENT, "="), variableName);

            parameter.addChild(declaration);
            parameter.addChild(assigment);

            return parameter;
        }
예제 #4
0
        private void defineFunction(FunctionDefinition f)
        {
            if (externalFunctions.ContainsKey(f.functionName))
            {
                throw new Error("There is already a function called '" + f.functionName + "'", Error.ErrorType.UNDEFINED, 0, 0);
            }

            AST parameterList = new AST(new Token(Token.TokenType.NODE_GROUP, "<PARAMETER_LIST>"));
            for (int i = 0; i < f.parameterTypes.Length; ++i)
            {
                parameterList.addChild(createParameterDefinition(f.parameterTypes[i], f.parameterNames[i]));
            }

            AST functionNode = createFunctionDefinitionNode(f.returnType, f.functionName, parameterList);

            m_builtInFunctions.Add(functionNode);
            externalFunctions.Add(f.functionName, f.callback);
        }
예제 #5
0
        private ExternalFunctionCreator AddExternalFunctions(FunctionDefinition[] functionDefinitions, AST ast)
        {
            List <FunctionDefinition> allFunctionDefinitions = new List <FunctionDefinition>();

            allFunctionDefinitions.AddRange(builtInFunctions);
            allFunctionDefinitions.AddRange(functionDefinitions);

            // HasFunction requires a reference to the SprakRunner
            FunctionDocumentation functionDoc_HasFunction =
                new FunctionDocumentation("Check if a function exists on the object", new string[] { "The name of the function" });

            allFunctionDefinitions.Add(new FunctionDefinition("bool", "HasFunction", new string[] { "string" }, new string[] { "functionName" }, new ExternalFunctionCreator.OnFunctionCall(API_hasFunction), functionDoc_HasFunction));

            ExternalFunctionCreator externalFunctionCreator = new ExternalFunctionCreator(allFunctionDefinitions.ToArray());
            AST functionList = ast.getChild(1);

            foreach (AST externalFunction in externalFunctionCreator.FunctionASTs)
            {
                functionList.addChild(externalFunction);
            }

            return(externalFunctionCreator);
        }
예제 #6
0
        private AST booleanExpression()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("boolean expression");
            #endif

            AST lhs = comparisonExpression();

            if ( lookAhead(1).getTokenString() == "&&" ||
                 lookAhead(1).getTokenString() == "||"
                )
            {
                Token operatorToken = match(Token.TokenType.OPERATOR);
                //Console.WriteLine ("Matched operator token " + operatorToken.getTokenString() + " at line " + operatorToken.LineNr + " and pos " + operatorToken.LinePosition);

                AST rhs = booleanExpression();
                checkLeftHandSide(lhs, operatorToken);
                checkRightHandSide(rhs, operatorToken);

                AST booleanExpressionTree = new AST(operatorToken);
                booleanExpressionTree.addChild(lhs);
                booleanExpressionTree.addChild(rhs);
                return booleanExpressionTree;

            } else {
                return lhs;
            }
        }
예제 #7
0
파일: Parser.cs 프로젝트: substans/Sprak
        private AST loop()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("loop");
            #endif
            AST loopBlockStatements = new AST(new Token(Token.TokenType.STATEMENT_LIST, "<LOOP_BLOCK_STATEMENTS>"));

            AST_LoopNode loopTree = new AST_LoopNode(match(Token.TokenType.LOOP));

            bool isForeachLoop = false;
            if(lookAheadType(1) != Token.TokenType.NEW_LINE)
            {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("foreach loop!");
            #endif
                isForeachLoop = true;

                // __index__
                AST_VariableDeclaration loopIndexDeclaration
                = new AST_VariableDeclaration(new Token(Token.TokenType.VAR_DECLARATION, "<VAR_DECL>"),
                                                        ReturnValueType.NUMBER,
                                                        "__index__");
                loopBlockStatements.addChild(loopIndexDeclaration);

                AST_Assignment loopIndexAssignment
                    = new AST_Assignment(new Token(Token.TokenType.ASSIGNMENT, "="), "__index__");
                loopIndexAssignment.addChild(new AST(new TokenWithValue(Token.TokenType.NUMBER, "-1", new ReturnValue(-1.0f))));

                loopBlockStatements.addChild(loopIndexAssignment);

                // match
                //match(Token.TokenType.PARANTHESIS_LEFT);
                AST arrayExpression = expression();
                //match(Token.TokenType.PARANTHESIS_RIGHT);

                // __array__ (is a copy of the array to loop over)
                AST_VariableDeclaration loopArrayDeclaration
                = new AST_VariableDeclaration(new Token(Token.TokenType.VAR_DECLARATION, "<VAR_DECL>"),
                                                        ReturnValueType.ARRAY,
                                                        "__array__");
                loopBlockStatements.addChild(loopArrayDeclaration);

                AST_Assignment loopArrayAssignment =
                    new AST_Assignment(new Token(Token.TokenType.ASSIGNMENT, "="), "__array__");

                if(arrayExpression != null) {
                    loopArrayAssignment.addChild(arrayExpression);
                }
                else {
                    throw new Error("Can't understand array expression in loop", Error.ErrorType.SYNTAX,
                                    loopArrayAssignment.getToken().LineNr,
                                    loopArrayAssignment.getToken().LinePosition);
                }

                loopBlockStatements.addChild(loopArrayAssignment);

                // __indexes__ (holds all the indexes in the array, since it works like a SortedDictionary)
                // __indexes = getIndexes(__array__)
                AST_VariableDeclaration indexesDeclaration
                = new AST_VariableDeclaration(new Token(Token.TokenType.VAR_DECLARATION, "<VAR_DECL>"),
                                                        ReturnValueType.ARRAY,
                                                        "__indexes__");
                loopBlockStatements.addChild(indexesDeclaration);

                AST_FunctionCall getArrayIndexes = new AST_FunctionCall(new Token(Token.TokenType.FUNCTION_CALL,
                                                                                  "getIndexes"));
                AST argumentList = new AST(new Token(Token.TokenType.NODE_GROUP, "<ARGUMENT_LIST>"));
                argumentList.addChild(new Token(Token.TokenType.NAME, "__array__"));
                getArrayIndexes.addChild(argumentList);

                AST_Assignment indexesAssignment =
                new AST_Assignment(new Token(Token.TokenType.ASSIGNMENT, "="), "__indexes__");
                indexesAssignment.addChild(getArrayIndexes);
                loopBlockStatements.addChild(indexesAssignment);
            }
            else
            {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("infinite loop!");
            #endif
            }

            /*
             * 		loopParentTree
             * 			__index__-declaration
             * 			__array__-declaration & assigment
             * 			loop tree
             * 				loop body
             * 					foreach stuff
             * 					rest of statements
             * 					goto beginning of loop
             *
             * */

            allowLineBreak();
            AST loopBody = statementList(false);
            loopBody.addChild(new AST(new Token(Token.TokenType.GOTO_BEGINNING_OF_LOOP, "<GOTO_BEGINNING_OF_LOOP>")));
            allowLineBreak();
            match(Token.TokenType.BLOCK_END);

            if(isForeachLoop) {
                loopBody.addChildFirst(foreachStuff());
            }

            loopTree.addChild(loopBody);

            loopBlockStatements.addChild(loopTree);

            AST_LoopBlockNode loopBlock = new AST_LoopBlockNode(new Token(Token.TokenType.LOOP_BLOCK, "<LOOP_BLOCK>"));
            loopBlock.addChild(loopBlockStatements);

            return loopBlock;
        }
예제 #8
0
        private AST ifThenElse()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("if block");
            #endif
            AST ifThenElseTree;
            AST trueChild;
            AST falseChild = null;
            AST expr;

            try {
                Token ifToken = match(Token.TokenType.IF);
                expr = expression(); // child 0

                if (expr == null) {
                    throw new Error("The if statement is missing an expression after the 'if'", Error.ErrorType.SYNTAX, ifToken.LineNr, ifToken.LinePosition);
                }

                if(lookAheadType(1) == Token.TokenType.NEW_LINE) {
                    match(Token.TokenType.NEW_LINE);
                }
                else {
                    throw new Error("Found assignment (=) in if statement. Use == instead?", Error.ErrorType.SYNTAX, ifToken.LineNr, ifToken.LinePosition);
                }

                trueChild = statementList(false); // child 1

                if ((lookAheadType(1) == Token.TokenType.ELSE) && (lookAheadType(2) == Token.TokenType.IF)) {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("if else block");
            #endif
                    match(Token.TokenType.ELSE);
                    var ifElseBranch = statement(); // ifThenElse();
                    // have to put it into a statement list to make scopes work
                    falseChild = new AST(new Token(Token.TokenType.STATEMENT_LIST, "<STATEMENT_LIST>"));
                    if(ifElseBranch != null) {
                        falseChild.addChild(ifElseBranch);
                    }
            #if WRITE_DEBUG_INFO
            Console.WriteLine("Popping out from ifElse branch");
            #endif
                }
                else if (lookAheadType(1) == Token.TokenType.ELSE) {
            #if WRITE_DEBUG_INFO
                    Console.WriteLine("else block");
            #endif
                    match(Token.TokenType.ELSE);

                    if(lookAhead(1).getTokenType() == Token.TokenType.NEW_LINE) {
                        match(Token.TokenType.NEW_LINE);
                    } else {
                        throw new Error("The else statement is missing a line break after it", Error.ErrorType.SYNTAX, ifToken.LineNr, ifToken.LinePosition);
                    }

                    falseChild = statementList(false); // child 2

                    if(lookAhead(1).getTokenType() == Token.TokenType.BLOCK_END) {
                        match(Token.TokenType.BLOCK_END);
                    } else {
                        throw new Error("The if statement is missing a following 'end'", Error.ErrorType.SYNTAX, ifToken.LineNr, ifToken.LinePosition);
                    }
                }
                else {
            #if WRITE_DEBUG_INFO
                    Console.WriteLine("no else block");
            #endif
                    if(lookAhead(1).getTokenType() == Token.TokenType.BLOCK_END) {
                        match(Token.TokenType.BLOCK_END);
                    } else {
                        throw new Error("The if statement is missing a following 'end'", Error.ErrorType.SYNTAX, ifToken.LineNr, ifToken.LinePosition);
                    }
                }
            }
            catch(Error e) {
                // The error caught here will probably be from the match() function.
                // Since that means we're missing some part of the if-statement we can give a better
                // error message by throwing a new one.
                throw e; // new Error("Something is wrong with the IF-statement", Error.ErrorType.SYNTAX, e.getLineNr(), e.getLinePosition());
            }

            ifThenElseTree = new AST_IfNode(new Token(Token.TokenType.IF, "if", lookAhead(1).LineNr, lookAhead(1).LinePosition));
            ifThenElseTree.addChild (expr);

            ifThenElseTree.addChild(trueChild);
            if (falseChild != null)
            {
                ifThenElseTree.addChild(falseChild);
            }

            return ifThenElseTree;
        }
예제 #9
0
        private AST fromMinToMaxArrayCreation()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("fromMinToMaxArrayCreation");
            #endif

            try {
                Token fromToken = match(Token.TokenType.FROM);

                AST minValue = expression();

                if(minValue == null) { throw new Error("Missing expression after 'from'",
                                             	Error.ErrorType.SYNTAX,
                                                    fromToken.LineNr, fromToken.LinePosition + 5 ); }

                match(Token.TokenType.TO);
                AST maxValue = expression();

                if(maxValue == null) { throw new Error("Missing expression after 'to'",
                                             	Error.ErrorType.SYNTAX,
                                                    fromToken.LineNr, fromToken.LinePosition + 3 ); }

                AST_FunctionCall callRangeFunction = new AST_FunctionCall(new Token(Token.TokenType.FUNCTION_CALL, "Range"));
                AST argumentList = new AST(new Token(Token.TokenType.NODE_GROUP, "<ARGUMENT_LIST>"));
                argumentList.addChild(minValue);
                argumentList.addChild(maxValue);
                callRangeFunction.addChild(argumentList);

                return callRangeFunction;
            }
            catch(Error e) {
                m_errorHandler.errorOccured(e);
                return null;
            }
        }
예제 #10
0
        private AST dotNotationExpression()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("dot notation expression");
            #endif

            AST lhs = parenthesisExpression();

            if ( lookAhead(1).getTokenType() == Token.TokenType.DOT)
            {
                match (Token.TokenType.DOT);

                #if WRITE_DEBUG_INFO
                Console.WriteLine("It's a dot notation expression!!! for example: object.f(a, b)");
                #endif

                Token nameToken = match(Token.TokenType.NAME);

                AST functionCallTree =
                    new AST_FunctionCall(new Token(Token.TokenType.FUNCTION_CALL, "RemoteFunctionCall", nameToken.LineNr, nameToken.LinePosition));

                // These are the argument sent through the remote function call
                AST innerArgumentList = FunctionArgumentList ();

                // The call to RemoteFunctionCall always takes three args: <id>, <functionName> & <args>
                AST argumentList = new AST (new Token (Token.TokenType.NODE_GROUP, "<ARGUMENT_LIST>"));

                // <ID>
                argumentList.addChild (lhs); // use whatever is on the left side of the dot in the function (method rather) call (.)
                //Console.WriteLine ("Method call ID: ");
                //(new ASTPainter()).PaintAST(lhs);

                // <FunctionName>
                Token functionNameToken = new TokenWithValue (
                    Token.TokenType.QUOTED_STRING,
                    nameToken.getTokenString (),
                    nameToken.LineNr,
                    nameToken.LinePosition,
                    nameToken.getTokenString());

                argumentList.addChild (new AST(functionNameToken));

                // <args>
                AST_ArrayEndSignal argsArray = new AST_ArrayEndSignal(new Token(Token.TokenType.ARRAY_END_SIGNAL, "<ARRAY>"));
                //Console.WriteLine ("Inner args:");
                foreach (var child in innerArgumentList.getChildren()) {
                    //Console.WriteLine (child.getTokenString ());
                    argsArray.addChild (child);
                }
                argsArray.ArraySize = innerArgumentList.getChildren().Count; // DAMNIT DON'T FORGET THIS ONE
                argumentList.addChild (argsArray); // send the arguments as an array to RemoteFunctionCall

                functionCallTree.addChild(argumentList);
                return functionCallTree;
            } else {
                return lhs;
            }
        }
예제 #11
0
        private AST parameter()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("parameter");
            #endif

            AST parameterTree = new AST(new Token(Token.TokenType.PARAMETER, "<PARAMETER>", lookAhead(1).LineNr, lookAhead(1).LinePosition));

            AST type = null;

            if(lookAheadType(1) == Token.TokenType.BUILT_IN_TYPE_NAME) {
                type = new AST(match(Token.TokenType.BUILT_IN_TYPE_NAME));
            } else {
                type = new AST(new Token(Token.TokenType.BUILT_IN_TYPE_NAME, "var"));
            }
            AST name = new AST(match(Token.TokenType.NAME));

            AST declaration = new AST_VariableDeclaration(new Token(Token.TokenType.VAR_DECLARATION, "<PARAMETER_DECLARATION>"),
                                                          ExternalFunctionCreator.GetReturnTypeFromString(type.getTokenString()), name.getTokenString());

            AST assigment = new AST_Assignment(new Token(Token.TokenType.ASSIGNMENT, "="), name.getTokenString());

            parameterTree.addChild(declaration);
            parameterTree.addChild(assigment);

            return parameterTree;
        }
예제 #12
0
        private AST negativeExpression()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("negative expression");
            #endif
            match(Token.TokenType.OPERATOR); // the minus sign

            AST negativeExpressionTree = new AST(new Token(Token.TokenType.OPERATOR, "*"));

            AST minusSign = new AST(new TokenWithValue(Token.TokenType.NUMBER, "-1", lookAhead(1).LineNr, lookAhead(1).LinePosition, -1.0f));
            AST expressionTree = parenthesisExpression();
            //operand();
            negativeExpressionTree.addChild(minusSign);
            negativeExpressionTree.addChild(expressionTree);

            return negativeExpressionTree;
        }
예제 #13
0
파일: Parser.cs 프로젝트: eriksvedang/Sprak
 private AST notStatement()
 {
     var notAST = new AST(match(Token.TokenType.NOT));
     var expr = expression();
     notAST.addChild(expr);
     return notAST;
 }
예제 #14
0
파일: Parser.cs 프로젝트: substans/Sprak
        private AST functionCall()
        {
#if WRITE_DEBUG_INFO
            Console.WriteLine("function call");
#endif

            Token nameToken = match(Token.TokenType.NAME);

            AST functionCallTree =
                new AST_FunctionCall(new Token(Token.TokenType.FUNCTION_CALL, nameToken.getTokenString(), nameToken.LineNr, nameToken.LinePosition));

            match(Token.TokenType.PARANTHESIS_LEFT);

            functionCallTree.getToken().LineNr       = nameToken.LineNr;
            functionCallTree.getToken().LinePosition = nameToken.LinePosition;

            AST argumentList = new AST(new Token(Token.TokenType.NODE_GROUP, "<ARGUMENT_LIST>"));

            if (lookAheadType(1) != Token.TokenType.PARANTHESIS_RIGHT)
            {
                while (true)
                {
                    AST expressionTree = expression();

                    if (expressionTree != null)
                    {
                        argumentList.addChild(expressionTree);                         // add arguments as subtrees
                    }
                    else
                    {
                        throw new Error("Something is wrong with the argument list", Error.ErrorType.SYNTAX,
                                        lookAhead(1).LineNr, lookAhead(1).LinePosition);
                    }

                    if (lookAheadType(1) == Token.TokenType.COMMA)
                    {
                        match(Token.TokenType.COMMA);
                        continue;
                    }
                    else
                    {
                        // Is something wrong?
                        if (lookAheadType(1) == Token.TokenType.NEW_LINE ||
                            lookAheadType(1) == Token.TokenType.EOF)
                        {
                            throw new Error("Ending parenthesis is missing in function call"
                                            , Error.ErrorType.SYNTAX,
                                            lookAhead(1).LineNr, lookAhead(1).LinePosition);
                        }
                        else if (lookAheadType(1) == Token.TokenType.NAME ||
                                 lookAheadType(1) == Token.TokenType.QUOTED_STRING ||
                                 lookAheadType(1) == Token.TokenType.NUMBER)
                        {
                            throw new Error("A comma is missing in argument list"
                                            , Error.ErrorType.SYNTAX,
                                            lookAhead(1).LineNr, lookAhead(1).LinePosition);
                        }

                        break;
                    }
                }
            }

            match(Token.TokenType.PARANTHESIS_RIGHT);

            functionCallTree.addChild(argumentList);

            return(functionCallTree);
        }
예제 #15
0
파일: Parser.cs 프로젝트: substans/Sprak
        private AST loop()
        {
#if WRITE_DEBUG_INFO
            Console.WriteLine("loop");
#endif
            AST loopBlockStatements = new AST(new Token(Token.TokenType.STATEMENT_LIST, "<LOOP_BLOCK_STATEMENTS>"));

            AST_LoopNode loopTree = new AST_LoopNode(match(Token.TokenType.LOOP));

            bool isForeachLoop = false;
            if (lookAheadType(1) != Token.TokenType.NEW_LINE)
            {
#if WRITE_DEBUG_INFO
                Console.WriteLine("foreach loop!");
#endif
                isForeachLoop = true;

                // __index__
                AST_VariableDeclaration loopIndexDeclaration
                    = new AST_VariableDeclaration(new Token(Token.TokenType.VAR_DECLARATION, "<VAR_DECL>"),
                                                  ReturnValueType.NUMBER,
                                                  "__index__");
                loopBlockStatements.addChild(loopIndexDeclaration);

                AST_Assignment loopIndexAssignment
                    = new AST_Assignment(new Token(Token.TokenType.ASSIGNMENT, "="), "__index__");
                loopIndexAssignment.addChild(new AST(new TokenWithValue(Token.TokenType.NUMBER, "-1", new ReturnValue(-1.0f))));

                loopBlockStatements.addChild(loopIndexAssignment);

                // match
                //match(Token.TokenType.PARANTHESIS_LEFT);
                AST arrayExpression = expression();
                //match(Token.TokenType.PARANTHESIS_RIGHT);

                // __array__ (is a copy of the array to loop over)
                AST_VariableDeclaration loopArrayDeclaration
                    = new AST_VariableDeclaration(new Token(Token.TokenType.VAR_DECLARATION, "<VAR_DECL>"),
                                                  ReturnValueType.ARRAY,
                                                  "__array__");
                loopBlockStatements.addChild(loopArrayDeclaration);

                AST_Assignment loopArrayAssignment =
                    new AST_Assignment(new Token(Token.TokenType.ASSIGNMENT, "="), "__array__");

                if (arrayExpression != null)
                {
                    loopArrayAssignment.addChild(arrayExpression);
                }
                else
                {
                    throw new Error("Can't understand array expression in loop", Error.ErrorType.SYNTAX,
                                    loopArrayAssignment.getToken().LineNr,
                                    loopArrayAssignment.getToken().LinePosition);
                }

                loopBlockStatements.addChild(loopArrayAssignment);

                // __indexes__ (holds all the indexes in the array, since it works like a SortedDictionary)
                // __indexes = getIndexes(__array__)
                AST_VariableDeclaration indexesDeclaration
                    = new AST_VariableDeclaration(new Token(Token.TokenType.VAR_DECLARATION, "<VAR_DECL>"),
                                                  ReturnValueType.ARRAY,
                                                  "__indexes__");
                loopBlockStatements.addChild(indexesDeclaration);

                AST_FunctionCall getArrayIndexes = new AST_FunctionCall(new Token(Token.TokenType.FUNCTION_CALL,
                                                                                  "getIndexes"));
                AST argumentList = new AST(new Token(Token.TokenType.NODE_GROUP, "<ARGUMENT_LIST>"));
                argumentList.addChild(new Token(Token.TokenType.NAME, "__array__"));
                getArrayIndexes.addChild(argumentList);

                AST_Assignment indexesAssignment =
                    new AST_Assignment(new Token(Token.TokenType.ASSIGNMENT, "="), "__indexes__");
                indexesAssignment.addChild(getArrayIndexes);
                loopBlockStatements.addChild(indexesAssignment);
            }
            else
            {
#if WRITE_DEBUG_INFO
                Console.WriteLine("infinite loop!");
#endif
            }

            /*
             *      loopParentTree
             *          __index__-declaration
             *          __array__-declaration & assigment
             *          loop tree
             *              loop body
             *                  foreach stuff
             *                  rest of statements
             *                  goto beginning of loop
             *
             * */

            allowLineBreak();
            AST loopBody = statementList(false);
            loopBody.addChild(new AST(new Token(Token.TokenType.GOTO_BEGINNING_OF_LOOP, "<GOTO_BEGINNING_OF_LOOP>")));
            allowLineBreak();
            match(Token.TokenType.BLOCK_END);

            if (isForeachLoop)
            {
                loopBody.addChildFirst(foreachStuff());
            }

            loopTree.addChild(loopBody);

            loopBlockStatements.addChild(loopTree);

            AST_LoopBlockNode loopBlock = new AST_LoopBlockNode(new Token(Token.TokenType.LOOP_BLOCK, "<LOOP_BLOCK>"));
            loopBlock.addChild(loopBlockStatements);

            return(loopBlock);
        }
예제 #16
0
        private AST comparisonExpression()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("comparison expression");
            #endif

            AST lhs = plusOrMinusExpression();

            if ( lookAhead(1).getTokenString() == "<" ||
                 lookAhead(1).getTokenString() == ">" ||
                 lookAhead(1).getTokenString() == "<=" ||
                 lookAhead(1).getTokenString() == ">=" ||
                 lookAhead(1).getTokenString() == "!=" ||
                 lookAhead(1).getTokenString() == "=="
                )
            {
                Token operatorToken = match(Token.TokenType.OPERATOR);
                AST rhs = plusOrMinusExpression();
                checkLeftHandSide(lhs, operatorToken);
                checkRightHandSide(rhs, operatorToken);

                AST comparisonExpressionTree = new AST(operatorToken);
                comparisonExpressionTree.addChild(lhs);
                comparisonExpressionTree.addChild(rhs);
                return comparisonExpressionTree;

            } else {
                return lhs;
            }
        }
예제 #17
0
        private AST declarationAndAssignment()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("declaration and assignment");
            #endif

            AST_VariableDeclaration declarationTree = declaration();
            Token assignmentToken = match(Token.TokenType.ASSIGNMENT);
            AST expressionTree = expression();

            if(expressionTree != null) {
                AST_Assignment assignmentTree = new AST_Assignment(assignmentToken, declarationTree.Name);

                assignmentTree.addChild(expressionTree);

                AST declarationAndAssignmentTree =
                        new AST(new Token(Token.TokenType.STATEMENT_LIST, "<DECLARATION_AND_ASSIGNMENT>", declarationTree.getToken().LineNr, declarationTree.getToken().LinePosition));
                declarationAndAssignmentTree.addChild(declarationTree);
                declarationAndAssignmentTree.addChild(assignmentTree);

                return declarationAndAssignmentTree;
            } else {
                throw new Error("The expression after = makes no sense", Error.ErrorType.SYNTAX,
                    lookAhead(1).LineNr, lookAhead(1).LinePosition);
            }
        }
예제 #18
0
        private AST parameterList()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("parameter list");
            #endif

            AST parameterListTree = new AST(new Token(Token.TokenType.NODE_GROUP, "<PARAMETER_LIST>", lookAhead(1).LineNr, lookAhead(1).LinePosition));

            if (lookAheadType(1) != Token.TokenType.PARANTHESIS_RIGHT) {

                while(true) {

                    AST parameterTree = parameter();
                    parameterListTree.addChild(parameterTree);

                    if (lookAheadType(1) == Token.TokenType.COMMA) {
                        match(Token.TokenType.COMMA);
                        continue;
                    } else {
                        break;
                    }
                }
            }

            return parameterListTree;
        }
예제 #19
0
        private AST foreachStuff(string pLoopVariableName)
        {
            AST statementList = new AST(new Token(Token.TokenType.STATEMENT_LIST, "<FOREACH_STATEMENTS>"));

            // increase __index__
            AST incrementNode = new AST(new Token(Token.TokenType.OPERATOR, "+"));
            incrementNode.addChild(new AST(new Token(Token.TokenType.NAME, "__index__")));
            incrementNode.addChild(new AST(new TokenWithValue(Token.TokenType.NUMBER, "1", 1.0f)));
            AST_Assignment assignmentNode = new AST_Assignment(new Token(Token.TokenType.ASSIGNMENT, "="), "__index__");
            assignmentNode.addChild(incrementNode);
            statementList.addChild(assignmentNode);

            // if(__index__ >= count(__indexes__)) { break }
            AST_FunctionCall lengthOfArray = new AST_FunctionCall(new Token(Token.TokenType.FUNCTION_CALL, "Count"));
            AST argumentList = new AST(new Token(Token.TokenType.NODE_GROUP, "<ARGUMENT_LIST>"));
            argumentList.addChild(new Token(Token.TokenType.NAME, "__indexes__"));
            lengthOfArray.addChild(argumentList);

            AST breakStatement = new AST_IfNode(new Token(Token.TokenType.IF, "IF"));
            AST operatorTree = new AST(new Token(Token.TokenType.OPERATOR, ">="));
            operatorTree.addChild(new Token(Token.TokenType.NAME, "__index__"));
            operatorTree.addChild(lengthOfArray);

            breakStatement.addChild(operatorTree);
            breakStatement.addChild(new Token(Token.TokenType.BREAK, "break"));
            statementList.addChild(breakStatement);

            // Loop variable
            AST_VariableDeclaration declarationTree =
                new AST_VariableDeclaration(new Token(Token.TokenType.VAR_DECLARATION, "<VAR_DECL>"), ReturnValueType.UNKNOWN_TYPE, pLoopVariableName);
            statementList.addChild(declarationTree);

            AST arrayIndexLookup = new AST(new Token(Token.TokenType.ARRAY_LOOKUP, "__indexes__"));
            arrayIndexLookup.addChild(new AST(new Token(Token.TokenType.NAME, "__index__")));

            AST arrayValueLookup = new AST(new Token(Token.TokenType.ARRAY_LOOKUP, "__array__"));
            arrayValueLookup.addChild(arrayIndexLookup);

            AST_Assignment assignmentTree =
                new AST_Assignment(new Token(Token.TokenType.ASSIGNMENT, "="), pLoopVariableName);
            assignmentTree.addChild(arrayValueLookup);
            statementList.addChild(assignmentTree);

            return statementList;
        }
예제 #20
0
        private AST parenthesisExpression()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("parenthesis expression");
            #endif
            AST lhs;

            if (lookAheadType(1) == Token.TokenType.PARANTHESIS_LEFT) {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("paranthesis left");
            #endif
                match(Token.TokenType.PARANTHESIS_LEFT);
                lhs = expression();
            #if WRITE_DEBUG_INFO
            Console.WriteLine("paranthesis right");
            #endif
                match(Token.TokenType.PARANTHESIS_RIGHT);
            } else {
                return operand();
            }

            if (lookAheadType(1) == Token.TokenType.OPERATOR) { // two parenthesis expressions with an operator between them
                Token operatorToken = match(Token.TokenType.OPERATOR);

                AST rightParenthesisTree = expression();

                AST duoParenthesisTree = new AST(operatorToken);
                duoParenthesisTree.addChild(lhs);
                duoParenthesisTree.addChild(rightParenthesisTree);
                return duoParenthesisTree;
            } else {
                return lhs;
            }
        }
예제 #21
0
        AST FunctionArgumentList()
        {
            match (Token.TokenType.PARANTHESIS_LEFT);

            AST argumentList = new AST (new Token (Token.TokenType.NODE_GROUP, "<ARGUMENT_LIST>"));
            if (lookAheadType (1) != Token.TokenType.PARANTHESIS_RIGHT) {
                while (true) {
                    AST expressionTree = expression ();
                    if (expressionTree != null) {
                        argumentList.addChild (expressionTree);
                        // add arguments as subtrees
                    }
                    else {
                        throw new Error ("Something is wrong with the argument list", Error.ErrorType.SYNTAX, lookAhead (1).LineNr, lookAhead (1).LinePosition);
                    }
                    if (lookAheadType (1) == Token.TokenType.COMMA) {
                        match (Token.TokenType.COMMA);
                        continue;
                    }
                    else {
                        // Is something wrong?
                        if (lookAheadType (1) == Token.TokenType.NEW_LINE || lookAheadType (1) == Token.TokenType.EOF) {
                            throw new Error ("Ending parenthesis is missing in function call", Error.ErrorType.SYNTAX, lookAhead (1).LineNr, lookAhead (1).LinePosition);
                        }
                        else
                            if (lookAheadType (1) == Token.TokenType.NAME || lookAheadType (1) == Token.TokenType.QUOTED_STRING || lookAheadType (1) == Token.TokenType.NUMBER) {
                                //throw new Error("A comma is missing in argument list", Error.ErrorType.SYNTAX, lookAhead(1).LineNr, lookAhead(1).LinePosition);
                                // allow missing commas in function call
                                continue;
                            }
                        break;
                    }
                }
            }
            match (Token.TokenType.PARANTHESIS_RIGHT);
            return argumentList;
        }
예제 #22
0
        private AST plusOrMinusExpression()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("plus or minus expression");
            #endif

            AST lhs = multiplicationExpression();

            if ( lookAhead(1).getTokenString() == "+" ||
                 lookAhead(1).getTokenString() == "-" )
            {
                Token operatorToken = match(Token.TokenType.OPERATOR);
                AST rhs = plusOrMinusExpression();
                checkLeftHandSide(lhs, operatorToken);
                checkRightHandSide(rhs, operatorToken);

                AST plusMinusExpressionTree = new AST(operatorToken);
                plusMinusExpressionTree.addChild(lhs);
                plusMinusExpressionTree.addChild(rhs);
                return plusMinusExpressionTree;
            } else {
                return lhs;
            }
        }
예제 #23
0
        private AST loop()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("loop");
            #endif
            AST loopBlockStatements = new AST(new Token(Token.TokenType.STATEMENT_LIST, "<LOOP_BLOCK_STATEMENTS>"));

            AST_LoopNode loopTree = new AST_LoopNode(match(Token.TokenType.LOOP));

            string loopVariableName = "@"; // default name if no name is specified directly after 'loop' keyword

            bool isForeachLoop = false;
            if(lookAheadType(1) != Token.TokenType.NEW_LINE)
            {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("foreach loop!");
            #endif
                isForeachLoop = true;

                // __index__
                AST_VariableDeclaration loopIndexDeclaration
                = new AST_VariableDeclaration(new Token(Token.TokenType.VAR_DECLARATION, "<VAR_DECL>"),
                                                        ReturnValueType.NUMBER,
                                                        "__index__");
                loopBlockStatements.addChild(loopIndexDeclaration);

                AST_Assignment loopIndexAssignment
                    = new AST_Assignment(new Token(Token.TokenType.ASSIGNMENT, "="), "__index__");
                loopIndexAssignment.addChild(new AST(new TokenWithValue(Token.TokenType.NUMBER, "-1", -1.0f)));

                loopBlockStatements.addChild(loopIndexAssignment);

                Token savePoint = lookAhead(1); // will backtrack from here if matching loopVariable + loopRangeExpression fails
                //Console.WriteLine("Created save point at token " + savePoint);

                Token loopVariable = null;
                AST loopRangeExpression = null; // what the loop will loop through

                if ((lookAheadType (1) == Token.TokenType.NAME && lookAheadType(2) == Token.TokenType.IN) ||
                    (lookAheadType (1) == Token.TokenType.NAME && lookAheadType(2) == Token.TokenType.FROM))
                {
                    loopVariable = match (Token.TokenType.NAME);

                    if(lookAheadType(1) == Token.TokenType.IN) {
                        match (Token.TokenType.IN);
                    }
                    else if(lookAheadType(1) == Token.TokenType.FROM) {
                        // proceed
                    }

                    try {
                        //Console.WriteLine ("Found a potential loop variable " + loopVariable.getTokenString() + ", trying to match loop range expression with a loop variable");
                        loopRangeExpression = expression();
                        if(loopRangeExpression == null) {
                            //Console.WriteLine ("null! Failed to match statement after loop variable, will backtrack and assume this loop does not use a loop variable");
                            backtrackToToken (savePoint);
                        } else {
                            loopVariableName = loopVariable.getTokenString();
                            //Console.WriteLine("Success, loop variable is called: " + loopVariableName);
                        }
                    }
                    catch(Error e) {
                        //Console.WriteLine ("Failed to match statement after loop variable, will backtrack and assume this loop does not use a loop variable");
                        backtrackToToken (savePoint);
                    }
                }

                if (loopRangeExpression == null) {
                    //Console.WriteLine ("There is no loop variable, trying to match a bare loop range expression");
                    loopRangeExpression = expression();
                }

                if (loopRangeExpression == null) {
                    throw new Error ("Failed to match the expression after 'loop'", Error.ErrorType.SYNTAX, loopTree.getToken ().LineNr, loopTree.getToken ().LinePosition);
                }

                //Console.WriteLine ("Loop range/array expression: ");
                //(new ASTPainter ()).PaintAST (loopRangeExpression);

                // __array__ (is a copy of the array to loop over)
                AST_VariableDeclaration loopArrayDeclaration = new AST_VariableDeclaration(
                    new Token(Token.TokenType.VAR_DECLARATION, "<VAR_DECL>"),
                    ReturnValueType.UNKNOWN_TYPE,
                    "__array__");

                loopBlockStatements.addChild(loopArrayDeclaration);

                AST_Assignment loopArrayAssignment =
                    new AST_Assignment(new Token(Token.TokenType.ASSIGNMENT, "="), "__array__");

                if(loopRangeExpression != null) {
                    loopArrayAssignment.addChild(loopRangeExpression);
                }
                else {
                    throw new Error("Can't understand array expression in loop", Error.ErrorType.SYNTAX,
                                    loopArrayAssignment.getToken().LineNr,
                                    loopArrayAssignment.getToken().LinePosition);
                }

                loopBlockStatements.addChild(loopArrayAssignment);

                // __indexes__ (holds all the indexes in the array, since it works like a SortedDictionary)
                // __indexes = getIndexes(__array__)
                AST_VariableDeclaration indexesDeclaration = new AST_VariableDeclaration(
                    new Token(Token.TokenType.VAR_DECLARATION, "<VAR_DECL>"),
                    ReturnValueType.UNKNOWN_TYPE,
                    "__indexes__");

                loopBlockStatements.addChild(indexesDeclaration);

                AST_FunctionCall getArrayIndexes = new AST_FunctionCall(new Token(Token.TokenType.FUNCTION_CALL, "GetIndexes"));
                AST argumentList = new AST(new Token(Token.TokenType.NODE_GROUP, "<ARGUMENT_LIST>"));
                argumentList.addChild(new Token(Token.TokenType.NAME, "__array__"));
                getArrayIndexes.addChild(argumentList);

                AST_Assignment indexesAssignment = new AST_Assignment(new Token(Token.TokenType.ASSIGNMENT, "="), "__indexes__");
                indexesAssignment.addChild(getArrayIndexes);
                loopBlockStatements.addChild(indexesAssignment);
            }
            else
            {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("infinite loop!");
            #endif
            }

            /*
             * 		loopParentTree
             * 			__index__-declaration
             * 			__array__-declaration & assigment
             * 			loop tree
             * 				loop body
             * 					foreach stuff
             * 					rest of statements
             * 					goto beginning of loop
             *
             * */

            allowLineBreak();
            AST loopBody = statementList(false);
            loopBody.addChild(new AST(new Token(Token.TokenType.GOTO_BEGINNING_OF_LOOP, "<GOTO_BEGINNING_OF_LOOP>")));
            allowLineBreak();
            match(Token.TokenType.BLOCK_END);

            if(isForeachLoop) {
                loopBody.addChildFirst(foreachStuff(loopVariableName));
            }

            loopTree.addChild(loopBody);

            loopBlockStatements.addChild(loopTree);

            AST_LoopBlockNode loopBlock = new AST_LoopBlockNode(new Token(Token.TokenType.LOOP_BLOCK, "<LOOP_BLOCK>"));
            loopBlock.addChild(loopBlockStatements);

            return loopBlock;
        }
예제 #24
0
        private AST returnFromFunction()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("return from function");
            #endif

            AST returnTree = new AST(match(Token.TokenType.RETURN));
            AST returnExpression = expression();

            if(returnExpression != null) {
                returnTree.addChild(returnExpression);
            }
            //else {
            //    throw new Error("No expression in return statement", Error.ErrorType.SYNTAX,
            //        lookAhead(1).LineNr, lookAhead(1).LinePosition);
            //}

            return returnTree;
        }
예제 #25
0
        void AddLocalVariables(AST ast, VariableDefinition[] variableDefinitions)
        {
            AST nodeForDefiningGlobalVariables = ast.getChild(0).getChild(0);

            if(variableDefinitions == null) { return; }

            foreach(VariableDefinition vd in variableDefinitions) {

                Token token = new Token(Token.TokenType.VAR_DECLARATION,"<VAR_DECL>", ast.getToken().LineNr, ast.getToken().LinePosition);

                AST_VariableDeclaration declarationTree =
                    new AST_VariableDeclaration(token,
                                                vd.initValue.getReturnValueType(),
                                                vd.variableName);

                if(vd.initValue != null)
                {
                    AST assignmentTree = CreateAssignmentTreeFromInitValue(vd.variableName, vd.initValue);
                    AST declarationAndAssignmentTree = new AST(new Token(Token.TokenType.STATEMENT_LIST, "<DECLARATION_AND_ASSIGNMENT>", declarationTree.getToken().LineNr, declarationTree.getToken().LinePosition));
                    declarationAndAssignmentTree.addChild(declarationTree);
                    declarationAndAssignmentTree.addChild(assignmentTree);
                    nodeForDefiningGlobalVariables.addChild(declarationAndAssignmentTree);
                }
                else
                {
                    nodeForDefiningGlobalVariables.addChild(declarationTree);
                }
            }
        }
예제 #26
0
        private AST statementList(bool isInMainScope)
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("statement list");
            #endif
            AST statementListTree = new AST(new Token(Token.TokenType.STATEMENT_LIST, "<STATEMENT_LIST>"));

            while (lookAheadType(1) != Token.TokenType.EOF &&
                   lookAheadType(1) != Token.TokenType.ELSE)
            {
                if(lookAheadType(1) == Token.TokenType.BLOCK_END) {
                    if(isInMainScope) {
                        m_errorHandler.errorOccured("Found the word 'end' where it makes no sense",
                                                    Error.ErrorType.SYNTAX, lookAhead(1).LineNr, lookAhead(1).LinePosition);
                    }
                    break;
                }

                AST statementTree = statement();
                if(statementTree != null) {
                    statementListTree.addChild(statementTree);
                }
                else {
            #if WRITE_DEBUG_INFO
                    Console.WriteLine("null statement");
            #endif
                }
            }

            return statementListTree;
        }
예제 #27
0
 private AST arrayLookup()
 {
     AST arrayName = new AST(match(Token.TokenType.NAME));
     AST arrayLookupNode = new AST(new Token(Token.TokenType.ARRAY_LOOKUP, arrayName.getTokenString()));
     match(Token.TokenType.BRACKET_LEFT);
     AST arrayIndex = expression();
     match(Token.TokenType.BRACKET_RIGHT);
     arrayLookupNode.addChild(arrayIndex);
     return arrayLookupNode;
 }
예제 #28
0
파일: Parser.cs 프로젝트: substans/Sprak
        private AST functionCall()
        {
            #if WRITE_DEBUG_INFO
            Console.WriteLine("function call");
            #endif

            Token nameToken = match(Token.TokenType.NAME);

            AST functionCallTree =
                new AST_FunctionCall(new Token(Token.TokenType.FUNCTION_CALL, nameToken.getTokenString(), nameToken.LineNr, nameToken.LinePosition));

            match(Token.TokenType.PARANTHESIS_LEFT);

            functionCallTree.getToken().LineNr = nameToken.LineNr;
            functionCallTree.getToken().LinePosition = nameToken.LinePosition;

            AST argumentList = new AST(new Token(Token.TokenType.NODE_GROUP, "<ARGUMENT_LIST>"));

            if (lookAheadType(1) != Token.TokenType.PARANTHESIS_RIGHT) {

                while(true) {

                    AST expressionTree = expression();

                    if(expressionTree != null)
                    {
                        argumentList.addChild(expressionTree); // add arguments as subtrees
                    }
                    else
                    {
                        throw new Error("Something is wrong with the argument list", Error.ErrorType.SYNTAX,
                            lookAhead(1).LineNr, lookAhead(1).LinePosition);
                    }

                    if (lookAheadType(1) == Token.TokenType.COMMA) {
                        match(Token.TokenType.COMMA);
                        continue;
                    } else {

                        // Is something wrong?
                        if( lookAheadType(1) == Token.TokenType.NEW_LINE ||
                            lookAheadType(1) == Token.TokenType.EOF )
                        {
                            throw new Error("Ending parenthesis is missing in function call"
                                , Error.ErrorType.SYNTAX,
                                lookAhead(1).LineNr, lookAhead(1).LinePosition);
                        }
                        else if( lookAheadType(1) == Token.TokenType.NAME ||
                                 lookAheadType(1) == Token.TokenType.QUOTED_STRING ||
                                 lookAheadType(1) == Token.TokenType.NUMBER )
                        {
                            throw new Error("A comma is missing in argument list"
                                , Error.ErrorType.SYNTAX,
                                lookAhead(1).LineNr, lookAhead(1).LinePosition);
                        }

                        break;
                    }
                }
            }

            match(Token.TokenType.PARANTHESIS_RIGHT);

            functionCallTree.addChild(argumentList);

            return functionCallTree;
        }