/// <summary> /// Создаёт дерево программы /// </summary> /// <param name="code">Исходный код</param> /// <returns>Дерево программы</returns> private Tree GetProgramTree(string code) { string[] replace = new string[] { " ", "\r", "\n", "\t" }; for (int i = 0; i < replace.Length; i++) code = code.Replace(replace[i], "☺" + replace[i]); code = code.Replace(";", ";☺"); string[] words = code.Split('☺'); string str_stack = ""; Tree root_program = new Tree(); Tree cursor = root_program; cursor.is_root = true; bool is_wait = true; bool is_func = false; int words_count = 0, line_count = 1; foreach (string word in words) { Regex new_line = new Regex(@"(\n){1}", RegexOptions.Multiline); Match nl_match = new_line.Match(word); if (nl_match.Success) line_count++; if (!string.IsNullOrWhiteSpace(str_stack) && !is_wait) throw new CompileException("Ошибка, ожидалась ; после " + str_stack.Trim(), line_count); is_wait = false; words_count += word.Length; //str_stack = str_stack.Trim(); str_stack += word; while (!cursor.wait && (cursor.type == "if" || cursor.type == "for" || cursor.type == "while")) cursor = cursor.parent; Match match; #region Вырезаем комментарии if ((match = Regexs.Match(str_stack, Regs.Comments)).Success) { str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); is_wait = true; continue; } else if ((match = Regexs.Match(str_stack, Regs.CommentsStart)).Success) { is_wait = true; continue; } else if ((match = Regexs.Match(str_stack, Regs.Comment)).Success) { str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); is_wait = true; continue; } else if ((match = Regexs.Match(str_stack, Regs.CommentStart)).Success) { is_wait = true; continue; } #endregion #region Корень программы, блоки функций и операторов не обрабатываются #region PROGRAM else if ((match = Regexs.Match(str_stack, Regs.Program)).Success) { if (is_func) throw new CompileException("Блок program не может находиться внутри исполняемого блока программы", line_count); while (!cursor.is_root) cursor = cursor.parent; str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor.AppendChild(new Tree(match.Value, words_count - match.Value.TrimStart().Length, words_count, line_count)); cursor = cursor.GetLastChild(); cursor.type = "program"; cursor.wait = true; continue; } #endregion #region CONST else if ((match = Regexs.Match(str_stack, Regs.Const)).Success) { if (is_func) throw new CompileException("Блок const не может находиться внутри исполняемого блока программы", line_count); while (!cursor.is_root) cursor = cursor.parent; str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor.AppendChild(new Tree(match.Value, words_count - match.Value.TrimStart().Length, words_count, line_count)); cursor = cursor.GetLastChild(); cursor.type = "const"; continue; } #endregion #region TYPE else if ((match = Regexs.Match(str_stack, Regs.Type)).Success) { if (is_func) throw new CompileException("Блок type не может находиться внутри исполняемого блока программы", line_count); while (!cursor.is_root) cursor = cursor.parent; str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor.AppendChild(new Tree(match.Value, words_count - match.Value.TrimStart().Length, words_count, line_count)); cursor = cursor.GetLastChild(); cursor.type = "type"; continue; } #endregion #region VAR else if ((match = Regexs.Match(str_stack, Regs.Var)).Success) { if (is_func) throw new CompileException("Блок var не может находиться внутри исполняемого блока программы", line_count); while (!cursor.is_root) cursor = cursor.parent; str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor.AppendChild(new Tree(match.Value, words_count - match.Value.TrimStart().Length, words_count, line_count)); cursor = cursor.GetLastChild(); cursor.type = "var"; continue; } #endregion #region FUNCTION else if ((match = Regexs.Match(str_stack, Regs.Function)).Success) { if (is_func) throw new CompileException("Блок function не может находиться внутри исполняемого блока программы", line_count); while (!cursor.is_root) cursor = cursor.parent; str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor.AppendChild(new Tree(match.Value, words_count - match.Value.TrimStart().Length, words_count, line_count)); cursor = cursor.GetLastChild(); cursor.type = "function"; cursor.wait = true; cursor.is_root = true; continue; } #endregion #region PROCEDURE else if ((match = Regexs.Match(str_stack, Regs.Procedure)).Success) { if (is_func) throw new CompileException("Блок procedure не может находиться внутри исполняемого блока программы", line_count); while (!cursor.is_root) cursor = cursor.parent; str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor.AppendChild(new Tree(match.Value, words_count - match.Value.TrimStart().Length, words_count, line_count)); cursor = cursor.GetLastChild(); cursor.type = "procedure"; cursor.wait = true; cursor.is_root = true; continue; } #endregion #region RECORD else if ((match = Regexs.Match(str_stack, Regs.Record)).Success) { str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor.AppendChild(new Tree(match.Value, words_count - match.Value.TrimStart().Length, words_count, line_count)); cursor = cursor.GetLastChild(); cursor.type = "record"; continue; } #endregion #endregion #region Код программы, обработка операторов #region IF else if ((match = Regexs.Match(str_stack, Regs.If)).Success) { if (!is_func) throw new CompileException("Блок if не может находиться вне исполняемого блока программы", line_count); str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor.AppendChild(new Tree(match.Value, words_count - match.Value.TrimStart().Length, words_count, line_count)); cursor = cursor.GetLastChild(); cursor.type = "if"; cursor.ignore_sibling = true; cursor.ignore_exit = true; continue; } #endregion #region END + ELSE else if ((match = Regexs.Match(str_stack, Regs.EndElse)).Success) { if (!is_func) throw new CompileException("Блок else не может находиться вне исполняемого блока программы", line_count); str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor = cursor.parent; cursor.wait = true; continue; } #endregion #region ELSE else if ((match = Regexs.Match(str_stack, Regs.Else)).Success) { if (!is_func) throw new CompileException("Блок else не может находиться вне исполняемого блока программы", line_count); if (cursor.type != "if") throw new CompileException("Потерян блок if для конструкции else", line_count); if (!string.IsNullOrWhiteSpace(match.Value)) cursor.AppendChild(new Tree(match.Value, words_count - match.Value.TrimStart().Length, words_count, line_count)); cursor.wait = true; Regex r_temp = new Regex(@"(.*)\belse\b", RegexOptions.Multiline); match = r_temp.Match(str_stack); str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); continue; } #endregion #region FOR else if ((match = Regexs.Match(str_stack, Regs.For)).Success) { if (!is_func) throw new CompileException("Блок for не может находиться вне исполняемого блока программы", line_count); str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor.AppendChild(new Tree(match.Value, words_count - match.Value.TrimStart().Length, words_count, line_count)); cursor = cursor.GetLastChild(); cursor.type = "for"; continue; } #endregion #region WHILE else if ((match = Regexs.Match(str_stack, Regs.While)).Success) { if (!is_func) throw new CompileException("Блок while не может находиться вне исполняемого блока программы", line_count); str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor.AppendChild(new Tree(match.Value, words_count - match.Value.TrimStart().Length, words_count, line_count)); cursor = cursor.GetLastChild(); cursor.type = "while"; continue; } #endregion #endregion #region BEGIN else if ((match = Regexs.Match(str_stack, Regs.Begin)).Success) { while (!cursor.is_root && !is_func) cursor = cursor.parent; if (cursor.type == "function" || cursor.type == "procedure") cursor.is_root = false; str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor.AppendChild(new Tree(match.Value, words_count - match.Value.TrimStart().Length, words_count, line_count)); cursor = cursor.GetLastChild(); cursor.type = "begin"; cursor.ignore_enter = true; cursor.ignore_exit = true; if (!is_func) { is_func = true; cursor.is_root = true; } continue; } #endregion #region END if ((match = Regexs.Match(str_stack, Regs.EndProgram)).Success) { if (cursor.is_root) is_func = false; else throw new CompileException("Конец программы встретился раньше, чем закрылись все операторные скобки", line_count); str_stack = ""; cursor = root_program; break; } else if ((match = Regexs.Match(str_stack, Regs.End)).Success) { if (cursor.is_root) is_func = false; str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor = cursor.parent; continue; } #endregion #region Операции else if ((match = Regexs.Match(str_stack, Regs.Operation)).Success) { str_stack = str_stack.Remove(str_stack.IndexOf(match.Value), match.Value.Length); cursor.AppendChild(new Tree(match.Value, words_count - match.Value.TrimStart().Length, words_count, line_count)); cursor.GetLastChild().type = "operation"; continue; } #endregion is_wait = true; } return root_program; }