示例#1
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);
                    }
                }
            }
        }
示例#2
0
        private static ValueIntroducer <TDOut> ConvertValueConverterToValueIntroducer <TDIn, TDOut>(ValueConverter <TDIn, TDOut> valueConverter, bool isOptionalValue, TDOut defaultValue)
        {
            return((context, parseTreeNode) =>
            {
                Func <IEnumerable <ParseTreeNode>, Func <ParseTreeNode, bool>, ParseTreeNode> chooser;
                if (isOptionalValue)
                {
                    chooser = Enumerable.SingleOrDefault <ParseTreeNode>;
                }
                else
                {
                    chooser = Enumerable.Single <ParseTreeNode>;
                }

                ParseTreeNode parseTreeChild;

                try
                {
                    parseTreeChild = chooser(parseTreeNode.ChildNodes, childNode => childNode.AstNode != null);
                }
                catch (InvalidOperationException)
                {
                    if (isOptionalValue)
                    {
                        throw new ArgumentException("Only zero or one child with ast node is allowed for an optional BnfiTermConversion term: {0}", parseTreeNode.Term.Name);
                    }
                    else
                    {
                        throw new ArgumentException("Exactly one child with ast node is allowed for a non-optional BnfiTermConversion term: {0}", parseTreeNode.Term.Name);
                    }
                }

                return parseTreeChild != null
                    ? valueConverter(GrammarHelper.AstNodeToValue <TDIn>(parseTreeChild.AstNode))
                    : defaultValue;
            });
        }
示例#3
0
 public static BnfiTermConversion <TDOut> Cast <TDOut>(Terminal terminal)
 {
     return(Intro <TDOut>(terminal, (context, parseNode) => GrammarHelper.AstNodeToValue <TDOut>(parseNode.Token.Value), IdentityFunctionForceCast <TDOut, object>));
 }
示例#4
0
        protected BnfiTermRecord(Type domainType, string name)
            : base(domainType, name)
        {
#if !WINDOWS_STORE
#if PCL
            if (domainType.GetConstructor(new Type[0]) == null)
#else
            if (domainType.GetConstructor(bindingAttrInstanceAll, binder: null, types: Type.EmptyTypes, modifiers: null) == null)
#endif
            { throw new ArgumentException("Type has no default constructor (neither public nor nonpublic)", "type"); }
#endif

            this.AstConfig.NodeCreator = (context, parseTreeNode) =>
            {
                try
                {
                    object astValue;
                    try
                    {
#if PCL
                        astValue = ActivatorEx.CreateInstance(domainType, nonPublic: true);
#else
                        astValue = Activator.CreateInstance(domainType, nonPublic: true);
#endif
                    }
                    catch (MissingMemberException)
                    {
                        throw new AstException(string.Format("Type '{0}' does not have a parameterless public or internal constructor", domainType.FullName));
                    }

                    var parseChildBnfTerms = parseTreeNode.ChildNodes.Select(childParseTreeNode => childParseTreeNode.Term).ToList();

                    var parseChildValues = parseTreeNode.ChildNodes
                                           .Select(
                        (parseChildNode, parseChildNodeIndex) => new
                    {
                        ReferredBnfTerm = new ReferredBnfTermEL(parseChildBnfTerms, parseChildNode.Term, parseChildNodeIndex),
                        Value           = GrammarHelper.AstNodeToValue(parseChildNode.AstNode)
                    }
                        )
                                           .Where(parseChildValue => parseChildValue.Value != null)
                                           .ToList();

                    // 1. memberwise copy for BnfiTermCopy items
                    foreach (var parseChildValue in parseChildValues)
                    {
                        if (!IsMemberAtParse(parseChildValue.ReferredBnfTerm) && IsMemberwiseCopyable(astValue, parseChildValue.Value))
                        {
                            MemberwiseCopyExceptNullAndEmptyCollectionValues(astValue, parseChildValue.Value);
                        }
                    }

                    // 2. set member values for member items (it's the second step, so that we can overwrite the copied members if we want)
                    foreach (var parseChildValue in parseChildValues)
                    {
                        if (IsMemberAtParse(parseChildValue.ReferredBnfTerm))
                        {
                            SetValue(GetMemberAtParse(parseChildValue.ReferredBnfTerm).MemberInfo, astValue, parseChildValue.Value);
                        }
                    }

                    parseTreeNode.AstNode = GrammarHelper.ValueToAstNode(astValue, context, parseTreeNode);
                }
                catch (AstException e)
                {
                    context.AddMessage(AstException.ErrorLevel, parseTreeNode.Span.Location, e.Message);
                }
                catch (FatalAstException e)
                {
                    context.AddMessage(FatalAstException.ErrorLevel, parseTreeNode.Span.Location, e.Message);   // although it will be abandoned anyway
                    e.Location = parseTreeNode.Span.Location;
                    throw;
                }
            };
        }