pnodevisit.h 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. // Minimum amout of memory on the stack required by a vistor call.
  7. // Use this value to control when to stop the visitor recursion before a SOE occurs.
  8. #define PNODEVISIRORSIZE 256
  9. template <class Context>
  10. struct VisitorPolicyBase
  11. {
  12. typedef Context Context;
  13. protected:
  14. inline bool Preorder(ParseNode *pnode, Context context) { return true; }
  15. inline void Inorder(ParseNode *pnode, Context context) { }
  16. inline void Midorder(ParseNode *pnode, Context context) { }
  17. inline void Postorder(ParseNode *pnode, Context context) { }
  18. inline void InList(ParseNode *pnode, Context context) { }
  19. // This will be useful when you want the reference of your current node.
  20. inline void PassReference(ParseNode **ppnode, Context context) { }
  21. };
  22. template <class Visitor, class VisitorPolicy>
  23. struct VisitorWalkerPolicy : public VisitorPolicy
  24. {
  25. public:
  26. typedef ParseNode *ResultType;
  27. typedef struct WalkerContext
  28. {
  29. typename VisitorPolicy::Context visitorContext;
  30. Visitor *visitor;
  31. WalkerContext(typename VisitorPolicy::Context context, Visitor *visitor): visitorContext(context), visitor(visitor) { }
  32. } *Context;
  33. inline ParseNode *DefaultResult() { return NULL; }
  34. inline bool ContinueWalk(ParseNode *result) { return true; }
  35. inline ParseNode *WalkNode(ParseNode *pnode, Context context) { Inorder(pnode, context->visitorContext); return pnode; }
  36. inline ParseNode *WalkListNode(ParseNode *pnode, Context context) { InList(pnode, context->visitorContext); return NULL; }
  37. inline ParseNode *WalkFirstChild(ParseNode *pnode, Context context) { context->visitor->VisitNode(pnode, context); return pnode; }
  38. inline ParseNode *WalkSecondChild(ParseNode *pnode, Context context) { context->visitor->VisitNode(pnode, context); return pnode; }
  39. inline ParseNode *WalkNthChild(ParseNode *pparentnode, ParseNode *pnode, Context context) { Midorder(pparentnode, context->visitorContext); context->visitor->VisitNode(pnode, context); return pnode; }
  40. inline void WalkReference(ParseNode **ppnode, Context context) { context->visitor->PassReferenceNode(ppnode, context); }
  41. };
  42. template <class VisitorPolicy>
  43. class ParseNodeVisitor : public ParseNodeWalker<VisitorWalkerPolicy<ParseNodeVisitor<VisitorPolicy>, VisitorPolicy> >
  44. {
  45. typedef VisitorWalkerPolicy<ParseNodeVisitor<VisitorPolicy>, VisitorPolicy> WalkerPolicy;
  46. typedef typename WalkerPolicy::WalkerContext WalkerContext;
  47. public:
  48. typedef typename VisitorPolicy::Context VisitorContext;
  49. void Visit(ParseNode *pnode, VisitorContext context = VisitorContext())
  50. {
  51. WalkerContext walkerContext(context, this);
  52. VisitNode(pnode, &walkerContext);
  53. }
  54. void VisitNode(ParseNode *pnode, Context context)
  55. {
  56. if (!ThreadContext::IsCurrentStackAvailable(PNODEVISIRORSIZE))
  57. return;
  58. if (!pnode) return;
  59. if (!Preorder(pnode, context->visitorContext))
  60. return;
  61. Walk(pnode, context);
  62. Postorder(pnode, context->visitorContext);
  63. }
  64. void PassReferenceNode(ParseNode **ppnode, Context context)
  65. {
  66. PassReference(ppnode, context->visitorContext);
  67. }
  68. };