Exemplo n.º 1
0
        /// <summary>
        /// Practically the same as marking with MarkTransient. It is used in those cases when MarkTransient would not work due to technical issues,
        /// or when there are multiple children and only one of them has ast node.
        /// </summary>
        /// <example>
        /// When creating a Member we should not use MarkTransient, because under this Member there can be a list (TermFlags.IsList),
        /// which makes this term to become a list container (TermFlags.IsListContainer), and this causes ReduceParserActionCreate to process this term
        /// with ReduceListContainerParserAction instead of the desired ReduceTransientParserAction, which causes the parseTreeNode of this term
        /// to remain in the parseTree despite it is being transient (TermFlags.IsTransient), and this results bad behavior when building the AST tree,
        /// because this term will not produce an ast node (TermFlags.NoAstNode), and therefore the AST builder will not process its children.
        /// </example>
        internal static void MarkTransientForced(NonTerminal nonTerminal)
        {
            nonTerminal.AstConfig.NodeCreator = (context, parseTreeNode) =>
            {
                try
                {
                    parseTreeNode.AstNode = parseTreeNode.ChildNodes.Single(childNode => childNode.AstNode != null).AstNode;
                }
                catch (InvalidOperationException)
                {
                    // throw exception only if this exception cannot be the consequence of another ast error
                    if (!GrammarHelper.HasError(context))
                    {
                        throw new ArgumentException(string.Format("Only one child with astnode is allowed for a forced transient node: {0}", parseTreeNode.Term.Name), "nonTerminal");
                    }
                }
            };

            nonTerminal.SetFlag(TermFlags.InheritPrecedence);
        }
Exemplo n.º 2
0
        protected IEnumerable <TElementStaticType> GetFlattenedElements <TElementStaticType>(ParseTreeNode parseTreeNode, AstContext context)
        {
            foreach (var parseTreeChild in parseTreeNode.ChildNodes)
            {
                /*
                 * The type of childValue is 'object' because childValue can be other than an element, which causes error,
                 * but we want to give a proper error message (see below) instead of throwing a simple cast exception
                 * */
                object childValue = GrammarHelper.AstNodeToValue(parseTreeChild.AstNode);

                if (domainElementType.IsInstanceOfType(childValue))
                {
                    yield return((TElementStaticType)childValue);
                }
                else if (parseTreeChild.Term.Flags.IsSet(TermFlags.IsList))
                {
                    foreach (var descendantElement in GetFlattenedElements <TElementStaticType>(parseTreeChild, context))
                    {
                        yield return(descendantElement);
                    }
                }
                else if (parseTreeChild.Term.Flags.IsSet(TermFlags.NoAstNode))
                {
                    // simply omit children with no ast (they are probably delimiters)
                }
                else
                {
                    // throw exception only if this situation cannot be the consequence of another ast error
                    if (!GrammarHelper.HasError(context))
                    {
                        string errorMessage = string.Format("Term '{0}' should be type of '{1}' but found '{2}' instead",
                                                            parseTreeChild.Term,
                                                            domainElementType.FullName,
                                                            childValue != null ? childValue.GetType().FullName : "<<NULL>>");

                        throw new InvalidOperationException(errorMessage);
                    }
                }
            }
        }