コード例 #1
0
 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);
 }
コード例 #2
0
        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);
        }