コード例 #1
0
        private void BuildList(PropertyInfo property, object astNode, CstNonterminalNode cstNode)
        {
            ConsumeExpression[] expressions = astAttributes[cstNode.Nonterminal].Select(o => o.GetExpression()).ToArray();
            Expression          expression  = cstNode.Nonterminal.Expression;

            if (expressions.Length > 0 || (expression is Sequence || expression is ZeroOrMore || expression is OneOrMore))
            {
                IEnumerable <ICstNonterminalNode> itemNodes;
                if (expressions.Length > 0)
                {
                    itemNodes = GetChildrenByAstExpression(cstNode, expressions);
                }
                else
                {
                    Func <Expression, Nonterminal> findNonterminal = null;
                    findNonterminal = current =>
                    {
                        if (current is Nonterminal)
                        {
                            return((Nonterminal)current);
                        }
                        else if (current is Sequence)
                        {
                            return(findNonterminal(((Sequence)current).Expressions.First()));
                        }
                        else if (current is ZeroOrMore)
                        {
                            return(findNonterminal(((ZeroOrMore)current).Operand));
                        }
                        else
                        {
                            return(findNonterminal(((OneOrMore)current).Operand));
                        }
                    };

                    Nonterminal nonterminal = findNonterminal(expression);
                    itemNodes = GetChildrenByNonterminal(cstNode, nonterminal);
                }

                IList list     = (IList)Activator.CreateInstance(property.PropertyType);
                Type  listType = property.PropertyType.GetListElementType();
                foreach (var childNode in itemNodes)
                {
                    object listItemAstNode = Build(listType, childNode);
                    list.Add(listItemAstNode);
                }
                property.SetValue(astNode, list, null);
            }
            else
            {
                IList list     = (IList)Activator.CreateInstance(property.PropertyType);
                Type  listType = property.PropertyType.GetListElementType();

                object listItemAstNode = Build(listType, cstNode);
                list.Add(listItemAstNode);
                property.SetValue(astNode, list, null);
            }
        }
コード例 #2
0
        //        public static PegBuilder<ConsumeChoice> Builder = new PegBuilder<ConsumeChoice>(Grammar);

        public static ConsumeExpression Parse(string s)
        {
            var result = Parser.ParseString(s);

            // Bypass BnfBuilder because that depends on this in order to work
            CstNonterminalNode cst = CstBuilder.Build(result);

            return(BuildChoice(cst));
        }
コード例 #3
0
        private static ConsumeIndexExpression BuildIndexExpression(CstNonterminalNode node)
        {
            ConsumeIndexExpression expression = new ConsumeIndexExpression();

            CstNonterminalNode targetNode = (CstNonterminalNode)node.Children[0];

            expression.Target = BuildExpression(targetNode);

            //            CstNonterminalNode indexNode = (CstNonterminalNode)((Token)((ICstTerminalNode)node.Children[2]).Terminal).StructuredLexeme;
            expression.Index = int.Parse(node.Children[2].Coalesce());

            return(expression);
        }
コード例 #4
0
        /// <summary>
        /// Replaces all occurances of the pattern within input according to the definition provided
        /// by replacements.
        /// </summary>
        public static string Replace(this Expression expression, string input, params Replacement[] replacements)
        {
            // We want the expression to act like a nonterminal so that its contents get grouped up in the CST
            if (!(expression is Nonterminal))
            {
                expression = expression.Capture();
            }

            // Modify the expression to allow any character (allows matching substrings)
            var exp = +(expression | new AnyCharacter(true));

            var parser = CreateParser(exp);

            var output = parser.ParseString(input);

            if (!output.Any())
            {
                return(input);
            }

            var cst = CstBuilder.Build(output);

            cst = (CstNonterminalNode)cst.Children[0];

            var transformedCst = new CstNonterminalNode(cst.Nonterminal, -1);

            foreach (var child in cst.Children)
            {
                if (child is CstNonterminalNode)
                {
                    var childNonterminal = (CstNonterminalNode)child;
                    var cache            = new CstCache(childNonterminal);
                    var map         = replacements.ToDictionary(x => x.From, x => x.To.Replace(cache));
                    var transformed = childNonterminal.Transform(x => map.ContainsKey(x.Nonterminal) ? map[x.Nonterminal] : null);
                    transformedCst.Children.Add(transformed);
                }
                else
                {
                    transformedCst.Children.Add(child);
                }
            }

            return(transformedCst.Coalesce());
        }
コード例 #5
0
        public Type GetSubclass(ref CstNonterminalNode node, string ruleName)
        {
            foreach (var type in astTypes[ruleName])
            {
                if (type.expression == null || type.expression.Resolve(node).Any())
                {
                    return(type.type);
                }
            }
            if (node.Children.Count == 1 && node.Children[0] is CstNonterminalNode)
            {
                CstNonterminalNode childNode = (CstNonterminalNode)node.Children[0];
                Type result = GetSubclass(ref childNode, childNode.Nonterminal.Name);
                node = childNode;
                return(result);
            }

            throw new InvalidOperationException("No subclass registered for " + ruleName + ".  Consider adding [Ast(typeof(YourAstNode)] to " + ruleName);
        }
コード例 #6
0
        private static ConsumeChoice BuildChoice(CstNonterminalNode node)
        {
            ConsumeChoice      result  = new ConsumeChoice();
            CstNonterminalNode current = node;

            while (current != null)
            {
                if (current.Children.Count == 1)
                {
                    result.Choices.Insert(0, BuildConditional((CstNonterminalNode)current.Children[0]));
                    current = null;
                }
                else
                {
                    result.Choices.Insert(0, BuildConditional((CstNonterminalNode)current.Children[2]));
                    current = (CstNonterminalNode)current.Children[0];
                }
            }
            return(result);
        }
コード例 #7
0
        private static ConsumeReferenceExpression BuildReferenceExpression(CstNonterminalNode node)
        {
            ConsumeReferenceExpression expression = new ConsumeReferenceExpression();

            if (node.Children.Count == 1)
            {
                //                CstNonterminalNode nonterminal = (CstNonterminalNode)((Token)((ICstTerminalNode)node.Children[0]).Terminal).StructuredLexeme;
                expression.NonTerminal = node.Children[0].Coalesce();
            }
            else
            {
                CstNonterminalNode targetNode = (CstNonterminalNode)node.Children[0];
                ConsumeExpression  target     = BuildExpression(targetNode);
                expression.Target = target;

                //                CstNonterminalNode nonterminal = (CstNonterminalNode)((Token)((ICstTerminalNode)node.Children[2]).Terminal).StructuredLexeme;
                expression.NonTerminal = node.Children[2].Coalesce();//nonterminal.Coalesce();
            }
            return(expression);
        }
コード例 #8
0
        private static ConsumeExpression BuildExpression(CstNonterminalNode node)
        {
            CstNonterminalNode expressionType = (CstNonterminalNode)node.Children[0];

            if (expressionType.Nonterminal.Name == "Expression")
            {
                expressionType = (CstNonterminalNode)expressionType.Children[0];
            }
            switch (expressionType.Nonterminal.Name)
            {
            case "ReferenceExpression":
                return(BuildReferenceExpression(expressionType));

            case "IndexExpression":
                return(BuildIndexExpression(expressionType));

            default:
                throw new InvalidOperationException();
            }
        }
コード例 #9
0
        private static ConsumeConditional BuildConditional(CstNonterminalNode node)
        {
            CstNonterminalNode predicate;
            CstNonterminalNode expression;

            if (node.Children.Count == 1)
            {
                predicate  = null;
                expression = (CstNonterminalNode)node.Children[0];
            }
            else
            {
                predicate  = (CstNonterminalNode)node.Children[0];
                expression = (CstNonterminalNode)node.Children[2];
            }
            ConsumeConditional conditional = new ConsumeConditional();

            if (predicate != null)
            {
                conditional.Predicate = BuildExpression(predicate);
            }
            conditional.Expression = BuildExpression(expression);
            return(conditional);
        }
コード例 #10
0
        public T Build(CstNonterminalNode rootNode)
        {
            object astNode = Build(typeof(T), rootNode);

            return((T)astNode);
        }
コード例 #11
0
        public T Build(IEnumerable <OutputRecord> outputStream)
        {
            CstNonterminalNode cstNode = CstBuilder.Build(outputStream);

            return(Build((CstNonterminalNode)cstNode.Children[0]));
        }
コード例 #12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="astNodeType">The type of node we are creating.  A subclass might possibly be selected.</param>
        /// <param name="cstNode">The CST node that represents the structured input for the specified AST node</param>
        /// <returns>The new astNode of the specified astNodeType that consumes the cstNode</returns>
        private object Build(Type astNodeType, ICstNode cstNode)
        {
            int consumeIndex = 0;

            if (astNodeType.IsAbstract || astNodeType.IsInterface)
            {
                string             ruleName           = ((CstNonterminalNode)cstNode).Nonterminal.Name;
                CstNonterminalNode cstNonterminalNode = (CstNonterminalNode)cstNode;
                astNodeType = GetSubclass(ref cstNonterminalNode, ruleName);
                cstNode     = cstNonterminalNode;
            }
            object astNode;

            try
            {
                if (astNodeType == typeof(string))
                {
                    return(cstNode.Coalesce());
                }
                else if (astNodeType == typeof(int))
                {
                    return(int.Parse(cstNode.Coalesce()));
                }
                else if (astNodeType == typeof(byte))
                {
                    return(byte.Parse(cstNode.Coalesce()));
                }
                else if (astNodeType == typeof(short))
                {
                    return(short.Parse(cstNode.Coalesce()));
                }
                else if (astNodeType == typeof(long))
                {
                    return(long.Parse(cstNode.Coalesce()));
                }
                else if (astNodeType == typeof(float))
                {
                    return(float.Parse(cstNode.Coalesce()));
                }
                else if (astNodeType == typeof(double))
                {
                    return(double.Parse(cstNode.Coalesce()));
                }
                else if (astNodeType == typeof(decimal))
                {
                    return(decimal.Parse(cstNode.Coalesce()));
                }
                else if (astNodeType == typeof(bool))
                {
                    return(bool.Parse(cstNode.Coalesce()));
                }
                else
                {
                    astNode = CreateAstNode(astNodeType);
                }
            }
            catch (Exception e)
            {
                throw new InvalidOperationException("Error instantiating " + astNodeType.FullName, e);
            }
            foreach (PropertyInfo property in astNode.GetType().GetAllPropertiesInAncestry())
            {
                ConsumeAttribute[] consumeAttributes = property.GetAttributes <ConsumeAttribute>();
                foreach (ConsumeAttribute consumeAttribute in consumeAttributes)
                {
                    if (consumeIndex > 0 && consumeIndex != consumeAttribute.Production)
                    {
                        continue;
                    }

                    CstNonterminalNode productionNode = cstNode as CstNonterminalNode;

                    // 1) Handle the simple case where the NonTerminal exactly matches the NonTerminal property of our consume attribute
                    // 2) Handle the empty [Consume] case, which means it goes into this block no matter what.
                    // Get the expression (parsed from the NonTerminal property)
                    ConsumeExpression expression = consumeAttribute.GetExpression();

                    // The goal of the expression is to bring us to a new CST node (a descendent of the current one)
                    ICstNode newCstNode;
                    try
                    {
                        newCstNode = expression != null?expression.Resolve(productionNode).FirstOrDefault() : productionNode;
                    }
                    catch (Exception e)
                    {
                        throw new InvalidOperationException("Error resolving expression '" + consumeAttribute.Expression + "' for " + property.GetPath(), e);
                    }

                    // There are a number of reasons why the new cst node might be null.  It is perfectly
                    // legal to specify nonterminal expressions that only resolve under certain productions.
                    // In other scenarios, it will remain null.
                    if (newCstNode != null)
                    {
                        // If the Value property is set, then we simply assign the property to that value (since newCstNode is not null)
                        if (consumeAttribute.Value != null)
                        {
                            property.SetValue(astNode, consumeAttribute.Value, null);
                        }
                        else if (consumeAttribute.Type != null)
                        {
                            Coalesce(astNode, property, newCstNode, consumeAttribute.Type);
                        }
                        else
                        {
                            MapProperty(property, astNode, newCstNode);
                        }
                        goto nextProperty;
                    }
                }

                var impliedCstNode = ((CstNonterminalNode)cstNode).Children.OfType <ICstNonterminalNode>().SingleOrDefault(o => o.Nonterminal.Name == property.Name);
                if (impliedCstNode != null)
                {
                    MapProperty(property, astNode, impliedCstNode);
                }

                nextProperty :;
            }
            return(astNode);
        }