public SyntaxTreeVisitor(ParserConfiguration <IN, OUT> conf, object parserInstance) { ParserClass = ParserClass; Configuration = conf; ParserVsisitorInstance = parserInstance; }
public static BuildResult <ParserConfiguration <IN, OUT> > BuildExpressionRules <IN, OUT>( ParserConfiguration <IN, OUT> configuration, Type parserClass, BuildResult <ParserConfiguration <IN, OUT> > result) where IN : struct { var methods = parserClass.GetMethods().ToList(); methods = methods.Where(m => { var attributes = m.GetCustomAttributes().ToList(); var attr = attributes.Find(a => a.GetType() == typeof(OperationAttribute)); return(attr != null); }).ToList(); var operationsByPrecedence = new Dictionary <int, List <OperationMetaData <IN> > >(); methods.ForEach(m => { var attributes = (OperationAttribute[])m.GetCustomAttributes(typeof(OperationAttribute), true); foreach (var attr in attributes) { var operation = new OperationMetaData <IN>(attr.Precedence, attr.Assoc, m, attr.Affix, ConvertIntToEnum <IN>(attr.Token)); var operations = new List <OperationMetaData <IN> >(); if (operationsByPrecedence.ContainsKey(operation.Precedence)) { operations = operationsByPrecedence[operation.Precedence]; } operations.Add(operation); operationsByPrecedence[operation.Precedence] = operations; } }); if (operationsByPrecedence.Count > 0) { methods = parserClass.GetMethods().ToList(); var operandMethod = methods.Find(m => { var attributes = m.GetCustomAttributes().ToList(); var attr = attributes.Find(a => a.GetType() == typeof(OperandAttribute)); return(attr != null); }); string operandNonTerminal = null; if (operandMethod == null) { result.AddError(new ParserInitializationError(ErrorLevel.FATAL, "missing [operand] attribute")); throw new Exception("missing [operand] attribute"); } var production = operandMethod.GetCustomAttributes().ToList() .Find(attr => attr.GetType() == typeof(ProductionAttribute)) as ProductionAttribute; if (production != null) { var ruleItems = production.RuleString.Split(':'); if (ruleItems.Length > 0) { operandNonTerminal = ruleItems[0].Trim(); } } if (operandNonTerminal != null && operationsByPrecedence.Count > 0) { GenerateExpressionParser(configuration, operandNonTerminal, operationsByPrecedence, parserClass.Name); } } result.Result = configuration; return(result); }
private static string GetOperandNonTerminal <IN, OUT>(Type parserClass, ParserConfiguration <IN, OUT> configuration, BuildResult <ParserConfiguration <IN, OUT> > result) where IN : struct { List <MethodInfo> methods; methods = parserClass.GetMethods().ToList(); var operandMethods = methods.Where(m => { var attributes = m.GetCustomAttributes().ToList(); var attr = attributes.Find(a => a.GetType() == typeof(OperandAttribute)); return(attr != null); }).ToList(); if (!operandMethods.Any()) { result.AddError(new ParserInitializationError(ErrorLevel.FATAL, "missing [operand] attribute", ErrorCodes.PARSER_MISSING_OPERAND)); throw new Exception("missing [operand] attribute"); } string operandNonTerminalName = null; if (operandMethods.Count == 1) { var operandMethod = operandMethods.Single(); // TODO call GenerateExpressionParser with <ParserClassNAMe>_operand (or remove operand rule param ? ) operandNonTerminalName = GetNonTerminalNameFromProductionMethod <IN, OUT>(operandMethod); } else { // TODO 1 : generate <ParserClassNAMe>_operand production rule : operand : methods* // rule.isexpression = true // rule.isbypass = true operandNonTerminalName = $"{parserClass.Name}_operand"; var operandNonTerminals = operandMethods.Select(x => GetNonTerminalNameFromProductionMethod <IN, OUT>(x)); var operandNonTerminal = new NonTerminal <IN>(operandNonTerminalName); foreach (var operand in operandNonTerminals) { if (!string.IsNullOrEmpty(operand)) { var rule = new Rule <IN>() { IsByPassRule = true, IsExpressionRule = true, Clauses = new List <IClause <IN> >() { new NonTerminalClause <IN>(operand) } }; operandNonTerminal.Rules.Add(rule); } } configuration.NonTerminals[operandNonTerminalName] = operandNonTerminal; } return(operandNonTerminalName); }
public EBNFSyntaxTreeVisitor(ParserConfiguration <IN, OUT> conf, object parserInstance) : base(conf, parserInstance) { }
public static (bool foundRecursion, List <List <string> > recursions) CheckLeftRecursion(ParserConfiguration <IN, OUT> configuration) { List <List <string> > recursions = new List <List <string> >(); bool foundRecursion = false; foreach (var nonTerminal in configuration.NonTerminals) { var(found, recursion) = CheckLeftRecursion(configuration, nonTerminal.Value, new List <string>() { nonTerminal.Key }); if (found) { foundRecursion = true; recursions.AddRange(recursion); } } return(foundRecursion, recursions); }
public static (bool recursionFound, List <List <string> > recursion) CheckLeftRecursion(ParserConfiguration <IN, OUT> configuration, NonTerminal <IN> nonTerminal, List <string> currentPath) { var foundRecursion = false; List <List <string> > recursions = new List <List <string> >(); var(found, path) = FindRecursion(currentPath); if (found) { return(true, new List <List <string> >() { currentPath }); } var leftClauses = nonTerminal.Rules.SelectMany(x => GetLeftClausesName(x, configuration)).ToList(); foreach (var leftClause in leftClauses) { if (configuration.NonTerminals.ContainsKey(leftClause)) { var newNonTerminal = configuration.NonTerminals[leftClause]; if (newNonTerminal != null) { var nPath = BuildPath(currentPath, leftClause); var(foundRRuleRecursion, recursion) = CheckLeftRecursion(configuration, newNonTerminal, nPath); if (foundRRuleRecursion) { foundRecursion = true; recursions.AddRange(recursion); } } } else { ; } } return(foundRecursion, recursions); }
public override BuildResult <Parser <IN, OUT> > BuildParser(object parserInstance, ParserType parserType, string rootRule, BuildExtension <IN> extensionBuilder = null) { var ruleparser = new RuleParser <IN>(); var builder = new ParserBuilder <EbnfTokenGeneric, GrammarNode <IN> >(); var grammarParser = builder.BuildParser(ruleparser, ParserType.LL_RECURSIVE_DESCENT, "rule").Result; var result = new BuildResult <Parser <IN, OUT> >(); ParserConfiguration <IN, OUT> configuration = null; try { configuration = ExtractEbnfParserConfiguration(parserInstance.GetType(), grammarParser); LeftRecursionChecker <IN, OUT> recursionChecker = new LeftRecursionChecker <IN, OUT>(); 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; } catch (Exception e) { result.AddError(new ParserInitializationError(ErrorLevel.ERROR, e.Message, ErrorCodes.PARSER_UNKNOWN_ERROR)); return(result); } var syntaxParser = BuildSyntaxParser(configuration, parserType, rootRule); SyntaxTreeVisitor <IN, OUT> visitor = null; if (parserType == ParserType.LL_RECURSIVE_DESCENT) { new SyntaxTreeVisitor <IN, OUT>(configuration, parserInstance); } else if (parserType == ParserType.EBNF_LL_RECURSIVE_DESCENT) { visitor = new EBNFSyntaxTreeVisitor <IN, OUT>(configuration, parserInstance); } var parser = new Parser <IN, OUT>(syntaxParser, visitor); parser.Configuration = configuration; var lexerResult = BuildLexer(extensionBuilder); if (lexerResult.IsError) { foreach (var lexerResultError in lexerResult.Errors) { result.AddError(lexerResultError); } return(result); } else { parser.Lexer = lexerResult.Result; } parser.Instance = parserInstance; result.Result = parser; return(result); }