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); }
private VisitResult BuiltinFunctionCall(ASTFunctionCall functionCall) { var functionName = functionCall.FunctionName; switch (functionName) { case "print": return(PrintFunctionCall()); } throw new ArgumentNullException($"Builtin function {functionName} not found"); }
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); }
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); }
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); } } }