예제 #1
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);
        }
예제 #2
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);
        }
예제 #3
0
 public TypeRecord(ConsumeExpression expression, Type type)
 {
     this.expression = expression;
     this.type       = type;
 }