Esempio n. 1
0
            public void TestNonterminal()
            {
                Nonterminal term = new Nonterminal();

                string[] arr = { "123", "345" };
                term.Add(arr);
                List <string> list = new List <string>()
                {
                    "qqq", "ddd"
                };

                term.Add(list);
                Assert.AreEqual(2, term.Size);
                term.Add(new List <string>()
                {
                    "ggg", "www"
                });
                Assert.AreEqual(3, term.Size);
            }
        public StackMachineTest()
        {
            EasyLexerLang = new LexerLang(new Terminal[] {
                new Terminal("ASSIGN_OP", "^=$"),
                new Terminal("VAR", "^[a-zA-Z]+$", uint.MaxValue),
                new Terminal("DIGIT", "^0|([1-9][0-9]*)$"),
                new Terminal("OP", "^\\+|-|\\*|/$"),
                new Terminal("WHILE_KW", "^while$", 0),
                new Terminal("PRINT_KW", "^print$", 0),
                new Terminal("L_QB", "^{$"),
                new Terminal("R_QB", "^}$"),
                new Terminal("L_B", "^\\($"),
                new Terminal("R_B", "^\\)$"),

                new Terminal("CH_SPACE", "^ $"),
                new Terminal("CH_LEFTLINE", "^\r$"),
                new Terminal("CH_NEWLINE", "^\n$"),
                new Terminal("CH_TAB", "^\t$")
            });

            /*
             * Правила стековой машины:
             * Все команды выполняются в постфиксной записи.
             *
             * {value logical, value addr, "if", com1}
             * Где:
             * logical - если 0, то переход к com1. Ложь - переход к адресу addr.
             * addr - адрес перехода.
             *
             * {value addr, "goto"}
             * Переход к адресу addr.
             *
             */

            Nonterminal lang = new Nonterminal("lang",
                                               (List <string> commands, ActionInsert insert, int id) =>
            {
                for (int i = 0; i < id; i++)
                {
                    insert(i);
                }
            }, ZERO_AND_MORE);
            Nonterminal value = new Nonterminal("value",
                                                (List <string> commands, ActionInsert insert, int id) =>
            {
                insert();
            }, OR, "VAR", "DIGIT");
            Nonterminal stmt = new Nonterminal("stmt",
                                               (List <string> commands, ActionInsert insert, int id) =>
            {
                insert(1);
                insert(0);
            }, AND,
                                               value, new Nonterminal("(OP value)*",
                                                                      (List <string> commands, ActionInsert insert, int id) =>
            {
                for (int i = 0; i < id; i++)
                {
                    insert(i);
                }
            }, ZERO_AND_MORE, new Nonterminal("OP & value",
                                              (List <string> commands, ActionInsert insert, int id) =>
            {
                insert(1);
                insert(0);
            }, AND, "OP", value)));
            Nonterminal assign_expr = new Nonterminal("assign_expr",
                                                      (List <string> commands, ActionInsert insert, int id) =>
            {
                insert(0);
                insert(2);
                insert(1);
            }, AND,
                                                      "VAR", "ASSIGN_OP", stmt);
            Nonterminal while_expr = new Nonterminal("while_expr",
                                                     // Нужно преобразовать в стековый код.
                                                     (List <string> commands, ActionInsert insert, int id) =>
            {
                insert(2);
                commands.Add("?");     // Адрес с истиной.
                int indexAddrTrue = commands.Count - 1;
                commands.Add("if");
                commands.Add("?");     // Адрес с ложью.
                int indexAddrFalse = commands.Count - 1;
                commands.Add("goto");
                // Сюда надо попасть, если true.
                commands[indexAddrTrue] = commands.Count.ToString();
                insert(5);            // Тело while.
                commands.Add(indexAddrTrue.ToString());
                commands.Add("goto"); // Команда перехода в if к while.
                // Надо выйти из цикла, если false:
                commands[indexAddrFalse] = commands.Count.ToString();
            }, AND,
                                                     "WHILE_KW", "L_B", stmt, "R_B", "L_QB", lang, "R_QB");
            Nonterminal expr = new Nonterminal("expr",
                                               // Нужно преобразовать в стековый код.
                                               (List <string> commands, ActionInsert insert, int id) =>
            {
                switch (id)
                {
                case 0:
                    {
                        insert();
                    }
                    break;

                case 1:
                    {
                        insert();
                    }
                    break;

                case 2:
                    {
                        commands.Add("print");
                    }
                    break;
                }
            }, OR,
                                               assign_expr, while_expr, "PRINT_KW");

            lang.Add(expr);
            EasyParserLang = new ParserLang(lang);

            SuperEasyParserLang = new ParserLang(new Nonterminal("easy lang",
                                                                 (List <string> commands, ActionInsert insert, int id) =>
            {
                insert(0);
                insert(2);
                insert(1);
            }, AND, "VAR", "ASSIGN_OP", "DIGIT"));

            EasyStackLang = new MyEasyStackLang();
        }