internal override bool TypeCheck(out Type type) { type = Type.NULL; if (expression is not null) { if (CurrentFunction.returnType == Type.VOID) { Error("Return statement cannot have value in void function"); return(false); } if (expression.TypeCheck(out Type returnType)) { if (!AssignmentTypeHelper(CurrentFunction.returnType, returnType)) { Error($"Return type doens't match. Expect: {TypeString(CurrentFunction.returnType)}," + $" Got: {TypeString(returnType)}"); return(false); } } else { return(false); } } this.function = CurrentFunction; return(true); }
public Statement Parse() { GetNextToken(); //Array containing all accepted tokens by the print statement Token[] acceptedPrintTokens = new[] { Token.String, Token.BoolTrue, Token.BoolFalse, Token.Number, Token.VariableName, Token.Not, Token.Minus }; //PRINT statement check/parse if (LastToken == Token.Print && acceptedPrintTokens.Contains(CurrentToken)) { return(new PrintStatement(EvaluateExpression())); } //FUNCTION definition statement check/parse if (LastToken == Token.FunctionDef && CurrentToken == Token.FunctionName) { List <Statement> statements = new List <Statement>(); List <Argument> arguments = new List <Argument>(); //Gets the arguments for the function GetNextToken(); while (CurrentToken != Token.OpenBrace) { GetNextToken(); if (LastToken == Token.Argument && (CurrentToken == Token.BoolVariable || CurrentToken == Token.NumberVariable || CurrentToken == Token.StringVariable)) { GetNextToken(); if (CurrentToken == Token.VariableName) { Argument argument = new Argument(); argument.ArgumentName = VariableName; GeneralSymbol symbol = new GeneralSymbol(); Dictionary <Token, Enums.Type> tokenConversion = new Dictionary <Token, Enums.Type> { { Token.StringVariable, Enums.Type.String }, { Token.NumberVariable, Enums.Type.Number }, { Token.BoolVariable, Enums.Type.Bool } }; symbol.Type = tokenConversion[LastToken]; argument.Value = symbol; arguments.Add(argument); GetNextToken(); } else { throw new Exception("Expecting argument name!"); } } else { throw new Exception("Expecting type after argument"); } } //Gets the statements for the function if (CurrentToken == Token.OpenBrace) { GetNextToken(); while (CurrentToken != Token.CloseBrace) { statements.Add(Parse()); } FunctionDefinitionStatement function = new FunctionDefinitionStatement(statements, arguments, FunctionName); _statements.Add(function); } } //Checks for function call if (CurrentToken == Token.FunctionCall) { GetNextToken(); if (CurrentToken == Token.FunctionName) { GetNextToken(); List <Argument> arguments = new List <Argument>(); while (CurrentToken != Token.Semi && CurrentToken != Token.EndFile) { if (CurrentToken == Token.String || CurrentToken == Token.Number || CurrentToken == Token.BoolFalse || CurrentToken == Token.BoolTrue || CurrentToken == Token.Minus || CurrentToken == Token.VariableName) { Argument argument = new Argument(); argument.Value = EvaluateExpression().Evaluate(); arguments.Add(argument); } GetNextToken(); } return(new FunctionCallStatement(FunctionName, arguments)); } } //Checks for variable decleration if (CurrentToken == Token.NumberVariable || CurrentToken == Token.StringVariable || CurrentToken == Token.BoolVariable) { GetNextToken(); if (CurrentToken == Token.VariableName) { GetNextToken(); if (CurrentToken == Token.VariableAssignment) { GetNextToken(); if (CurrentToken == Token.String || CurrentToken == Token.Number || CurrentToken == Token.BoolFalse || CurrentToken == Token.BoolTrue || CurrentToken == Token.Minus || CurrentToken == Token.VariableName) { //Finds the type of variable which is being declared Enums.Type type = Enums.Type.Null; Dictionary <Token, Enums.Type> tokenConversion = new Dictionary <Token, Enums.Type> { { Token.StringVariable, Enums.Type.String }, { Token.NumberVariable, Enums.Type.Number }, { Token.BoolVariable, Enums.Type.Bool } }; type = tokenConversion[ThirdLastToken]; VariableDeclerationStatement variableDecleration = new VariableDeclerationStatement(type, VariableName, EvaluateExpression()); variableDecleration.Execute(); return(variableDecleration); } else { throw new Exception("Unknown type"); } } } else { throw new Exception("Invalid variable name"); } } //Checks for variable assignment if (CurrentToken == Token.VariableName && LastToken == Token.Semi) { GetNextToken(); if (CurrentToken == Token.VariableAssignment) { GetNextToken(); if (CurrentToken == Token.String || CurrentToken == Token.Number || CurrentToken == Token.BoolTrue || CurrentToken == Token.BoolFalse || CurrentToken == Token.Not || CurrentToken == Token.VariableName) { return(new VariableAssignmentStatement(VariableName, EvaluateExpression())); } else { throw new Exception("Unknown type"); } } else { throw new Exception("Missing = after variable name"); } } if (CurrentToken == Token.VariableName && (LastToken != Token.BoolVariable && LastToken != Token.StringVariable && LastToken != Token.NumberVariable)) { throw new Exception("Variable does not exists in scope"); } //Console.WriteLine("Time taken to compile: " + (DateTime.Now - startTime) + "\n"); return(null); }