M
M
MicrofCorp2019-02-09 23:38:44
C++ / C#
MicrofCorp, 2019-02-09 23:38:44

Where is my mistake in C# code?

I'm developing my mini-interpreter (don't ask why), and so I had a problem: "Prepreter" (as I called it) at the very beginning bypasses the entire code file and searches for functions by the "function" keyword, and then adds them into the list in the form of a structure (the line number of its beginning is indicated). Further, in the main loop, when it comes to the line of the function call, the "postpretator" takes the structure from the list and adds the line number of the initializer of this function to it, then it writes a command like "goto;8" before the function termination character ("}") " and then translates the execution line number to the line number of the start of the function, then after the function is executed, it should translate the execution line number back to the main loop. But the function can be in any part of the script, that's why the "prepretator" was invented. Everything works for me with one function, but it doesn’t want to with two: for some reason it does not substitute the line number translation command into the first function, but it substitutes normally into the second one.

C# source code
/// <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;
                }
            }
}
My code
func;test
//mess - просто текст в консоль выводит
mess;Добро пожаловать в Test.
func;fc
//функции
function;test
isfunction;
mess;Функция, функция
mess;Тело, тело
mess;Кто то батя в C#
}
isfunction;
function;fc
isfunction;
mess;Функция другая
}
Link to GitHub (I haven't posted it there yet)
PS I have an interpreter, not a compiler, and I work with my own scripting language, so there is no need to talk about "compiling C # on the fly" and information on compilers, they have a slightly different principle and essence , than me

Answer the question

In order to leave comments, you need to log in

4 answer(s)
C
CHolfield, 2019-02-10
@CHolfield

You came up with an exceptionally moronic shnyaga, and even tried to embody it. You need to read the theory of creating compilers, they write something interesting from Intel. All in English, really)

R
Roman, 2019-02-10
@yarosroman

Why such difficulties, if you can compile C# on the fly and use it.

S
Stormbringer-s, 2019-02-11
@Stormbringer-s

Take a ready-made scripting language like lua / python.

M
MicrofCorp, 2019-02-12
@MicrofCorp

They answered well on Stack Overflow and did not show off, like here. The problem was in the game and main variables. Here is the solution:

The code
/// <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; //изменяем основной скрипт                                    
                }

            }
        }

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question