예제 #1
0
 public SyntaxTreeVisitor(ParserConfiguration <IN, OUT> conf, object parserInstance)
 {
     ParserClass            = ParserClass;
     Configuration          = conf;
     ParserVsisitorInstance = parserInstance;
 }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
 public EBNFSyntaxTreeVisitor(ParserConfiguration <IN, OUT> conf, object parserInstance) : base(conf,
                                                                                                parserInstance)
 {
 }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }