/// <summary> /// Builds a parser (lexer, syntax parser and syntax tree visitor) according to a parser definition instance /// </summary> /// <typeparam name="IN"></typeparam> /// <param name="parserInstance"> /// a parser definition instance , containing /// [Reduction] methods for grammar rules /// <param name="parserType"> /// a ParserType enum value stating the analyser type (LR, LL ...) for now only LL recurive /// descent parser available /// </param> /// <param name="rootRule">the name of the root non terminal of the grammar</param> /// <returns></returns> public virtual BuildResult <Parser <IN, OUT> > BuildParser(object parserInstance, ParserType parserType, string rootRule, BuildExtension <IN> extensionBuilder = null) { Parser <IN, OUT> parser = null; var result = new BuildResult <Parser <IN, OUT> >(); if (parserType == ParserType.LL_RECURSIVE_DESCENT) { var configuration = ExtractParserConfiguration(parserInstance.GetType()); configuration.StartingRule = rootRule; var syntaxParser = BuildSyntaxParser(configuration, parserType, rootRule); var visitor = new SyntaxTreeVisitor <IN, OUT>(configuration, parserInstance); parser = new Parser <IN, OUT>(syntaxParser, visitor); var lexerResult = BuildLexer(extensionBuilder); parser.Lexer = lexerResult.Result; if (lexerResult.IsError) { result.Errors.AddRange(lexerResult.Errors); return(result); } parser.Instance = parserInstance; parser.Configuration = configuration; result.Result = parser; } else if (parserType == ParserType.EBNF_LL_RECURSIVE_DESCENT) { var builder = new EBNFParserBuilder <IN, OUT>(); result = builder.BuildParser(parserInstance, ParserType.EBNF_LL_RECURSIVE_DESCENT, rootRule, extensionBuilder); } parser = result.Result; if (!result.IsError) { var expressionResult = parser.BuildExpressionParser(result, rootRule); if (expressionResult.IsError) { result.AddErrors(expressionResult.Errors); } result.Result.Configuration = expressionResult.Result; result = CheckParser(result); if (result.IsError) { result.Result = null; } } else { result.Result = null; } return(result); }
/// <summary> /// Builds a parser (lexer, syntax parser and syntax tree visitor) according to a parser definition instance /// </summary> /// <typeparam name="IN"></typeparam> /// <param name="parserInstance"> /// a parser definition instance , containing /// [Reduction] methods for grammar rules /// <param name="parserType"> /// a ParserType enum value stating the analyser type (LR, LL ...) for now only LL recurive /// descent parser available /// </param> /// <param name="rootRule">the name of the root non terminal of the grammar</param> /// <returns></returns> public virtual BuildResult <Parser <IN, OUT> > BuildParser(object parserInstance, ParserType parserType, string rootRule, BuildExtension <IN> extensionBuilder = null) { Parser <IN, OUT> parser = null; var result = new BuildResult <Parser <IN, OUT> >(); if (parserType == ParserType.LL_RECURSIVE_DESCENT) { var configuration = ExtractParserConfiguration(parserInstance.GetType()); var(foundRecursion, recursions) = LeftRecursionChecker <IN, OUT> .CheckLeftRecursion(configuration); if (foundRecursion) { var recs = string.Join("\n", recursions.Select(x => string.Join(" > ", x))); result.AddError(new ParserInitializationError(ErrorLevel.FATAL, $"left recursion detected : {recs}", ErrorCodes.PARSER_LEFT_RECURSIVE)); return(result); } configuration.StartingRule = rootRule; var syntaxParser = BuildSyntaxParser(configuration, parserType, rootRule); var visitor = new SyntaxTreeVisitor <IN, OUT>(configuration, parserInstance); parser = new Parser <IN, OUT>(syntaxParser, visitor); var lexerResult = BuildLexer(extensionBuilder); parser.Lexer = lexerResult.Result; if (lexerResult.IsError) { result.Errors.AddRange(lexerResult.Errors); return(result); } parser.Instance = parserInstance; parser.Configuration = configuration; result.Result = parser; } else if (parserType == ParserType.EBNF_LL_RECURSIVE_DESCENT) { var builder = new EBNFParserBuilder <IN, OUT>(); result = builder.BuildParser(parserInstance, ParserType.EBNF_LL_RECURSIVE_DESCENT, rootRule, extensionBuilder); } parser = result.Result; if (!result.IsError) { var expressionResult = parser.BuildExpressionParser(result, rootRule); if (expressionResult.IsError) { result.AddErrors(expressionResult.Errors); } result.Result.Configuration = expressionResult.Result; result = CheckParser(result); if (result.IsError) { result.Result = null; } } else { result.Result = null; } return(result); }