//------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #pragma once // Minimum amount of memory on the stack required by a visitor call. // Use this value to control when to stop the visitor recursion before a SOE occurs. #define PNODEVISIRORSIZE 256 template struct VisitorPolicyBase { typedef Context Context; protected: inline bool Preorder(ParseNode *pnode, Context context) { return true; } inline void Inorder(ParseNode *pnode, Context context) { } inline void Midorder(ParseNode *pnode, Context context) { } inline void Postorder(ParseNode *pnode, Context context) { } inline void InList(ParseNode *pnode, Context context) { } // This will be useful when you want the reference of your current node. inline void PassReference(ParseNode **ppnode, Context context) { } }; template struct VisitorWalkerPolicy : public VisitorPolicy { public: typedef ParseNode *ResultType; typedef struct WalkerContext { typename VisitorPolicy::Context visitorContext; Visitor *visitor; WalkerContext(typename VisitorPolicy::Context context, Visitor *visitor): visitorContext(context), visitor(visitor) { } } *Context; inline ParseNode *DefaultResult() { return NULL; } inline bool ContinueWalk(ParseNode *result) { return true; } inline ParseNode *WalkNode(ParseNode *pnode, Context context) { Inorder(pnode, context->visitorContext); return pnode; } inline ParseNode *WalkListNode(ParseNode *pnode, Context context) { InList(pnode, context->visitorContext); return NULL; } inline ParseNode *WalkFirstChild(ParseNode *pnode, Context context) { context->visitor->VisitNode(pnode, context); return pnode; } inline ParseNode *WalkSecondChild(ParseNode *pnode, Context context) { context->visitor->VisitNode(pnode, context); return pnode; } inline ParseNode *WalkNthChild(ParseNode *pparentnode, ParseNode *pnode, Context context) { Midorder(pparentnode, context->visitorContext); context->visitor->VisitNode(pnode, context); return pnode; } inline void WalkReference(ParseNode **ppnode, Context context) { context->visitor->PassReferenceNode(ppnode, context); } }; template class ParseNodeVisitor : public ParseNodeWalker, VisitorPolicy> > { typedef VisitorWalkerPolicy, VisitorPolicy> WalkerPolicy; typedef typename WalkerPolicy::WalkerContext WalkerContext; public: typedef typename VisitorPolicy::Context VisitorContext; void Visit(ParseNode *pnode, VisitorContext context = VisitorContext()) { WalkerContext walkerContext(context, this); VisitNode(pnode, &walkerContext); } void VisitNode(ParseNode *pnode, Context context) { if (!ThreadContext::IsCurrentStackAvailable(PNODEVISIRORSIZE)) return; if (!pnode) return; if (!Preorder(pnode, context->visitorContext)) return; Walk(pnode, context); Postorder(pnode, context->visitorContext); } void PassReferenceNode(ParseNode **ppnode, Context context) { PassReference(ppnode, context->visitorContext); } };