Пример #1
0
        public static Node ParseProgram()
        {
            //Diagram rules
            //1st -> SubDec | FuncDec
            //SubDec | FuncDec -> SubDec | FuncDec
            //SubDec | FuncDec -> EOF

            Statements root = new Statements();

            while (tokens.actual.type != "EOF")
            {
                if (tokens.actual.type == "SUB" || tokens.actual.type == "FUNCTION")
                {
                    root.Add(ParseFunction());
                }
                else
                {
                    if (tokens.actual.type == "LINEBREAK")
                    {
                        CurrentLine++;
                        tokens.SelectNext();
                    }
                    else
                    {
                        throw new SystemException($"Statement line outside functions are not allowed. Got a {tokens.actual.type}.(position {tokens.position}) [Line: {CurrentLine}]");
                    }
                }
            }

            //add a main funccall
            FuncCall mainCall = new FuncCall();

            mainCall.value = "main";
            root.Add(mainCall);

            return(root);
        }
Пример #2
0
        public static Node ParseFactor()
        {
            //Console.WriteLine("Parsing Factor");

            //Factor rules
            //1st -> num
            //1st -> +
            //1st -> -
            //1st -> not
            //1st -> (
            //+ -> factor
            //- -> factor
            //not -> factor
            //( -> expression
            //expression -> )
            //identifier acts as num
            //True | False acts as num

            Node root;

            switch (tokens.actual.type)
            {
            case "INT":
                root       = new IntVal();
                root.value = tokens.actual.value;
                tokens.SelectNext();
                return(root);

            case "IDENTIFIER":
                root       = new Identifier((string)tokens.actual.value);
                root.value = tokens.actual.value;
                tokens.SelectNext();

                //check if this is a function
                if (tokens.actual.type == "POPEN")
                {
                    FuncCall call = new FuncCall();
                    call.value = root.value;
                    tokens.SelectNext();

                    if (tokens.actual.type != "PCLOSE")
                    {
                        do
                        {
                            if (tokens.actual.type == "COMMA")
                            {
                                tokens.SelectNext();
                            }
                            call.Add(ParseRelExpression());
                        } while(tokens.actual.type == "COMMA");
                    }
                    Expect("PCLOSE", true);
                    return(call);
                }

                return(root);

            case "TRUE":
            case "FALSE":
                root       = new UnOp();
                root.value = tokens.actual.type == "TRUE" ? "true": "false";
                tokens.SelectNext();
                return(root);

            case "PLUS":
            case "MINUS":
                root       = new UnOp();
                root.value = tokens.actual.type == "PLUS" ? '+': '-';
                tokens.SelectNext();
                root.children[0] = ParseFactor();
                return(root);

            case "NOT":
                root       = new UnOp();
                root.value = "not";
                tokens.SelectNext();
                root.children[0] = ParseFactor();
                return(root);

            case "POPEN":
                tokens.SelectNext();
                root = ParseRelExpression();
                if (tokens.actual.type != "PCLOSE")
                {
                    throw new SystemException($"Missing closing parentesis (position {tokens.position}) [Line: {CurrentLine}]");
                }
                tokens.SelectNext();
                return(root);

            case "INPUT":
                root       = new UnOp();
                root.value = "input";
                tokens.SelectNext();
                return(root);
            }

            //End of term reached, but exiting was not allowed
            throw new SystemException($"Invalid expression format. Expression end was unexpected(position {tokens.position}) [Line: {CurrentLine}]");
        }
Пример #3
0
        //public static Node ParseStatements(string poi){
        //    return ParseStatements("none");
        // }

        public static Node ParseStatement()
        {
            //Console.WriteLine("parsing expression");
            //Diagram rules
            //1st - Identfier
            //identifier - =
            //= - expression
            //1st - print
            //print - expression
            //1st - statements

            Node root;

            //TODO- condense this code by replacing similar code with some functions (expect line end for example)

            switch (tokens.actual.type)
            {
            case "END":
                return(new NoOp());

            case "IDENTIFIER":
                // IDENTIFIER - = - EXPRESSION
                // get identifier
                Identifier ident = new Identifier((string)tokens.actual.value);
                tokens.SelectNext();
                if (tokens.actual.type != "EQUAL")     //expecting a EQUAL
                {
                    throw new SystemException($"Identifier with no assignment ({tokens.actual.value}) (position {tokens.position}) [Line: {CurrentLine}]");
                }
                root             = new BinOp();          //create the assign biop node
                root.value       = '=';
                root.children[0] = ident;                //left is the identfier
                tokens.SelectNext();
                root.children[1] = ParseRelExpression(); //right is a relative expression

                if (tokens.actual.type != "LINEBREAK")   //expect linebreak after the expression;
                {
                    throw new SystemException($"No LINEBREAK after assignment (position {tokens.position}) [Line: {CurrentLine}]");
                }
                CurrentLine++;
                tokens.SelectNext();     //go to next token after linebreak
                return(root);

            case "CALL":
                tokens.SelectNext();
                Expect("IDENTIFIER", false);

                FuncCall call = new FuncCall();
                call.value = (string)tokens.actual.value;

                tokens.SelectNext();
                Expect("POPEN", true);
                if (tokens.actual.type != "PCLOSE")
                {
                    do
                    {
                        if (tokens.actual.type == "COMMA")
                        {
                            tokens.SelectNext();
                        }
                        call.Add(ParseRelExpression());
                    }while (tokens.actual.type == "COMMA");
                }
                Expect("PCLOSE", true);
                return(call);

            case "PRINT":
                //print - expression
                root       = new UnOp();
                root.value = "print";
                tokens.SelectNext();
                root.children[0] = ParseRelExpression();
                if (tokens.actual.type != "LINEBREAK")     //expect linebreak after the expression;
                {
                    throw new SystemException($"No LINEBREAK after PRINT (position {tokens.position}) [Line: {CurrentLine}]");
                }
                CurrentLine++;
                tokens.SelectNext();     //go to next token after linebreak
                return(root);

            case "WHILE":
                root = new WhileNode();
                tokens.SelectNext();
                root.children[0] = ParseRelExpression();
                if (tokens.actual.type != "LINEBREAK")     //expect linebreak after the expression;
                {
                    throw new SystemException($"No LINEBREAK after Relative Expression (position {tokens.position}) [Line: {CurrentLine}]");
                }
                CurrentLine++;
                tokens.SelectNext();                         //go to next token after linebreak
                root.children[1] = ParseStatements("while"); //already goes to next line, no select next required
                return(root);

            case "DIM":
                root       = new BinOp();
                root.value = "vardec";
                tokens.SelectNext();

                if (tokens.actual.type != "IDENTIFIER")
                {
                    throw new SystemException($"IDENTIFIER is required after an variable declaration declaration (position {tokens.position}) [Line: {CurrentLine}]");
                }
                root.children[0]       = new NoOp();
                root.children[0].value = (string)tokens.actual.value;
                tokens.SelectNext();

                if (tokens.actual.type != "AS")
                {
                    throw new SystemException($"'As' is required in an variable declaration (position {tokens.position}) [Line: {CurrentLine}]");
                }
                tokens.SelectNext();

                root.children[1] = parseType();

                if (tokens.actual.type != "LINEBREAK")     //expect linebreak after the expression;
                {
                    throw new SystemException($"No LINEBREAK after Variable declaration(position {tokens.position}) [Line: {CurrentLine}]");
                }
                CurrentLine++;
                tokens.SelectNext();     //go to next token after linebreak

                return(root);

            case "IF":
                root = new IfNode();
                tokens.SelectNext();
                root.children[0] = ParseRelExpression();

                if (tokens.actual.type != "THEN")     //expect THEN after the rel expression;
                {
                    throw new SystemException($"THEN is required after an IF's Relative Expression (position {tokens.position}) [Line: {CurrentLine}]");
                }
                tokens.SelectNext();

                if (tokens.actual.type != "LINEBREAK")     //expect linebreak after THEN;
                {
                    throw new SystemException($"No LINEBREAK after Relative Expression (position {tokens.position}) [Line: {CurrentLine}]");
                }
                CurrentLine++;
                tokens.SelectNext();                      //go to next token after linebreak

                root.children[1] = ParseStatements("if"); //already goes to next line, no select next required

                if (tokens.actual.type == "ELSE")
                {
                    tokens.SelectNext();
                    if (tokens.actual.type != "LINEBREAK")     //expect linebreak after ELSE;
                    {
                        throw new SystemException($"No LINEBREAK after ELSE (position {tokens.position}) [Line: {CurrentLine}]");
                    }
                    CurrentLine++;
                    tokens.SelectNext();                        //go to next token after linebreak
                    root.children[2] = ParseStatements("else"); //left the token after the END, so it is probably on IF (END IF\n)
                }

                if (tokens.actual.type != "IF")     //expect IF after the statements END for END IF\n construction;
                {
                    throw new SystemException($"IF section end symbol not found, found END instead of END IF (position {tokens.position}) [Line: {CurrentLine}]");
                }
                tokens.SelectNext();

                if (tokens.actual.type != "LINEBREAK")     //expect linebreak after THEN;
                {
                    throw new SystemException($"No LINEBREAK after Relative Expression (position {tokens.position}) [Line: {CurrentLine}]");
                }
                CurrentLine++;
                tokens.SelectNext();     //go to next token after linebreak

                return(root);

            default:
                return(new NoOp());
            }
        }