Не могу изменить строку. Где моя ошибка?

150
29 сентября 2019, 05:20

Я разрабатываю свой мини-интерпретатор (не спрашивайте зачем), так вот у меня возникла проблема: "Препретатор"(как я его назвал) в самом начале обходит весь файл с кодом и ищет по ключевому слову "function" функции, а затем добавляет их в список в виде структуры (указывается номер строки её начала). Далее, в основном цикле, когда доходит очередь до строки вызова функции, "постпретатор" берёт структуру из списка и добавляет в неё номер строки инициализатора этой функции, затем оно перед символом завершения функции ("}") оно пишет команду вида "goto;8" и затем переводит номер строки выполнения на номер строку начала функции, затем после выполнения функции оно должно перевести номер строки выполнения обратно в основной цикл. Но функция может находится в любой части скрипта, поэтому и был придуман "препретатор". У меня же с одной функцией, всё работает, а вот с двумя уже не хочет: оно почему-то не подставляет команду перевода номера строки в первую функцию, а во вторую подставляет нормально.

Основной код C#
    /// <summary>
    /// Структура функции
    /// </summary>
    struct Function
    {
        public int start;
        public int point;
        public string name;
    }
    /// <summary>
    /// Список структур функции
    /// </summary>
    static SortedList<string, Function> funct = new SortedList<string, Function>();
    /// <summary>
    /// Препретатор функция
    /// </summary>
    /// <param name="game">Массив строк всего скрипта</param>
    /// <param name="main">Сам скрипт</param>
    public static void Compilation(string[] game, ref string main)
    {
        //funct.Clear();
        for (int i = 0; i < game.Length; i++)
        {
            if (game[i].Split(';')[0] == "function")
            {
                //создание или "взятие" функции
                Function fn;
                if (!funct.ContainsKey(game[i].Split(';')[1]))
                {
                    fn = new Function();
                    fn.start = i + 1;
                    string name = game[i].Split(';')[1];
                    fn.name = name;
                    funct.Add(name, fn);
                }
                else
                {
                    fn = funct[game[i].Split(';')[1]];
                }
                //Подсчёт строк функции
                int o = 1;
                for (; !game[i + o].EndsWith("}"); o++) ;

                var rrrhhh = ""; //временная переменная с итоговым кодом скрипта
                var telo = "";//тело функции
                for (int p = 0; p < ((i + o)); p++)
                {
                    rrrhhh += game[p] + "\n";  //заполнение до конца функции                      
                }
                for (int q = i; q < i+o; q++)
                {
                    telo += game[q] + "\n"; //заполнение тела
                }
                telo = telo.Split('\n')[telo.Split('\n').Length - 2];//обрезка } (там 2 должно быть, потому что индекс с 0, а количество с 1)
                //Console.WriteLine(telo);
                if (!telo.Contains("goto;"))
                    rrrhhh = rrrhhh.Insert(rrrhhh.Length, String.Format("goto;{0}", fn.point)+"\n}");//если "гото" нет, то добавляем
                else//иначе изменяем
                {
                    rrrhhh = rrrhhh.Substring(0, rrrhhh.Length - 3);//обрезаем перенос строки и }
                    int y = rrrhhh.Length-1;//получаем длинну в виде индекса
                    int t = 0;//создает временную переменную
                    for (; rrrhhh[y] == ';'; y--, t++) ;//считаем от конца и до ; (это символ передачи аргументов)
                    //t++;
                    rrrhhh = rrrhhh.Substring(0, rrrhhh.Length - t);//обрезаем по него
                    rrrhhh += ";" + fn.point.ToString() + "\n}";//добавляем новый "гото"
                    //Console.WriteLine(rrrhhh);
                }
                main = rrrhhh; //изменяем основной скрипт                                    
            }
        }
    }
    /// <summary>
    /// Постпретатор функция
    /// </summary>
    /// <param name="game">Массив строк со скриптом</param>
    /// <param name="main">Сам скрипт</param>
    /// <param name="name">Имя функции</param>
    public static void Compilation(string[] game, ref string main, string name)
    {
        ///Тут всё почти также как и там, но другой начало
        for (int i = 0; i < game.Length; i++)
        {
            if (game[i].Split(';')[0] == "function")
            {
                //Console.WriteLine(i);
                Function fn = funct[name]; //получем функцию из списка по её имени
                //Далее всё вроде так же, хотя я мог что то изменить
                int o = 1;
                for (; !game[i + o].EndsWith("}"); o++) ;
                var rrrhhh = "";
                var telo = "";
                for (int p = 0; p < ((i + o)); p++)
                {
                    rrrhhh += game[p] + "\n";
                }
                for (int q = i; q < i + o; q++)
                {
                    telo += game[q] + "\n";
                }
                telo = telo.Split('\n')[telo.Split('\n').Length - 2];

                if (!telo.Contains("goto;"))
                    rrrhhh = rrrhhh.Insert(rrrhhh.Length, String.Format("goto;{0}", fn.point) + "\n}");
                else
                {
                    rrrhhh = rrrhhh.Substring(0, rrrhhh.Length - 3);
                    int y = rrrhhh.Length - 1;
                    int t = 0;
                    for (; rrrhhh[y] == ';'; y--, t++) ;
                    //t++;
                    rrrhhh = rrrhhh.Substring(0, rrrhhh.Length - t);
                    rrrhhh += ";" + fn.point.ToString() + "\n}";
                    //Console.WriteLine(rrrhhh);
                }
                main = rrrhhh;
                //Console.WriteLine(telo);
            }
        }
    }
    public static void loadgame(string path)
       {
       //Начало препретатора
        Console.WriteLine("Start Compilation");
        Compilation(game.Split('\n'), ref game);
        lenght = game.Split('\n').Length;
        Console.WriteLine("Stop Compilation");
        //конец препретатора
        for (int i = 0; i < lenght; i++)
        {
            switch (game.Split('\n')[i].Split(';')[0])
            {
                    case "func":
                    //func;test
                    Function fc = funct[game.Split('\n')[i].Split(';')[1]]; //получение из аргумента имени функции                      
                    fc.point = i+2; //передача текущего номера строки
                    funct[game.Split('\n')[i].Split(';')[1]] = fc; //замена функции в списке
                    Compilation(game.Split('\n'), ref game, game.Split('\n')[i].Split(';')[1]); //запуск постпретатора
                    //Compilation(game.Split('\n'), ref game);
                    lenght = game.Split('\n').Length;//пересчёт новой общей длинны скрипта
                    i = fc.start;//передача управления другой строке
                    break;
            }
        }

}

Это сам скрипт

func;test
//mess - просто текст в консоль выводит
mess;Добро пожаловать в Test.
func;fc
//функции
function;test
isfunction;
mess;Функция, функция
mess;Тело, тело
mess;Кто то батя в C#
}
isfunction;
function;fc
isfunction;
mess;Функция другая
}
Answer 1

Используй отладчик. В методе Compilation 2 проблемы, одна фундаментальная.

1) Ты смотришь окончание строки, но не предусматриваешь возможный перевод строки, пробел, табуляцию

                //Подсчёт строк функции
                int o = 1;
                for (; !game[i + o].TrimEnd('\n', '\r').EndsWith("}"); o++) ;

2) В конце метода ты изменяешь основную переменную main, но расчёты ведешь на старых данных по переменной game. Тебе надо или отказаться от переменной game, или делать в неё инсерт строки goto.

                main = rrrhhh; //изменяем основной скрипт                                    

READ ALSO
Не видно ui обьектов в Canvas в unity

Не видно ui обьектов в Canvas в unity

Не видно ui обьектов в canvasУ меня 2 canvas, я не вижу обьектов на втором canvas они невидимые, почему так

104
Excel проверка значения ячейки на шаблон

Excel проверка значения ячейки на шаблон

Символы могут быть разнымиПробелы могут быть тоже

125
Как сериализовать Int из XML?

Как сериализовать Int из XML?

Как из этой строки достать просто Int32, пользуясь SystemXml

126
Некорректное создание кораблей

Некорректное создание кораблей

Всем приветСитуация следующая: Есть модуль создания волн вражеских кораблей

122