Транслятор с компиляцией

в 12:29, , рубрики: .net, .net frameowrk, Mono, Visual Studio, visual studio 2010, Компиляторы, Программирование

Здравствуйте. Раньше, когда почти не знал C#, хотел написать свой «мега-крутой» язык программирования. Много раз осматривал разные форумы с мыслями скопировать весь код и быть крутым. Но ничего такого никогда не находил, расстраивался и продолжал трудится над изучением C#. Через полгода я смог написать консольное приложение, которое вписывало свой текст, написанный в консоли, в *.cs файл. Еще полгода спустя пытался «позаимствовать» код с Хабрхабра, но код был на другом для меня языке и я забросил это дело. Позже, месяца так через 1-2, я смог написать транслятор в C#, который компилировал .src (я исковеркал .cs) файл и выдавал, как ни странно, .exe файл.

После такого долгого вступления хочу показать вам код и помочь новичкам. Код, конечно, не весь, но смысл должен быть понятен. Так же предупреждаю, что будет ненавистный «IndexOf», по крайней мере я видел, что его не очень любят. Так же скажу, что я не смотрел, есть ли на данный момент похожая на мою статья, но тогда я не нашел, что нужно, поэтому пишу здесь.

Что же, начнем.

class ProgramsMain
{

    static void Main()
    {

        System.Console.Title = "HabrHabr";

        while (true) Start.ReadConsoleCommands();

    }

}

Это наша точка запуска программы, static — забрасывает её сразу в память, void — метод. Задаем название нашему окну и запускаем вечный цикл, в котором вызывается метод ReadConsoleCommands(). Сам метод.

class Start
{
public static void ReadConsoleCommands()
    {

        string[] C = System.Console.ReadLine().Split(' ');

        try
        {
            switch (C[0].ToLower().Trim())
            {

                case "compile":

                    Vars.PathTo = C[1];
                    Vars.PathOut = C[2];

                    Translator.Translate(Vars.PathTo, Vars.PathOut + ".ourlang");

                    break;

                default:

                    break;

            }
        }
        catch (System.Exception ex)
        {

            System.Console.WriteLine(ex.Message);

        }
    }

}

Давайте снова разберем код. string[] C = System.Console.ReadLine().Split(' '); — объявляем переменную, которую будем парсить, в данном случае это — массив. Дальше идет try, он нужен для того, чтобы если мы не дадим нашему парсеру необходимые параметры, наша программа не вылетела. Потом идет конструкция switch-case-default, точно такая же как и if-else if-else, но считается красивее. Проверяем, равен ли наш первый элемент массива «compile», аргументы в switch «C[0].ToLower().Trim()» — делают наш введенный текст равный обычным буквам и удаляет лишние пробелы, таким образом, текст, который введен как: «ПриВет, МиР», будет считаться как: «привет, мир». Если условие истинно, то переменным Vars.PathTo и Vars.PathOut присваивается значение C[1];, C[2];.

Что за переменные Vars.PathTo и Vars.PathOut? Эти переменные у меня хранятся в другом .cs файле под именем Glob. Однако вы можете написать программу в один .cs файл, текст которого будет в конце статьи. Дальше мы вызываем Translator.Translate(string path, string pathTo);, этот метод и есть транслятор, мы задаем ему параметры входного и выходного файла.

    public class Translator
    {

            public static void Translate(string path, string pathTo) 
            {

                System.IO.StreamWriter OutputFile = System.IO.StreamWriter(pathTo);

                OutputFile.WriteLine(@"class Program { static void Main() { ");

                foreach (string line in System.IO.File.ReadLines(path)) 
                {

                    string Done = line.Trim().ToLower();

                    if (Done.IndexOf("print") != -1) 
                    {

                        string[] args = line.Split(':');

                        OutputFile.Write("Console.WriteLine(");

                        for (int i = 0; i < args.Length; i++) 
                        {

                            OutputFile.Write(args[i]);

                        }

                        OutputFile.Write(");");

                    }

                }

                OutputFile.Close();

                CP.Start();

            }

    }

Внимание

Это только пример, вы можете таким способом сделать все, что угодно, просто скажите компилятору проверять слова, а при нахождении вписывать в выходной файл какой-то код.

Давайте снова разбирать. System.IO.StreamWriter OutputFile = System.IO.StreamWriter(pathTo); — записывает в файл, в аргументах путь к файлу. foreach (string line in System.IO.File.ReadLines(path)) — цикл, который можно заменить for, но foreach удобнее, он объявляет переменную, которой присвоено значение читаемой линии в File.ReadLines(path). Done = line.Trim().ToLower(); — чтобы каждый раз не писать: «line.Trim().ToLower()...». if (Done.IndexOf(«print») != -1) — если найдено слово «print», выполняем код. OutputFile.WriteLine(«Console.WriteLine(»); — вписываем в выходной файл. for (int i = 0; i < args.Length; i++) {OutputFile.WriteLine(args[i]);} — в исходном файле нашего «языка» может быть на одна ':', поэтому на этот случай пишем цикл. OutputFile.Write(");"); — закрываем скобки. OutputFile.Close(); — заканчиваем метод, если мы этого не сделаем, то при следующих компиляциях программа будет вылетать и ее придется перезагружать. CP.Start(); — вызываем наш метод «компиляции». Сам метод.

public class CP
{
    public static void Start() 
    {
        try
        {
            StreamWriter SW = new StreamWriter("CP.bat", false);

            SW.Write(@"@echo off
C:WINDOWSMicrosoft.NETFrameworkv3.5csc.exe /out:" + Vars.PathOut + "App.exe "
                                                       + Vars.PathOut + "ToCompile.src"
                                                       + "n");
            SW.Close();

            Process.Start("CP.bat");
        }
        catch (Exception ex) 
        {
            Console.Write("n " + ex.Message + " n");
        }
    }
}

SW.Write(@" @ echo off C:WINDOWSMicrosoft.NETFrameworkv3.5csc.exe /out:" + Vars.PathOut + «App.exe » + Vars.PathOut + «ToCompile.+ „n“); — вписывает в .BAT файл код вызова .NET компилятора(есть в каждой Windows). Process.Start(»CP.bat"); — запускает наш .BAT

Внимание!

Чтобы System.Diagnostics.Process.Start работало, нужно подключить в ссылках System

Готово! Исходный код в один файл.

class ProgramsMain
{

    static void Main()
    {

        System.Console.Title = "HabrHabr";

        while (true) Start.ReadConsoleCommands();

    }

}
class Start
{
public static void ReadConsoleCommands()
    {

        string[] C = System.Console.ReadLine().Split(' ');

        try
        {
            switch (C[0].ToLower().Trim())
            {

                case "compile":

                    Vars.PathTo = C[1];
                    Vars.PathOut = C[2];

                    Translator.Translate(Vars.PathTo, Vars.PathOut + ".ourlang");

                    break;

                default:

                    break;

            }
        }
        catch (System.Exception ex)
        {

            System.Console.WriteLine(ex.Message);

        }
    }

}
public class Translator
    {

            public static void Translate(string path, string pathTo) 
            {

                System.IO.StreamWriter OutputFile = System.IO.StreamWriter(pathTo);

                OutputFile.WriteLine(@"class Program { static void Main() { ");

                foreach (string line in System.IO.File.ReadLines(path)) 
                {

                    string Done = line.Trim().ToLower();

                    if (Done.IndexOf("print") != -1) 
                    {

                        string[] args = line.Split(':');

                        OutputFile.Write("Console.WriteLine(");

                        for (int i = 0; i < args.Length; i++) 
                        {

                            OutputFile.Write(args[i]);

                        }

                        OutputFile.Write(");");

                    }

                }

                OutputFile.Close();

                CP.Start();

            }

    }
public class CP
{
    public static void Start() 
    {
        try
        {
            StreamWriter SW = new StreamWriter("CP.bat", false);

            SW.Write(@"@echo off
C:WINDOWSMicrosoft.NETFrameworkv3.5csc.exe /out:" + Vars.PathOut + "App.exe "
                                                       + Vars.PathOut + "ToCompile.src"
                                                       + "n");
            SW.Close();

            Process.Start("CP.bat");
        }
        catch (Exception ex) 
        {
            Console.Write("n " + ex.Message + " n");
        }
    }
}

Автор: unseyablewiq

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js