public void Merge(ReportParser reportParser) { if (Compile != null) { if (reportParser.Compile != null) { if (Compile.Current == null) { Compile = reportParser.Compile; } else if (reportParser.Compile.Current != null) { Compile.Add(reportParser.Compile); } else { Info.AddInfo($"Информацию компиляции пропущена при добавлении к информации: {Compile}"); } } else { Info.AddInfo($"Не удалось добавить информацию компиляции к информации: {Compile}"); } } else { Compile = reportParser.Compile; } Info.AddRange(reportParser.Info); if (IsSuccess) { CheckTreeOf_RuleOr_Error(Compile); } }
private ReportParser RuleOR(int deep, IList <Token> tokens, ref int begin, ref int end) { ParserToken comp = new ParserToken(this, OR, -1, FreeId++); ITreeNode <object> compileTree = new TreeNode <object>(comp); ReportParser output = new ReportParser(compileTree); foreach (object o in this) { comp.Helper++; if (o is Terminal) { if (begin > end) { output.Info.Add(new ReportParserInfoLine( "Входные жетоны закончились", o, null, begin)); } else if (!o.Equals(tokens[begin++].Type)) { output.Info.Add(new ReportParserInfoLine(o, tokens[--begin], tokens, begin)); } else { compileTree.Add(tokens[begin - 1]); output.Info.Success(tokens[begin - 1].ToString()); return(output); } } else if (o is Nonterminal nonterminal) { ReportParser buffer = nonterminal.PCheckRule(deep, tokens, ref begin, ref end); if (buffer.IsSuccess) { output.Merge(buffer); output.Info.Success(o.ToString()); return(output); // Да, этот нетерминал нам подходит. } else { buffer.CompileCancel(); output.Merge(buffer); } } else { throw new Exception($"Unexpected type {o.GetType()} of {o} in list"); } } if (begin < tokens.Count) { output.Info.Add(new ReportParserInfoLine("Для оператора OR не найдено ни одного истинного выражения.", this, tokens[begin], tokens, -1)); } output.CompileCancel(); return(output); }
private ReportParser RuleAND(int deep, IList <Token> tokens, ref int begin, ref int end) { ITreeNode <object> compileTree = new TreeNode <object>(new ParserToken(this, AND, Id: FreeId++)); ReportParser output = new ReportParser(compileTree); int b = begin; int e = end; int i = -1; foreach (object o in this) { i++; if (o is Terminal) { if (begin > end) { output.Info.Add(new ReportParserInfoLine( "Входные жетоны закончились", o, null, begin)); } else if (!o.Equals(tokens[begin++].Type)) { output.Info.Add(new ReportParserInfoLine(o, tokens[--begin], tokens, begin)); } else { compileTree.Add(tokens[begin - 1]); output.Info.Success(tokens[begin - 1].ToString()); } } else if (o is Nonterminal nonterminal) { output.Merge(nonterminal.PCheckRule(deep, tokens, ref begin, ref end)); if (!output.IsSuccess) { output.Info.Add(new ReportParserInfoLine(o, null, tokens, begin)); } } if (!output.IsSuccess) { begin = b; end = e; output.CompileCancel(); return(output); } } if (!output.IsSuccess) { begin = b; end = e; output.CompileCancel(); } return(output); }
private ReportParser RuleZERO_AND_MORE(int deep, IList <Token> tokens, ref int begin, ref int end) { ParserToken compile = new ParserToken(this, ZERO_AND_MORE, -1, FreeId++); ReportParser output = new ReportParser(compile); do { RuleMORE(deep, tokens, output, ref begin, ref end); compile.Helper++; }while (output.IsSuccess); output.Info.Success($"Нетерминалы ZERO_AND_MORE всегда успешны. Текущий: {ToString()}"); return(output); }
private bool RuleMORE(int deep, IList <Token> tokens, ReportParser output, ref int begin, ref int end) { int b = begin; int e = end; if (Count != 1) { throw new NotSupportedException($"Правило {rule} поддерживает только один элемент в нетерминале."); } foreach (object o in this) { if (o is Terminal) { if (begin > end) { output.Info.Add(new ReportParserInfoLine( "Входные жетоны закончились", o, null, begin)); } else if (!o.Equals(tokens[begin++].Type)) { output.Info.Add(new ReportParserInfoLine(o, tokens[--begin], tokens, begin)); } else { output.Compile.Add(tokens[begin - 1]); } } else if (o is Nonterminal nonterminal) { output.Merge(nonterminal.PCheckRule(deep, tokens, ref begin, ref end)); if (!output.IsSuccess) { output.Info.Add(new ReportParserInfoLine(o, null, tokens, begin)); } } if (!output.IsSuccess) { begin = b; end = e; return(output.IsSuccess); } } if (!output.IsSuccess) { begin = b; end = e; } return(output.IsSuccess); }
/// <summary> /// Проверяет, чтобы заданные жетоны соответствовали нетерминалу. /// </summary> /// <param name="tokens">Список жетонов, которые надо проверить.</param> /// <param name="begin">Первый доступный индекс в листе tokens.</param> /// <param name="end">Последний доступный индекс в листе tokens.</param> /// <returns>Отчёт анализа кода.</returns> private ReportParser PCheckRule(int deep, IList <Token> tokens, ref int begin, ref int end) { if (tokens == null) { throw new ArgumentNullException("Список жетонов должен был инициализирован."); } ReportParser output = new ReportParser(); ulong currentFreeId = FreeId; output.Info.AddInfo($"Зашёл в нетерминал: {ToString()}, FreeId: RPC{currentFreeId}"); if (--deep <= 0) { output.Info.Add(new ReportParserInfoLine("Обнаружена бесконечная рекурсия. Выход...")); } else { switch (rule) { case AND: output.Merge(RuleAND(deep, tokens, ref begin, ref end)); break; case ONE_AND_MORE: output.Merge(RuleONE_AND_MORE(deep, tokens, ref begin, ref end)); break; case OR: output.Merge(RuleOR(deep, tokens, ref begin, ref end)); break; case ZERO_AND_MORE: output.Merge(RuleZERO_AND_MORE(deep, tokens, ref begin, ref end)); break; case NONE: output.Info.Add(new ReportParserInfoLine("Игнорирую.")); break; default: throw new NotImplementedException($"Оператор {Enum.GetName(typeof(RuleOperator), rule)} не реализован."); } } output.Info.AddInfo($"Состояние отчёта: {output.IsSuccess}, выхожу из нетерминала: {ToString()} RPC{currentFreeId}"); return(output); }