コード例 #1
0
        protected virtual ParserConfiguration <IN, OUT> ExtractEbnfParserConfiguration(Type parserClass,
                                                                                       Parser <EbnfTokenGeneric, GrammarNode <IN> > grammarParser)
        {
            var conf         = new ParserConfiguration <IN, OUT>();
            var nonTerminals = new Dictionary <string, NonTerminal <IN> >();
            var methods      = parserClass.GetMethods().ToList();

            methods = methods.Where(m =>
            {
                var attributes = m.GetCustomAttributes().ToList();
                var attr       = attributes.Find(a => a.GetType() == typeof(ProductionAttribute));
                return(attr != null);
            }).ToList();

            methods.ForEach(m =>
            {
                var attributes =
                    (ProductionAttribute[])m.GetCustomAttributes(typeof(ProductionAttribute), true);

                foreach (var attr in attributes)
                {
                    var ruleString  = attr.RuleString;
                    var parseResult = grammarParser.Parse(ruleString);
                    if (!parseResult.IsError)
                    {
                        var rule        = (Rule <IN>)parseResult.Result;
                        rule.RuleString = ruleString;
                        rule.SetVisitor(m);
                        NonTerminal <IN> nonT = null;
                        if (!nonTerminals.ContainsKey(rule.NonTerminalName))
                        {
                            nonT = new NonTerminal <IN>(rule.NonTerminalName, new List <Rule <IN> >());
                        }
                        else
                        {
                            nonT = nonTerminals[rule.NonTerminalName];
                        }
                        nonT.Rules.Add(rule);
                        nonTerminals[rule.NonTerminalName] = nonT;
                    }
                    else
                    {
                        var message = parseResult
                                      .Errors
                                      .Select(e => e.ErrorMessage)
                                      .Aggregate((e1, e2) => e1 + "\n" + e2);
                        message = $"rule error [{ruleString}] : {message}";
                        throw new ParserConfigurationException(message);
                    }
                }
            });

            conf.NonTerminals = nonTerminals;

            return(conf);
        }
コード例 #2
0
        private static NonTerminal <IN> BuildNonTerminal <IN>(bool last, string name, string nextName,
                                                              List <OperationMetaData <IN> > operations, Dictionary <int, List <OperationMetaData <IN> > > operationsByPrecedence)
            where IN : struct
        {
            var nonTerminal = new NonTerminal <IN>(name, new List <Rule <IN> >());

            foreach (var operation in operations)
            {
                if (operation.Affix == Affix.InFix)
                {
                    var rule = new Rule <IN>();
                    rule.Clauses.Add(new NonTerminalClause <IN>(nextName));
                    rule.Clauses.Add(new TerminalClause <IN>(operation.OperatorToken));
                    rule.Clauses.Add(new NonTerminalClause <IN>(name));
                    rule.IsExpressionRule = true;
                    rule.ExpressionAffix  = operation.Affix;
                    rule.SetVisitor(operation);
                    nonTerminal.Rules.Add(rule);
                }
                else if (operation.Affix == Affix.PreFix)
                {
                    var rule = new Rule <IN>();
                    rule.Clauses.Add(new TerminalClause <IN>(operation.OperatorToken));
                    rule.Clauses.Add(new NonTerminalClause <IN>(nextName));
                    rule.IsExpressionRule = true;
                    rule.ExpressionAffix  = operation.Affix;
                    rule.SetVisitor(operation);
                    nonTerminal.Rules.Add(rule);
                }
                else if (operation.Affix == Affix.PostFix)
                {
                    var rule = new Rule <IN>();
                    rule.Clauses.Add(new NonTerminalClause <IN>(nextName));
                    rule.Clauses.Add(new TerminalClause <IN>(operation.OperatorToken));
                    rule.IsExpressionRule = true;
                    rule.ExpressionAffix  = operation.Affix;
                    rule.SetVisitor(operation);
                    nonTerminal.Rules.Add(rule);
                }
            }

            var rule0 = new Rule <IN>();

            rule0.Clauses.Add(new NonTerminalClause <IN>(nextName));
            rule0.IsExpressionRule = true;
            rule0.ExpressionAffix  = Affix.NotOperator;
            rule0.IsByPassRule     = true;
            nonTerminal.Rules.Add(rule0);

            return(nonTerminal);
        }
コード例 #3
0
        private static void GenerateExpressionParser <IN, OUT>(ParserConfiguration <IN, OUT> configuration,
                                                               string operandNonTerminal, Dictionary <int, List <OperationMetaData <IN> > > operationsByPrecedence,
                                                               string parserClassName) where IN : struct
        {
            var precedences = operationsByPrecedence.Keys.ToList();

            precedences.Sort();
            var max = precedences.Max();

            for (var i = 0; i < precedences.Count; i++)
            {
                var precedence     = precedences[i];
                var nextPrecedence = i < precedences.Count - 1 ? precedences[i + 1] : -1;
                var operations     = operationsByPrecedence[precedence];
                var name           = GetNonTerminalNameForPrecedence(precedence, operationsByPrecedence, operandNonTerminal);
                var nextName       =
                    GetNonTerminalNameForPrecedence(nextPrecedence, operationsByPrecedence, operandNonTerminal);

                var nonTerminal = BuildNonTerminal(i == precedences.Count - 1, name, nextName, operations,
                                                   operationsByPrecedence);

                configuration.NonTerminals[nonTerminal.Name] = nonTerminal;
            }

            // entry point non terminal
            var entrypoint = new NonTerminal <IN>($"{parserClassName}_expressions", new List <Rule <IN> >());
            var prec       = precedences[0];
            var lowestname = GetNonTerminalNameForPrecedence(prec, operationsByPrecedence, operandNonTerminal);
            var rule       = new Rule <IN>();

            rule.Clauses.Add(new NonTerminalClause <IN>(lowestname));
            rule.IsByPassRule     = true;
            rule.IsExpressionRule = true;
            rule.ExpressionAffix  = Affix.NotOperator;
            configuration.NonTerminals[entrypoint.Name] = entrypoint;
            entrypoint.Rules.Add(rule);
        }