예제 #1
0
        public static BaseParser BuildParser(GrammarType type, string text, List <Message> messages)
        {
            var builtGrammar = BuildGrammar(type, text, messages);

            if (messages.Count(m => m.Type == MessageType.Error) != 0)
            {
                return(null);
            }

            builtGrammar.RebuildUserificationCache();

            BaseTable table = null;

            switch (type)
            {
            case GrammarType.LL:
                table = new TableLL1(builtGrammar);
                break;

            case GrammarType.LR:
                table = new TableLR1(builtGrammar);
                break;
            }

            messages.AddRange(table.CheckValidity());

            table.ExportToCsv(TempName("current_table.csv"));

            var lexerType = BuildLexer(builtGrammar, "CurrentLexer", messages);

            if (messages.Count(m => m.Type == MessageType.Error) != 0)
            {
                return(null);
            }

            /// Создаём парсер
            BaseParser parser = null;

            switch (type)
            {
            case GrammarType.LL:
                parser = new Parsing.LL.Parser(builtGrammar,
                                               new AntlrLexerAdapter(
                                                   (Antlr4.Runtime.ICharStream stream) => (Antlr4.Runtime.Lexer)Activator.CreateInstance(lexerType, stream)
                                                   )
                                               );
                break;

            case GrammarType.LR:
                parser = new Parsing.LR.Parser(builtGrammar,
                                               new AntlrLexerAdapter(
                                                   (Antlr4.Runtime.ICharStream stream) => (Antlr4.Runtime.Lexer)Activator.CreateInstance(lexerType, stream)
                                                   )
                                               );
                break;
            }

            return(parser);
        }
예제 #2
0
        /// <summary>
        /// Генерация библиотеки с парсером
        /// </summary>
        /// <param name="type">Тип парсера (LL или LR)</param>
        /// <param name="text">Грамматика разбираемого формата файлов</param>
        /// <param name="namespace">Пространство имён для сгенерированного парсера</param>
        /// <param name="path">Путь к каталогу, в котором необходимо сгенерировать библиотеку</param>
        /// <param name="messages">Лог генерации парсера</param>
        /// <returns>Признак успешности выполнения операции</returns>
        public static bool GenerateLibrary(
            GrammarType type,
            string text,
            string @namespace,
            string path,
            string keyPath,
            List <Message> messages
            )
        {
            const string ANTLR_LIBRARY = "Antlr4.Runtime.Standard.dll";

            /// Строим объект грамматики и проверяем, корректно ли прошло построение
            var builtGrammar = BuildGrammar(type, text, messages);

            /// Проверяем, не появились ли ошибки после построения грамматики
            if (messages.Count(m => m.Type == MessageType.Error) != 0)
            {
                return(false);
            }

            builtGrammar.RebuildUserificationCache();

            /// Строим таблицу и проверяем, соответствует ли она указанному типу грамматики
            BaseTable table = null;

            switch (type)
            {
            case GrammarType.LL:
                table = new TableLL1(builtGrammar);
                break;

            case GrammarType.LR:
                table = new TableLR1(builtGrammar);
                break;
            }

            messages.AddRange(table.CheckValidity());

            /// Проверяем, не появились ли ошибки после построения таблицы
            if (messages.Count(m => m.Type == MessageType.Error) != 0)
            {
                return(false);
            }

            var lexerFileName         = TempName($"{@namespace.Replace('.', '_')}_Lexer.cs");
            var parserFileName        = TempName($"{@namespace.Replace('.', '_')}_Parser.cs");
            var grammarFileName       = TempName($"{@namespace.Replace('.', '_')}_Grammar.cs");
            var nodeGeneratorFileName = TempName($"{@namespace.Replace('.', '_')}_NodeGenerator.cs");

            BuildLexer(builtGrammar, Path.GetFileNameWithoutExtension(lexerFileName), messages);

            /// Проверяем, не появились ли ошибки после генерации исходников лексера
            if (messages.Count(m => m.Type == MessageType.Error) != 0)
            {
                return(false);
            }

            File.WriteAllText(grammarFileName, GetGrammarProviderText(builtGrammar, @namespace));
            File.WriteAllText(parserFileName, GetParserProviderText(@namespace));
            File.WriteAllText(nodeGeneratorFileName, GetNodeGeneratorText(builtGrammar, @namespace));

            if (!String.IsNullOrEmpty(keyPath) && !File.Exists(keyPath))
            {
                /// Создаём файл ключа
                Process          process   = new Process();
                ProcessStartInfo startInfo = new ProcessStartInfo()
                {
                    FileName               = "cmd.exe",
                    Arguments              = $"/C chcp 1251 | \"Resources/sn.exe\" -k \"{keyPath}\"",
                    CreateNoWindow         = true,
                    RedirectStandardOutput = true,
                    UseShellExecute        = false
                };
                process.StartInfo = startInfo;
                process.Start();

                process.WaitForExit();
            }

            /// Компилируем библиотеку
            var codeProvider   = new CSharpCodeProvider();;
            var compilerParams = new System.CodeDom.Compiler.CompilerParameters();

            compilerParams.GenerateInMemory = false;
            compilerParams.OutputAssembly   = Path.Combine(path, $"{@namespace}.dll");
            compilerParams.ReferencedAssemblies.Add(ANTLR_LIBRARY);
            compilerParams.ReferencedAssemblies.Add("Land.Core.dll");
            compilerParams.ReferencedAssemblies.Add("System.dll");
            compilerParams.ReferencedAssemblies.Add("System.Core.dll");
            compilerParams.ReferencedAssemblies.Add("mscorlib.dll");

            if (!String.IsNullOrEmpty(keyPath))
            {
                compilerParams.CompilerOptions = $"/keyfile:\"{keyPath}\"";
            }

            var compilationResult = codeProvider.CompileAssemblyFromFile(compilerParams, lexerFileName, grammarFileName, parserFileName, nodeGeneratorFileName);

            if (compilationResult.Errors.Count == 0)
            {
                File.Copy(ANTLR_LIBRARY, Path.Combine(path, ANTLR_LIBRARY), true);

                return(true);
            }
            else
            {
                foreach (System.CodeDom.Compiler.CompilerError error in compilationResult.Errors)
                {
                    if (error.IsWarning)
                    {
                        messages.Add(Message.Warning(
                                         $"Предупреждение: {error.FileName}; ({error.Line}, {error.Column}); {error.ErrorText}",
                                         null,
                                         "C# Compiler"
                                         ));
                    }
                    else
                    {
                        messages.Add(Message.Error(
                                         $"Ошибка: {error.FileName}; ({error.Line}, {error.Column}); {error.ErrorText}",
                                         null,
                                         "C# Compiler"
                                         ));
                    }
                }

                return(messages.All(m => m.Type != MessageType.Error));
            }
        }