예제 #1
0
        public void Parser_MiniPL_LL1ParseTableGenerationTest()
        {
            CFG        grammar    = MiniPL.GetInstance().Grammar;
            ParseTable parseTable = grammar.CreateLL1ParseTable();

            Assert.AreNotEqual(null, parseTable);
        }
예제 #2
0
        static void Main(string[] args)
        {
            if (args.Length == 1)
            {
                debug = false;
            }

            switch (args.Length)
            {
            case 0:
                Console.WriteLine("Specify a file path.");
                break;

            default:
                FileStream fs;
                try
                {
                    fs = System.IO.File.OpenRead(args[0]);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    break;
                }

                MiniPL          miniPL = MiniPL.GetInstance();
                Scanner         sc     = miniPL.Scanner;
                Parser          ps     = miniPL.Parser;
                ParseTree       ptree  = ps.Parse(sc.Tokenize(fs));
                MiniPL.Runnable prog   = miniPL.ProcessParseTree(ptree, ps.Errors, ps.IsValidParseTree);
                prog.Execute(Console.In, Console.Out);

                break;
            }
        }
예제 #3
0
        public void Scanner_MiniPL_NestedCommentTest()
        {
            string text = "print \"Give a number\";\n" +
                          "var n : int; /* \n" +
                          "read n;\n" +
                          "var f : int := 1;\n" +
                          "/* var i : int; */\n" +
                          "/* for i in 1..n do\n" +
                          "       f := f * i;\n" +
                          "*/ end for;\n" +
                          "print \"The result is: \";\n" +
                          "print f;";

            int[] expectedRows = new int[] { 0, 0, 0,
                                             1, 1, 1, 1, 1 };
            int[] expectedCols = new int[] { 0, 6, 21,
                                             0, 4, 6, 8, 11 };

            Scanner      sc     = MiniPL.GetInstance().Scanner;
            List <Token> tokens = new List <Token>(sc.Tokenize(text, yieldEOF: false));

            for (int i = 0; i < tokens.Count; i++)
            {
                Assert.AreEqual(expectedRows[i], tokens[i].TextPosition.Row);
                Assert.AreEqual(expectedCols[i], tokens[i].TextPosition.Column);
            }
        }
예제 #4
0
        private List <Error> GetErrors(string program)
        {
            MiniPL    miniPL = MiniPL.GetInstance();
            Scanner   sc     = miniPL.Scanner;
            Parser    ps     = miniPL.Parser;
            ParseTree ptree  = ps.Parse(sc.Tokenize(program));

            MiniPL.Runnable prog = miniPL.ProcessParseTree(ptree, ps.Errors, ps.IsValidParseTree);

            return(prog.errors);
        }
예제 #5
0
        public void Parser_MiniPLTest1()
        {
            string text = "var X : int := 4 + (6 * 2);\n" +
                          "print X;";

            MiniPL  miniPL = MiniPL.GetInstance();
            Scanner sc     = miniPL.Scanner;
            Parser  ps     = miniPL.Parser;

            ParseTree ptree = ps.Parse(sc.Tokenize(text));

            List <Error> errors = ps.Errors;

            Assert.AreEqual(0, errors.Count);
        }
예제 #6
0
        private string RunWithInput(string program, string input)
        {
            MiniPL  miniPL = MiniPL.GetInstance();
            Scanner sc     = miniPL.Scanner;
            Parser  ps     = miniPL.Parser;

            ParseTree ptree = ps.Parse(sc.Tokenize(program));

            MiniPL.Runnable prog = miniPL.ProcessParseTree(ptree, ps.Errors, ps.IsValidParseTree);

            StringWriter writer = new StringWriter();
            StringReader reader = new StringReader(input);

            prog.Execute(reader, writer);

            return(writer.ToString());
        }
예제 #7
0
        public void Scanner_MiniPL_ExampleTest1()
        {
            string text = "var X : int := 4 + (6 * 2);\n" +
                          "print X;";

            string[] expectedTokens    = { "var", "X", ":", "int", ":=", "4", "+", "(", "6", "*", "2", ")", ";", "print", "X", ";" };
            string[] expectedTypeNames = { "keyword", "identifier", "colon", "type",        "assignment", "int",     "binary op",  "left paren",
                                           "int",     "binary op",  "int",   "right paren", "semicolon",  "keyword", "identifier", "semicolon" };

            Scanner      sc     = MiniPL.GetInstance().Scanner;
            List <Token> tokens = new List <Token>(sc.Tokenize(text, yieldEOF: false));

            for (int i = 0; i < tokens.Count; i++)
            {
                Assert.AreEqual(expectedTokens[i], tokens[i].Lexeme);
                Assert.AreEqual(expectedTypeNames[i], tokens[i].Type.Name);
            }
        }
예제 #8
0
        public void Scanner_MiniPL_ExampleTest3()
        {
            string text = "print \"Give a number\";\n" +
                          "var n : int;\n" +
                          "read n;\n" +
                          "var f : int := 1;\n" +
                          "var i : int;\n" +
                          "for i in 1..n do\n" +
                          "    f := f * i;\n" +
                          "end for;\n" +
                          "print \"The result is: \";\n" +
                          "print f;";

            string[] expectedTokens = { "print", "\"Give a number\"",   ";",
                                        "var",   "n",                   ":", "int",  ";",
                                        "read",  "n",                   ";",
                                        "var",   "f",                   ":", "int",  ":=","1",  ";",
                                        "var",   "i",                   ":", "int",  ";",
                                        "for",   "i",                   "in","1",    "..","n",  "do",
                                        "f",     ":=",                  "f", "*",    "i", ";",
                                        "end",   "for",                 ";",
                                        "print", "\"The result is: \"", ";",
                                        "print", "f",                   ";" };
            string[] expectedTypeNames = { "keyword",    "string",     "semicolon",
                                           "keyword",    "identifier", "colon",     "type",       "semicolon",
                                           "keyword",    "identifier", "semicolon",
                                           "keyword",    "identifier", "colon",     "type",       "assignment","int",         "semicolon",
                                           "keyword",    "identifier", "colon",     "type",       "semicolon",
                                           "keyword",    "identifier", "keyword",   "int",        "dots",      "identifier",  "keyword",
                                           "identifier", "assignment", "identifier","binary op",  "identifier","semicolon",
                                           "keyword",    "keyword",    "semicolon",
                                           "keyword",    "string",     "semicolon",
                                           "keyword",    "identifier", "semicolon" };

            Scanner      sc     = MiniPL.GetInstance().Scanner;
            List <Token> tokens = new List <Token>(sc.Tokenize(text, yieldEOF: false));

            for (int i = 0; i < tokens.Count; i++)
            {
                Assert.AreEqual(expectedTokens[i], tokens[i].Lexeme);
                Assert.AreEqual(expectedTypeNames[i], tokens[i].Type.Name);
            }
        }
예제 #9
0
        public void Scanner_MiniPL_TokenPositionTest()
        {
            string text = "print \"Give a number\";\n" +
                          "var n : int;\n" +
                          "read n;\n" +
                          "var f : int := 1;\n" +
                          "var i : int;\n" +
                          "for i in 1..n do\n" +
                          "    f := f * i;\n" +
                          "end for;\n" +
                          "print \"The result is: \";\n" +
                          "print f;";

            int[] expectedRows = new int[] { 0, 0, 0,
                                             1, 1, 1, 1, 1,
                                             2, 2, 2,
                                             3, 3, 3, 3, 3, 3, 3,
                                             4, 4, 4, 4, 4,
                                             5, 5, 5, 5, 5, 5, 5,
                                             6, 6, 6, 6, 6, 6,
                                             7, 7, 7,
                                             8, 8, 8,
                                             9, 9, 9 };
            int[] expectedCols = new int[] { 0, 6, 21,
                                             0, 4, 6, 8, 11,
                                             0, 5, 6,
                                             0, 4, 6, 8, 12, 15, 16,
                                             0, 4, 6, 8, 11,
                                             0, 4, 6, 9, 10, 12, 14,
                                             4, 6, 9, 11, 13, 14,
                                             0, 4, 7,
                                             0, 6, 23,
                                             0, 6, 7 };

            Scanner      sc     = MiniPL.GetInstance().Scanner;
            List <Token> tokens = new List <Token>(sc.Tokenize(text, yieldEOF: false));

            for (int i = 0; i < tokens.Count; i++)
            {
                Assert.AreEqual(expectedRows[i], tokens[i].TextPosition.Row);
                Assert.AreEqual(expectedCols[i], tokens[i].TextPosition.Column);
            }
        }
예제 #10
0
        public void Scanner_MiniPL_ExampleTest2()
        {
            string text = "var nTimes : int := 0;\n" +
                          "print \"How many times?\";\n" +
                          "read nTimes;\n" +
                          "var x : int;\n" +
                          "for x in 0..nTimes-1 do\n" +
                          "     print x;\n" +
                          "     print \" : Hello, World!\n\";\n" +
                          "end for;\n" +
                          "assert (x = nTimes);";

            string[] expectedTokens = { "var",    "nTimes",                 ":",  "int", ":=",     "0",      ";",
                                        "print",  "\"How many times?\"",    ";",
                                        "read",   "nTimes",                 ";",
                                        "var",    "x",                      ":",  "int", ";",
                                        "for",    "x",                      "in", "0",   "..",     "nTimes", "-","1","do",
                                        "print",  "x",                      ";",
                                        "print",  "\" : Hello, World!\n\"", ";",
                                        "end",    "for",                    ";",
                                        "assert", "(",                      "x",  "=",   "nTimes", ")",      ";" };

            string[] expectedTypeNames = { "keyword", "identifier", "colon",      "type",      "assignment", "int",         "semicolon",
                                           "keyword", "string",     "semicolon",
                                           "keyword", "identifier", "semicolon",
                                           "keyword", "identifier", "colon",      "type",      "semicolon",
                                           "keyword", "identifier", "keyword",    "int",       "dots",       "identifier",  "binary op","int","keyword",
                                           "keyword", "identifier", "semicolon",
                                           "keyword", "string",     "semicolon",
                                           "keyword", "keyword",    "semicolon",
                                           "keyword", "left paren", "identifier", "binary op", "identifier", "right paren", "semicolon" };

            Scanner      sc     = MiniPL.GetInstance().Scanner;
            List <Token> tokens = new List <Token>(sc.Tokenize(text, yieldEOF: false));

            for (int i = 0; i < tokens.Count; i++)
            {
                Assert.AreEqual(expectedTokens[i], tokens[i].Lexeme);
                Assert.AreEqual(expectedTypeNames[i], tokens[i].Type.Name);
            }
        }
예제 #11
0
        public void Semantics_DeclarationScanTest()
        {
            string text = "print \"Give a number\";\n" +
                          "var n : int;\n" +
                          "read n;\n" +
                          "var f : int := 1;\n" +
                          "var i : int;\n" +
                          "for i in 1..n do\n" +
                          "    f := f * i;\n" +
                          "end for;\n" +
                          "print \"The result is: \";\n" +
                          "print f;";
            MiniPL    miniPL = MiniPL.GetInstance();
            Scanner   sc     = miniPL.Scanner;
            Parser    ps     = miniPL.Parser;
            ParseTree ptree  = ps.Parse(sc.Tokenize(text));

            MiniPL.Runnable prog = miniPL.ProcessParseTree(ptree, ps.Errors, ps.IsValidParseTree);

            Assert.AreEqual(3, prog.declarations.Count);
        }
예제 #12
0
        public void Parser_MiniPLTest2()
        {
            string text = "var nTimes : int := 0;\n" +
                          "print \"How many times?\";\n" +
                          "read nTimes;\n" +
                          "var x : int;\n" +
                          "for x in 0..nTimes-1 do\n" +
                          "     print x;\n" +
                          "     print \" : Hello, World!\n\";\n" +
                          "end for;\n" +
                          "assert (x = nTimes);";

            MiniPL  miniPL = MiniPL.GetInstance();
            Scanner sc     = miniPL.Scanner;
            Parser  ps     = miniPL.Parser;

            ps.Parse(sc.Tokenize(text));
            List <Error> errors = ps.Errors;

            Assert.AreEqual(0, errors.Count);
        }
예제 #13
0
        public void Parser_MiniPLTest3()
        {
            string text = "print \"Give a number\";\n" +
                          "var n : int;\n" +
                          "read n;\n" +
                          "var f : int := 1;\n" +
                          "var i : int;\n" +
                          "for i in 1..n do\n" +
                          "    f := f * i;\n" +
                          "end for;\n" +
                          "print \"The result is: \";\n" +
                          "print f;";

            MiniPL    miniPL = MiniPL.GetInstance();
            Scanner   sc     = miniPL.Scanner;
            Parser    ps     = miniPL.Parser;
            ParseTree ptree  = ps.Parse(sc.Tokenize(text));

            List <Error> errors = ps.Errors;

            Assert.AreEqual(0, errors.Count);
        }
예제 #14
0
        public void Parser_ParseTreeTest()
        {
            string text = "var X : int := 4 + (6 * 2);\n" +
                          "print X;";

            MiniPL miniPL  = MiniPL.GetInstance();
            CFG    grammar = miniPL.Grammar;
            Dictionary <string, Nonterminal> vars  = miniPL.Nonterminals;
            Dictionary <string, Terminal>    terms = miniPL.Terminals;
            Scanner   sc    = miniPL.Scanner;
            Parser    ps    = miniPL.Parser;
            ParseTree ptree = ps.Parse(sc.Tokenize(text));

            // compare contents of tree to hand-drawn parse tree

            Assert.AreNotEqual(null, ptree);
            // 16 "real terminals", 2 epsilon
            Assert.AreEqual(18, ptree.SymbolCount(
                                s => s.GetSymbol() is Terminal));
            Assert.AreEqual(2, ptree.SymbolCount(
                                s => (s.GetSymbol() is Terminal) && (s.GetSymbol() as Terminal) == Terminal.EPSILON));
            Assert.AreEqual(3, ptree.SymbolCount(
                                s => (s.GetSymbol() is Terminal) && (s.GetSymbol() as Terminal).MatchedTokenType == miniPL.TokenTypes["int"]));
            Assert.AreEqual(2, ptree.SymbolCount(
                                s => (s.GetSymbol() is Terminal) && (s.GetSymbol() as Terminal).MatchedTokenType == miniPL.TokenTypes["binary_op"]));
            Assert.AreEqual(21, ptree.SymbolCount(
                                s => s.GetSymbol() is Nonterminal));
            // two actual binary operations, one -> epsilon
            Assert.AreEqual(3, ptree.SymbolCount(
                                s => (s.GetSymbol() is Nonterminal) && (s.GetSymbol() as Nonterminal) == vars["binary_operation"]));
            Assert.AreEqual(2, ptree.SymbolCount(
                                s => (s.GetSymbol() is Nonterminal) && (s.GetSymbol() as Nonterminal) == vars["statement"]));
            Assert.IsTrue(ptree.DepthContains(12,
                                              s => (s.GetSymbol() is Terminal) && (s.GetSymbol() as Terminal).MatchedTokenType == miniPL.TokenTypes["int"]));
            Assert.IsTrue(ptree.DepthContains(11,
                                              s => (s.GetSymbol() is Terminal) && (s.GetSymbol() as Terminal).MatchedTokenType == miniPL.TokenTypes["int"]));
            Assert.IsTrue(ptree.DepthContains(8,
                                              s => (s.GetSymbol() is Terminal) && (s.GetSymbol() as Terminal).MatchedTokenType == miniPL.TokenTypes["int"]));
        }
예제 #15
0
        public void Parser_LexicalErrorTest()
        {
            // check that the parser can disregard error tokens and log them as errors

            string text = "]var X :[ int := 4 +' (6 * 2);\n" +
                          "print X###;";

            MiniPL    miniPL = MiniPL.GetInstance();
            Scanner   sc     = miniPL.Scanner;
            Parser    ps     = miniPL.Parser;
            ParseTree ptree  = ps.Parse(sc.Tokenize(text));

            List <Error> errors = ps.Errors;

            Assert.AreEqual(6, errors.Count);

            Assert.AreNotEqual(null, ptree);
            Assert.AreEqual(18, ptree.SymbolCount(
                                s => s.GetSymbol() is Terminal));
            Assert.AreEqual(2, ptree.SymbolCount(
                                s => (s.GetSymbol() is Terminal) && (s.GetSymbol() as Terminal) == Terminal.EPSILON));
            Assert.AreEqual(3, ptree.SymbolCount(
                                s => (s.GetSymbol() is Terminal) && (s.GetSymbol() as Terminal).MatchedTokenType == miniPL.TokenTypes["int"]));
            Assert.AreEqual(2, ptree.SymbolCount(
                                s => (s.GetSymbol() is Terminal) && (s.GetSymbol() as Terminal).MatchedTokenType == miniPL.TokenTypes["binary_op"]));
            Assert.AreEqual(21, ptree.SymbolCount(
                                s => s.GetSymbol() is Nonterminal));
            Assert.AreEqual(3, ptree.SymbolCount(
                                s => (s.GetSymbol() is Nonterminal) && (s.GetSymbol() as Nonterminal) == miniPL.Nonterminals["binary_operation"]));
            Assert.AreEqual(2, ptree.SymbolCount(
                                s => (s.GetSymbol() is Nonterminal) && (s.GetSymbol() as Nonterminal) == miniPL.Nonterminals["statement"]));
            Assert.IsTrue(ptree.DepthContains(12,
                                              s => (s.GetSymbol() is Terminal) && (s.GetSymbol() as Terminal).MatchedTokenType == miniPL.TokenTypes["int"]));
            Assert.IsTrue(ptree.DepthContains(11,
                                              s => (s.GetSymbol() is Terminal) && (s.GetSymbol() as Terminal).MatchedTokenType == miniPL.TokenTypes["int"]));
            Assert.IsTrue(ptree.DepthContains(8,
                                              s => (s.GetSymbol() is Terminal) && (s.GetSymbol() as Terminal).MatchedTokenType == miniPL.TokenTypes["int"]));
        }
예제 #16
0
        public void Parser_SyntaxErrorTest()
        {
            string text = "var nTimes : int := -0;\n" + // no unary negative
                          "print \"How many times?\";\n" +
                          "read nTimes + 1;\n" +        // read expr
                          "+" +                         // stray +
                          "x : int;\n" +                // declaration without var
                          "for x in 0..nTimes-1 do\n" +
                          "     print x;\n" +
                          "     print \" : Hello, World!\n\";\n" +
                          "end for;\n" +
                          "*/" +                     // stray block comment end
                          "assert (x = nTimes); - "; // stray -

            MiniPL  miniPL = MiniPL.GetInstance();
            Scanner sc     = miniPL.Scanner;
            Parser  ps     = miniPL.Parser;

            ps.Parse(sc.Tokenize(text));
            List <Error> errors = ps.Errors;

            Assert.AreEqual(6, errors.Count);
        }
예제 #17
0
        public void Parser_MiniPL_LL1FollowSetsTest()
        {
            MiniPL miniPL  = MiniPL.GetInstance();
            CFG    grammar = miniPL.Grammar;
            Dictionary <string, Nonterminal> vars  = miniPL.Nonterminals;
            Dictionary <string, Terminal>    terms = miniPL.Terminals;

            ISet <Terminal> followSet = grammar.Follow(vars["program"]);

            Assert.IsTrue(followSet.SetEquals(new Terminal[] {
                Terminal.EOF
            }));

            followSet = grammar.Follow(vars["statements"]);
            Assert.IsTrue(followSet.SetEquals(new Terminal[] {
                terms["end"], Terminal.EOF
            }));

            followSet = grammar.Follow(vars["statements_head"]);
            Assert.IsTrue(followSet.SetEquals(new Terminal[] {
                terms["end"], Terminal.EOF, terms["var"], terms["assert"], terms["read"], terms["print"], terms["for"], terms["identifier"]
            }));

            followSet = grammar.Follow(vars["statements_tail"]);
            Assert.IsTrue(followSet.SetEquals(new Terminal[] {
                terms["end"], Terminal.EOF
            }));

            followSet = grammar.Follow(vars["statement"]);
            Assert.IsTrue(followSet.SetEquals(new Terminal[] {
                terms[";"]
            }));

            followSet = grammar.Follow(vars["declaration"]);
            Assert.IsTrue(followSet.SetEquals(new Terminal[] {
                terms[";"]
            }));

            followSet = grammar.Follow(vars["declaration_assignment"]);
            Assert.IsTrue(followSet.SetEquals(new Terminal[] {
                terms[";"]
            }));

            followSet = grammar.Follow(vars["expression"]);
            Assert.IsTrue(followSet.SetEquals(new Terminal[] {
                terms[".."], terms["do"], terms[")"], terms[";"]
            }));

            followSet = grammar.Follow(vars["unary_operation"]);
            Assert.IsTrue(followSet.SetEquals(new Terminal[] {
                terms[".."], terms["do"], terms[")"], terms[";"]
            }));

            followSet = grammar.Follow(vars["binary_operation"]);
            Assert.IsTrue(followSet.SetEquals(new Terminal[] {
                terms[".."], terms["do"], terms[")"], terms[";"]
            }));

            followSet = grammar.Follow(vars["operand"]);
            Assert.IsTrue(followSet.SetEquals(new Terminal[] {
                terms[".."], terms["do"], terms[")"], terms[";"], terms["binary_operator"]
            }));
        }