Exemplo n.º 1
0
    /// <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;
    }