Parser / Lexer / Язык программирования Вопрос - PullRequest
5 голосов
/ 06 марта 2011

Хорошо, так что я не очень хорошо разбираюсь в терминах и прочем, НО вот что я создал до сих пор:

1: приложение, которое читает символ за символом содержимое файла исходного кода. И,

2: приложение, которое определяет, является ли символ / строка 'x' идентификатором, или целым числом, или чем-то еще.

и 3: еще одно приложение, которое собирает все вместе и создает другой файл, который в основном содержит инструкции для отправки в мое четвертое приложение, в основном по направлениям:

Назначить значение Integer oldValue для Integer newValue.

Итак, мое четвертое приложение получает эту инструкцию и «компилирует» ее (ну, в данном случае я бы сказал, что я просто хочу ее интерпретировать), которая затем создаст приложение, которое выполняет:

int newValue = oldValue;

Итак, поскольку у меня уже есть парсер и т. Д., Как я могу перевести мои инструкции в инструкции, которые приводят к фактическим действиям, и сгенерировать EXE-файл, поэтому, когда я дважды щелкаю по файлу, он выполняет вышеуказанное действие?

Надеюсь, вас это не смущает.

Итак, в основном, я думаю, что я спрашиваю: «Как я могу программно создать« Событие »из строки, сохранить его в файл и сгенерировать exe?»

Ответы [ 4 ]

2 голосов
/ 06 марта 2011

Существует несколько вариантов создания EXE-файла из списка инструкций.Все опции включают в себя преобразование ваших инструкций в элементы другого языка.

  • Вы можете сгенерировать исходный код C # и скомпилировать результат с помощью компилятора C #: System.CodeDom

  • Вы можете сгенерировать инструкции IL и сохранить полученную сборку на диск: System.Reflection.Emit

  • Вы можете построить Деревья выражений вместо генерации инструкций IL: System.Linq.Expressions

1 голос
/ 06 марта 2011

Это настоящий рабочий пример для простого создания исполняемого файла, используя то, что я указал в комментарии:

using System;
using System.Reflection;
using System.Reflection.Emit;

namespace AssemblyGenerator
{
    partial class AssemblyGenerator
    {
        static void Main(string[] args)
        {
            string assemblyName = "Sample";
            string exeName = "Sample.exe";

            AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.Save);
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(exeName);
            TypeBuilder typeBuilder = moduleBuilder.DefineType(assemblyName, TypeAttributes.Public | TypeAttributes.Class);
            MethodBuilder methodBuilder = typeBuilder.DefineMethod("Main", MethodAttributes.Static | MethodAttributes.Public, typeof(void), null);

            assemblyBuilder.SetEntryPoint(methodBuilder, PEFileKinds.ConsoleApplication);

            ILGenerator ilGenerator = methodBuilder.GetILGenerator();
            // BEGIN method IL.
            ilGenerator.EmitWriteLine("This shows on console output.");
            ilGenerator.Emit(OpCodes.Ret);
            // END method IL.

            typeBuilder.CreateType();
            assemblyBuilder.Save(exeName);
        }
    }
}

Вы можете отправить свой код внутри блока метода, как указано в комментариях.

Кроме того, вы можете использовать выражение , используя метод LambdaExpression.CompileToMethod вместо ILGenerator.

0 голосов
/ 06 марта 2011

Самый простой способ - это, вероятно, заставить вашу программу генерировать исходный код для некоторого языка (например, C) и выводить его в файл, который вы скомпилируете отдельно. Это избавляет вас от необходимости создавать код, который может быть довольно сложным.

В зависимости от сложности вашей задачи, может быть проще использовать такие инструменты, как Yacc (и Lex). Они позволяют вам указать, как идентифицировать части ввода, которые вас интересуют, и грамматику для языка, а также то, что должно выводиться при идентификации конструкций. Вам не нужно указывать грамматику для всего C #, а только те части, которые вам нужны для вашей задачи.

0 голосов
/ 06 марта 2011

Когда дело доходит до фазы компиляции, лучше всего использовать API-интерфейсы Reflection Emit для генерации .NET IL и генерации EXE и DLL.

Вместо того, чтобы разбираться здесь во всем, я бы указал на следующую статью MSDN Создание языкового компилятора для .NET Framework , который включает в себя пример кода, который должен помочь вам в вашем пути.

Другой вариант включает генерацию кода на C # и использование CodeDOM для компиляции кода в EXE, это будет использовать компилятор C # в качестве промежуточного шага между генерацией кода и окончательной генерацией двоичного кода.

...