예제 #1
0
        public List <Step> ParseTokens() // Due to the size of this method I am not using IEnumerable 'yield return' as it is hard to track nested return statements.
        {
            List <Step> EvaluationSteps = new List <Step>();

            while (tokQueue.More())                  // While more tokens in queue (returns bool)
            {
                Token nextTok = tokQueue.MoveNext(); // pop next out of TokenQueue

                if (nextTok.Type().Equals("identifier"))
                // All statements in our language begin with identifiers.
                // We do not know what we have at this point, so let's check the identifier to see which tokens should follow after.
                {
                    if (Syntax.IsType(nextTok.Value()))
                    // If it is a var type, e.g "int", "string" - if it is, this is a variable declaration ("int x = 0;")
                    {
                        /*
                         * EXPECTED PATTERN: varType varName = expr;
                         * e.g int x = 2 + y*10;
                         * e.g string testing = "Hello World!";
                         */

                        VarDeclare varDeclare = CaptureVarDeclare(nextTok.Value()); // Call method with argument storing the type of var being declared, e.g 'string'

                        EvaluationSteps.Add(varDeclare);                            // Add Event object to the overall list of 'Steps' for the Evaluator module
                    }
                    else if (nextTok.Value().ToLower().Equals("if"))
                    // Start of an if statement
                    {
                        /*
                         * EXPECTED PATTERN: if(operands) { codeblock }
                         * e.g if (x > 0) {
                         *      output(x);
                         *      x = 0;
                         *     }
                         */

                        IfStatement ifState = CaptureIfStatement(); // Capture all useful information of the following if statements

                        // We COULD have an else statement, so let's check the next token
                        // First check there are still MORE tokens to check to avoid out of range errors
                        // Then check it's an IDENTIFIER ('else')
                        if (tokQueue.More() && tokQueue.Next().Type().Equals("identifier") && tokQueue.Next().Value().Equals("else"))
                        {
                            // If next token is 'else' and an identifier
                            ElseStatement elseState = CaptureElseStatement();
                            EvaluationSteps.Add(ifState);
                            EvaluationSteps.Add(elseState);
                            // Add if state then else directly after (ordered list!)
                        }
                        else
                        {
                            EvaluationSteps.Add(ifState);  // if no 'else' statement exists just add the if statement
                        }
                    }

                    else if (nextTok.Value().ToLower().Equals("while"))
                    {
                        IfStatement template  = CaptureIfStatement(); // Trick the program to think it's capturing an if statement
                        WhileLoop   whileLoop = new WhileLoop(template.GetCBContents(), template.GetOp1(), template.GetOp2(), template.GetComparator());
                        // Reuse code from the if statement because while & if follow the exact same structure:
                        // while (condition) { codeblock }
                        // if (condition) { codeblock }
                        // We just captured an if statement 'template' then used the information it collected to create a while loop instead

                        EvaluationSteps.Add(whileLoop);
                    }


                    else if (GrammarTokenCheck(tokQueue.Next(), "("))
                    // This condition will also return true if it finds an if/while statement, so it is AFTER the check for those.
                    // As we're using else if, if the program didn't recognise a 'while' or 'if' statement, we will reach this check
                    // We can GUARANTEE now that this must be a function call as 'if(){}' and 'while(){}' have been ruled out
                    {
                        /*
                         * EXPECTED PATTERN: funcName(expr); // Can take any expression!
                         * e.g output("Testing");
                         * e.g output(1 + 23);
                         * e.g output(x);
                         */

                        tokQueue.MoveNext(); // Skip the '(' token
                        // Remember, nextTok still holds the value of the token before '('
                        // This is the name of our function ('funcName')

                        FuncCall funcCall = CaptureFunctionCall(nextTok.Value()); // Pass the function name, e.g 'output'
                        EvaluationSteps.Add(funcCall);
                    }
                    else if (GrammarTokenCheck(tokQueue.Next(), "=")) // .Next() is PEEK not POP.
                    // Check if the token AFTER this one is "="
                    {
                        /*
                         * EXPECTED PATTERN: varName = expr;
                         * e.g x = 2 + y*10;
                         * e.g testing = "Hello World!";
                         */

                        tokQueue.MoveNext(); // Skip the '=' token
                        // Remember, nextTok still holds the value of the token before the '='
                        // This is the name of our variable to change ('varName')

                        VarChange varChan = CaptureVarChange(nextTok.Value());
                        EvaluationSteps.Add(varChan);
                    }
                    else
                    {
                        throw new SyntaxError();
                    }
                    // If there is a rogue 'else' statement it will be caught in this
                    // Else statements are not 'looked' for on there own, they are only recognised when an if statement is found
                }
                else
                {
                    throw new SyntaxError();    // Statement doesn't begin with identifier - throw error.
                }
            }

            return(EvaluationSteps);
        }