/// <summary> /// Быстрое проведение тестирования <see cref="Parser.ParserLang"/>. /// Удаляет жетоны с CH_. /// </summary> /// <param name="resource">Текст тестирования.</param> /// <param name="isSuccess">True, если ожидается успех парсирования.</param> /// <param name="tokens">Количество ожидаемых жетонов. Установите -1 для игнорирования.</param> /// <param name="parser">Особые правила парсера. Оставьте null, если нужен язык <see cref="parserLang"/>.</param> /// <param name="lexer">Особые правила лексера. Оставьте null, если нужен язык <see cref="lexerLang"/>.</param> public ReportParser CheckTest(string resource, bool isSuccess = true, int tokens = -1, ParserLang parser = null, LexerLang lexer = null) { if (parser == null) { parser = parserLang; } if (lexer == null) { lexer = lexerLang; } List <Token> listT = lexer.SearchTokens(StringToStream(resource)); Assert.IsNotNull(listT); Console.WriteLine("Count tokens: " + listT.Count); foreach (Token token in listT) { Console.WriteLine(token); } Console.WriteLine("\n ---- Without CH_:"); listT.RemoveAll((Token t) => t.Type.Name.Contains("CH_")); Console.WriteLine("Count tokens: " + listT.Count); foreach (Token token in listT) { Console.WriteLine(token); } ReportParser report = parser.Check(listT); Console.WriteLine(report); if (tokens != -1) { Assert.AreEqual(tokens, listT.Count); } Assert.AreEqual(isSuccess, report.IsSuccess); return(report); }
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(); }