protected void SetNodeCreator <TCollectionStaticType, TElementStaticType>(Func <TCollectionStaticType> createCollection, Action <TCollectionStaticType, TElementStaticType> addElementToCollection) { this.AstConfig.NodeCreator = (context, parseTreeNode) => { Lazy <TCollectionStaticType> collection = new Lazy <TCollectionStaticType>(() => createCollection()); bool collectionHasElements = false; foreach (var element in GetFlattenedElements <TElementStaticType>(parseTreeNode, context)) { collectionHasElements = true; addElementToCollection(collection.Value, element); } TCollectionStaticType astValue = !collectionHasElements && this.EmptyCollectionHandling == EmptyCollectionHandling.ReturnNull ? default(TCollectionStaticType) : collection.Value; parseTreeNode.AstNode = GrammarHelper.ValueToAstNode(astValue, context, parseTreeNode); }; }
protected BnfiTermConversion(Type domainType, BnfTerm bnfTerm, ValueIntroducer <object> valueIntroducer, ValueConverter <object, object> inverseValueConverterForUnparse, object defaultValue, bool isOptionalValue, string name, bool astForChild) : base(domainType, name) { this.IsContractible = true; this.bnfTerm = bnfTerm; this.isOptionalValue = isOptionalValue; this.defaultValue = defaultValue; if (!astForChild) { bnfTerm.SetFlag(TermFlags.NoAstNode); } this.RuleRawWithMove = isOptionalValue ? GrammarHelper.PreferShiftHere() + bnfTerm | Irony.Parsing.Grammar.CurrentGrammar.Empty : bnfTerm.ToBnfExpression(); this.AstConfig.NodeCreator = (context, parseTreeNode) => { try { parseTreeNode.AstNode = GrammarHelper.ValueToAstNode(valueIntroducer(context, new ParseTreeNodeWithoutAst(parseTreeNode)), 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; // handle in MultiParser } }; this.inverseValueConverterForUnparse = inverseValueConverterForUnparse; }
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; } }; }