public void Accept(IAstNodeReplacement visitor) { visitor.VisitEnter(this); foreach (AstNode node in Children) { node.Accept(visitor); } visitor.VisitLeave(this); }
public override void VisitLeave(CapturingGroup expression) { String name = expression.Name; Boolean reduceBySingleChildNode = expression.DoReplaceBySingleChildNode; IsMatchPredicate local = _matchStack.Pop(); _matchStack.Push( delegate(IInputIterator iterator) { if (expression.DoCreateCustomAstNode && _astNodeFactory == null) { throw new ArgumentNullException("Second constructor overload is required during instantiation. astNodeFactory requires to be set with this parser implementation."); } Int32 savePosition = iterator.Index; _sandbox.Peek().Push(new AstNode()); if (local(iterator)) { // predicates being processed should not append ast if (_disableCapturingGroup.Count > 0) { _sandbox.Peek().Pop(); iterator.Index = savePosition; return(true); } if (savePosition >= iterator.Index) { // Warn terminal does not consume and ast should not be created for it, yet it should return that it was successful match. _sandbox.Peek().Pop(); iterator.Index = savePosition; return(true); } Byte[] matchedBytes = iterator.Text(savePosition, iterator.Index - 1); if (_xmlBackReferenceLookup.ContainsKey(name)) { _xmlBackReferenceLookup[name].Push(matchedBytes); } else { _xmlBackReferenceLookup.Add(name, new Stack <Byte[]>()); _xmlBackReferenceLookup[name].Push(matchedBytes); } AstNode node = _sandbox.Peek().Pop(); node.Token = new TokenMatch(name, savePosition, iterator.Index - 1); if (expression.DoCreateCustomAstNode) { // create a custom astnode IAstNodeReplacement nodevisitor = _astNodeFactory.Create(node); nodevisitor.Token = node.Token; nodevisitor.Parent = node.Parent; nodevisitor.Children = node.Children; foreach (AstNode updateparent in nodevisitor.Children) { updateparent.Parent = nodevisitor; } // since the whole tree has not finished completing this.Parent will be null on this run. // logic inside astnodereplacement is to create properties, business names, that internally check Children collection to mine data. // you still will need a top level visitor to process tree after it completely available. node.Accept(nodevisitor); node = nodevisitor; } if (reduceBySingleChildNode) { if (node.Children.Count == 1) { node = node.Children[0]; } } if (_sandbox.Peek().Count > 0) { node.Parent = _sandbox.Peek().Peek(); _sandbox.Peek().Peek().Children.Add(node); } else { _sandbox.Peek().Push(node); // don't loose the root node // each successful sandbox will have 1 item left in the stack } return(true); } _sandbox.Peek().Pop(); iterator.Index = savePosition; return(false); }); }