Задать вопрос
@MicrofCorp

Где моя ошибка в C# коде?

Я разрабатываю свой мини-интерпретатор (не спрашивайте зачем), так вот у меня возникла проблема: "Препретатор"(как я его назвал) в самом начале обходит весь файл с кодом и ищет по ключевому слову "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;Функция другая
}
Ссылка на GitHub(это я туда ещё не выкладывал)

P.S. У меня интерпретатор, а не компилятор и работаю я со своим скриптовым языком, поэтому не надо говорить про "компиляцию C# на лету" и информацию по компиляторам, у них немного другой принцип и суть, чем у меня
  • Вопрос задан
  • 331 просмотр
Подписаться 1 Простой 4 комментария
Пригласить эксперта
Ответы на вопрос 4
@CHolfield
Ты придумал исключительно дебильную шнягу, и даже попытался воплотить ее. Тебе надо почитать теорию создания компиляторов, что-нибудь от Intel они интересно пишут. На англ все, правда)
Ответ написан
yarosroman
@yarosroman Куратор тега C#
C# the best
Зачем такие сложности, если можно на лету делать компиляцию C# и использовать ее.
Ответ написан
@Stormbringer-s
Готовый скриптовый язык возьми типа луа/питон.
Ответ написан
@MicrofCorp Автор вопроса
На Stack Overflow нормально ответили и не выпендривались, как тут. Проблема была в переменных game и main. Вот решение:

Код
/// <summary>
        /// Препретатор и постпретатор функция
        /// </summary>
        /// <param name="game">Массив строк всего скрипта</param>
        /// <param name="main">Сам скрипт</param>
        public static void Compilation(string[] game, ref string main, string namefunc = null)
        {
            //funct.Clear();
            for (int i = 0; i < game.Length; i++)
            {
                game = main.Split('\n');
                if (game[i].Split(';')[0] == "function")
                {
                    
                    //создание или "взятие" функции
                    Function fn;
                    if(namefunc != null)
                    {
                        fn = funct[namefunc]; //получем функцию из списка по её имени
                    }
                    else 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].TrimEnd('\n', '\r', '\t').EndsWith("}"); o++) ;

                    var rrrhhh = ""; //временная переменная с итоговым кодом скрипта
                    var telo = "";//тело функции
                    for (int p = 0; p < ((i + o)); p++)
                    {
                        rrrhhh += game[p] + "\n";  //заполнение до конца функции                      
                    }

                    //Console.WriteLine(rrrhhh);

                    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);
                    int lenghtgoto = 0;
                    if (!telo.Contains("goto;")){
                        rrrhhh = rrrhhh.Insert(rrrhhh.Length, String.Format("goto;{0}", fn.point) + "\n}");//если "гото" нет, то добавляем                        
                        lenghtgoto = (String.Format("goto;{0}", fn.point) + "\n}").Length; //вычисляем длинну вставки
                    }
                    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);
                    }
                    rrrhhh = rrrhhh.Insert(rrrhhh.Length, main.Substring(rrrhhh.Length - (lenghtgoto))); //Добавляем всё что после функции
                    //Console.WriteLine(rrrhhh);
                    main = rrrhhh; //изменяем основной скрипт                                    
                }

            }
        }

Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы