Example #1
0
        private VisitResult VisitFunctionCall(ASTFunctionCall functionCall)
        {
            var symbolFunction   = functionCall.SymbolFunction;
            var functionName     = functionCall.FunctionName;
            var formalParameters = symbolFunction.Parameters;
            var actualParameters = functionCall.ActualParameters;

            var activationRecord = new ActivationRecord(functionName, ActivationRecordType.Function, symbolFunction.ScopeLevel + 1);

            for (var i = 0; i < formalParameters.Count; ++i)
            {
                activationRecord[formalParameters[i].Name] = Visit(actualParameters[i]).Value;
            }

            Logger.Debug($"Enter {functionName}");
            _callStack.Push(activationRecord);

            var result = symbolFunction is SymbolBuiltinFunction?BuiltinFunctionCall(functionCall) : Visit(symbolFunction.Body);

            var returnedValue = result != null ? result.Value : "null";

            if (returnedValue is List <dynamic> collection)
            {
                returnedValue = collection.ToPrint();
            }

            Logger.DebugMemory($"Leave {functionName}, returned value ({returnedValue})");
            Logger.DebugMemory(_callStack.ToString());

            _callStack.Pop();

            return(result);
        }
Example #2
0
        private VisitResult BuiltinFunctionCall(ASTFunctionCall functionCall)
        {
            var functionName = functionCall.FunctionName;

            switch (functionName)
            {
            case "print":
                return(PrintFunctionCall());
            }

            throw new ArgumentNullException($"Builtin function {functionName} not found");
        }
Example #3
0
        private static ASTNode ParseFunctionCallOrParameterAccess(string scope)
        {
            string functionNameOrParameter = currentTokens[currentToken].Token;

            currentToken++;
            if (currentTokens[currentToken].Token != "(")
            {
                return(new ASTClassParameter()
                {
                    Scope = scope,
                    Parameter = new ASTStatement()
                    {
                        Statement = new ASTString()
                        {
                            String = functionNameOrParameter
                        }
                    }
                });
            }
            currentToken++;

            ASTFunctionCall ret = new ASTFunctionCall()
            {
                Scope        = scope,
                FunctionName = functionNameOrParameter
            };

            while (currentTokens[currentToken].Token != ")")
            {
                ret.Parameter.Add(ParseStatement());
                if (currentTokens[currentToken].Token == ",")
                {
                    currentToken++;
                }
            }
            currentToken++;
            return(ret);
        }
Example #4
0
        private dynamic VisitProgram(ASTProgram program)
        {
            Logger.Debug("Enter Program");
            var activationRecord = new ActivationRecord("Main", ActivationRecordType.Program, 1);

            _callStack.Push(activationRecord);

            var runParameters = new List <ASTNode>();
            var mainFunction  = new ASTFunctionCall(program.Token, "Main", runParameters);

            mainFunction.SymbolFunction = program.MainFunction;

            var result = Visit(mainFunction);

            Logger.DebugMemory("Leave Program");
            Logger.DebugMemory(_callStack.ToString());

            _callStack.Pop();

            Logger.Debug($"Program exited with status code {result?.Value ?? "null"}");

            return(result);
        }
Example #5
0
        private static ASTNode ParseSingleStatement()
        {
            ASTNode ret = null;

            if (currentTokens[currentToken] is StringToken)
            {
                ret = new ASTString {
                    String = currentTokens[currentToken].Token
                };
                currentToken++;
            }
            else if (currentTokens[currentToken] is NumberToken)
            {
                double dResult;
                if (double.TryParse(currentTokens[currentToken].Token, NumberStyles.Any, CultureInfo.GetCultureInfo("en"), out dResult))
                {
                    ret = new ASTNumber {
                        Number = dResult
                    };
                }
                else
                {
                    throw new ParserException(string.Format("Number {0} is not valid.", currentTokens[currentToken].Token), currentTokens[currentToken].LineNumber);
                }
                currentToken++;
            }
            else if (currentTokens[currentToken] is ReservedWordToken)
            {
                if (currentTokens[currentToken].Token == "this" || currentTokens[currentToken].Token == "VM")
                {
                    string scope = currentTokens[currentToken].Token;
                    currentToken++;
                    if (currentTokens[currentToken] is SpecialToken && currentTokens[currentToken].Token == ".")
                    {
                        currentToken++;
                        ret = ParseFunctionCallOrParameterAccess(scope);
                    }
                    else
                    {
                        throw new ParserException(string.Format("Expected '.' instead of '{0}'.", currentTokens[currentToken].Token), currentTokens[currentToken].LineNumber);
                    }
                }
                else if (currentTokens[currentToken].Token == "object" ||
                         currentTokens[currentToken].Token == "string" ||
                         currentTokens[currentToken].Token == "number")
                {
                    VMType type = currentTokens[currentToken].Token == "number" ? VMType.Number : (currentTokens[currentToken].Token == "string" ? VMType.String : VMType.Object);
                    currentToken++;
                    if (currentTokens[currentToken] is IdentifierToken)
                    {
                        ret = new ASTLocalVariable()
                        {
                            Type = type,
                            Name = currentTokens[currentToken].Token
                        };
                    }
                    else
                    {
                        throw new ParserException("Expected Identifier.", currentTokens[currentToken].LineNumber);
                    }
                    currentToken++;
                }
                else if (currentTokens[currentToken].Token == "new")
                {
                    currentToken++;
                    ASTNode createClass = ParseFunctionCallOrParameterAccess("constructor");
                    if (createClass is ASTFunctionCall)
                    {
                        ASTFunctionCall fc = (ASTFunctionCall)createClass;
                        ret = new ASTCreateClass()
                        {
                            Scope        = fc.FunctionName,
                            FunctionName = fc.FunctionName,
                            Parameter    = fc.Parameter
                        };
                    }
                    else
                    {
                        throw new ParserException("Error with new.", currentTokens[currentToken].LineNumber);
                    }
                }
                else if (currentTokens[currentToken].Token == "return")
                {
                    currentToken++;
                    ret = new ASTReturn()
                    {
                        Return = ParseStatement()
                    };

                    // Point to ';' again!!!
                    --currentToken;
                }
                else
                {
                    throw new ParserException(string.Format("Reserved Word {0} is not legal in Statement.", currentTokens[currentToken].Token), currentTokens[currentToken].LineNumber);
                }
            }
            else if (currentTokens[currentToken] is IdentifierToken)
            {
                string identifierOrScope = currentTokens[currentToken].Token;
                currentToken++;
                if (currentTokens[currentToken] is SpecialToken)
                {
                    if (currentTokens[currentToken].Token == ".")
                    {
                        currentToken++;
                        TokenBase isFunction = currentTokens[currentToken + 1];
                        ret = ParseFunctionCallOrParameterAccess(identifierOrScope);
                    }
                    else if (currentTokens[currentToken].Token == "(")
                    {
                        // Set focus again to the function name
                        --currentToken;
                        ret = ParseFunctionCallOrParameterAccess("this");
                    }
                    else if (currentTokens[currentToken].Token == "[")
                    {
                        currentToken++;
                        ASTStatement statement = ParseStatement();
                        if (statement == null)
                        {
                            throw new ParserException("Expected Statement for Parameter Access.", currentTokens[currentToken].LineNumber);
                        }
                        ret = new ASTClassParameter()
                        {
                            Scope     = identifierOrScope,
                            Parameter = statement
                        };
                    }
                    else
                    {
                        ret = new ASTIdentifier()
                        {
                            Identifier = identifierOrScope
                        };
                    }
                }
                else
                {
                    ret = new ASTIdentifier()
                    {
                        Identifier = identifierOrScope
                    };
                }
            }

            if (ret == null)
            {
                throw new ParserException(String.Format("Problems parsing the Identifier/Function Call/String/Number {0}.", currentTokens[currentToken].Token), currentTokens[currentToken].LineNumber);
            }
            return(ret);
        }
        private static void PrintNode(ASTNode node, int incident)
        {
            if (node == null)
            {
                return;
            }
            for (int i = 0; i < incident; i++)
            {
                sw.Write("\t");
            }
            if (node is ASTString)
            {
                sw.WriteLine("ASTString: " + ((ASTString)node).String.Replace("\n", "\\n"));
            }
            else if (node is ASTNumber)
            {
                sw.WriteLine("ASTNumber: " + ((ASTNumber)node).Number);
            }
            else if (node is ASTIdentifier)
            {
                sw.WriteLine("ASTIdentifier: " + ((ASTIdentifier)node).Identifier);
            }
            else if (node is ASTOperator)
            {
                ASTOperator op = (ASTOperator)node;
                sw.WriteLine("ASTOperator: " + op.Operator);
                PrintNode(op.Left, incident + 1);
                PrintNode(op.Right, incident + 1);
            }
            else if (node is ASTStatement)
            {
                ASTStatement stm = (ASTStatement)node;
                sw.WriteLine("ASTStatement: ");
                PrintNode(stm.Statement, incident + 1);
            }
            else if (node is ASTFunctionCall)
            {
                ASTFunctionCall call = (ASTFunctionCall)node;
                sw.WriteLine("ASTFunctionCall: " + call.Scope + "." + call.FunctionName);
                foreach (ASTNode param in call.Parameter)
                {
                    PrintNode(param, incident + 1);
                }
            }
            else if (node is ASTClassParameter)
            {
                ASTClassParameter classP = (ASTClassParameter)node;
                sw.WriteLine("ASTClassParameter: " + classP.Scope);
                PrintNode(classP.Parameter, incident + 1);
            }
            else if (node is ASTIf)
            {
                ASTIf ifNode = (ASTIf)node;
                sw.WriteLine("ASTIf:");
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCondition:");
                PrintNode(ifNode.Condition, incident + 2);
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCodeBlock:");
                foreach (ASTNode codeBlock in ifNode.CodeBlock)
                {
                    PrintNode(codeBlock, incident + 2);
                }
                if (ifNode.ElseCodeBlock != null)
                {
                    for (int i = 0; i < incident; i++)
                    {
                        sw.Write("\t");
                    }
                    sw.WriteLine("\tElse:");
                    foreach (ASTNode codeBlock in ifNode.ElseCodeBlock)
                    {
                        PrintNode(codeBlock, incident + 2);
                    }
                }
            }
            else if (node is ASTFor)
            {
                ASTFor forNode = (ASTFor)node;
                sw.WriteLine("ASTFor:");
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tInit:");
                PrintNode(forNode.Initialise, incident + 2);
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCondition:");
                PrintNode(forNode.Condition, incident + 2);
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCounter:");
                PrintNode(forNode.Count, incident + 2);
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCodeBlock:");
                foreach (ASTNode codeBlock in forNode.CodeBlock)
                {
                    PrintNode(codeBlock, incident + 2);
                }
            }
            else if (node is ASTWhile)
            {
                ASTWhile wNode = (ASTWhile)node;
                sw.WriteLine("ASTWhile:");
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCondition:");
                PrintNode(wNode.Condition, incident + 2);
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCodeBlock:");
                foreach (ASTNode codeBlock in wNode.CodeBlock)
                {
                    PrintNode(codeBlock, incident + 2);
                }
            }
            else if (node is ASTFunction)
            {
                ASTFunction func = (ASTFunction)node;
                if (node is ASTConstructor)
                {
                    sw.WriteLine("ASTConstructor:");
                }
                else
                {
                    sw.WriteLine("ASTFunction: " + func.ReturnValue.ToString() + " " + func.Name);
                }
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tParameter:");
                foreach (ASTNode n in func.Parameter)
                {
                    PrintNode(n, incident + 2);
                }
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCodeBlock:");
                foreach (ASTNode codeBlock in func.CodeBlock)
                {
                    PrintNode(codeBlock, incident + 2);
                }
            }
            else if (node is ASTFunctionParameter)
            {
                ASTFunctionParameter param = (ASTFunctionParameter)node;
                switch (param.Type)
                {
                case VMType.Object:
                    sw.WriteLine("Object: " + param.Name);
                    break;

                case VMType.String:
                    sw.WriteLine("String: " + param.Name);
                    break;

                case VMType.Number:
                    sw.WriteLine("Number: " + param.Name);
                    break;
                }
            }
            else if (node is ASTLocalVariable)
            {
                ASTLocalVariable param = (ASTLocalVariable)node;
                switch (param.Type)
                {
                case VMType.Object:
                    sw.WriteLine("var Object: " + param.Name);
                    break;

                case VMType.String:
                    sw.WriteLine("var String: " + param.Name);
                    break;

                case VMType.Number:
                    sw.WriteLine("var Number: " + param.Name);
                    break;
                }
            }
            else if (node is ASTReturn)
            {
                sw.WriteLine("ASTReturn:");
                PrintNode(((ASTReturn)node).Return, incident + 1);
            }
            else if (node is ASTClass)
            {
                ASTClass cNode = (ASTClass)node;
                sw.WriteLine("ASTClass: " + cNode.Name);
                sw.WriteLine("\tAttributes:");
                foreach (ASTNode n in cNode.Attributes)
                {
                    PrintNode(n, incident + 2);
                }
                sw.WriteLine("\tConstructors:");
                foreach (ASTNode n in cNode.Constructors)
                {
                    PrintNode(n, incident + 2);
                }
                sw.WriteLine("\tFunctions:");
                foreach (ASTNode n in cNode.Functions)
                {
                    PrintNode(n, incident + 2);
                }
            }
        }