Advertisement
Guest User

Untitled

a guest
Jul 26th, 2017
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.23 KB | None | 0 0
  1. #include <memory> // std::unique_ptr
  2. #include <vector>
  3. using std::vector;
  4.  
  5. // abstract visitor
  6. struct visitor {
  7. virtual ~visitor(void) {};
  8. virtual void visit(struct realConstantNode &) = 0;
  9. virtual void visit(struct sinNode &) = 0;
  10. };
  11.  
  12. // node hierarchy
  13. struct node {
  14. node() {};
  15. virtual ~node(void) {};
  16. virtual void accept(visitor &) = 0;
  17. };
  18. struct terminalNode : public virtual node {
  19. };
  20. struct nonterminalNode : public virtual node {
  21. virtual void add_child(node* child) = 0;
  22. };
  23. struct unaryNode : public virtual nonterminalNode {
  24. std::unique_ptr<node> child;
  25. void add_child(node * child) {
  26. this->child = std::unique_ptr<node>(child);
  27. };
  28. };
  29.  
  30. // sample terminal node
  31. struct realConstantNode : public terminalNode {
  32. realConstantNode(double value) : value(value) {};
  33. double value;
  34. void accept(visitor & vis) {
  35. vis.visit(*this);
  36. };
  37. };
  38.  
  39. // sample nonterminal node
  40. struct sinNode : public unaryNode {
  41. void accept(visitor & vis) {
  42. vis.visit(*this);
  43. };
  44. };
  45.  
  46. // copy visitor
  47. template<typename copyNodeType>
  48. struct copyCreator : public visitor {
  49. copyCreator() {}
  50. copyCreator(node * firstVisit) {
  51. firstVisit->accept(*this);
  52. }
  53. ~copyCreator() {
  54. copy.reset();
  55. for(auto ptr : openList) {
  56. delete ptr;
  57. }
  58. }
  59.  
  60. std::unique_ptr<copyNodeType> copy = 0;
  61. vector<nonterminalNode *> openList;
  62. bool error = true;
  63.  
  64. // push to tree
  65. template<typename nodeType> // templated bc we want a specific handle, not
  66. bool push(nodeType * ptr) { // a generic node * that we need to cast!
  67. if (copy) {
  68. openList.back()->add_child(ptr); // if root is set, append to tree
  69. }
  70. else {
  71. //setCopy<nodeType>(ptr);
  72. auto temp = dynamic_cast<copyNodeType *>(ptr);
  73. if(temp) {
  74. copy = std::unique_ptr<copyNodeType>(temp);
  75. error = false;
  76. }
  77. else {
  78. /*
  79. Is there a nicer way to dispose of the newly created node `ptr`
  80. or `next` other than checking the return value and wrapping the
  81. entire visit method of all nodes in an if statement?
  82. */
  83. return false;
  84. }
  85. }
  86. return true;
  87. }
  88.  
  89. void visit(struct realConstantNode & nod) {
  90. auto next = new realConstantNode(nod.value);
  91. if(!push(next)) {
  92. delete next;
  93. }
  94. }
  95.  
  96. void visit(struct sinNode & nod) {
  97. auto next = new sinNode;
  98. if(push(next)) {
  99. openList.push_back(next);
  100. nod.child->accept(*this);
  101. openList.pop_back();
  102. }
  103. else {
  104. delete next;
  105. }
  106. };
  107. };
  108.  
  109. int main(int argc, const char * argv[]) {
  110.  
  111. sinNode s;
  112. auto pi = new realConstantNode(3.141);
  113. s.add_child(pi); // s.child now owns pi
  114.  
  115. // These three versions of calling the copyCreator are possible!
  116. copyCreator<sinNode> cpy0;
  117. s.accept(cpy0);
  118.  
  119. copyCreator<sinNode> cpy1;
  120. cpy1.visit(s);
  121.  
  122. copyCreator<sinNode> cpy2(&s);
  123.  
  124. // If we visit pi directly, we cannot create a copy of a sinNode!
  125. copyCreator<sinNode> cpy3(pi);
  126. return 0;
  127. };
  128.  
  129. // copy visitor
  130. template<typename copyNodeType>
  131. struct copyCreator : public visitor {
  132. copyCreator() {}
  133. copyCreator(node * firstVisit) {
  134. firstVisit->accept(*this);
  135. }
  136. ~copyCreator() {}
  137.  
  138. std::unique_ptr<copyNodeType> copy = nullptr;
  139. vector<nonterminalNode *> openList;
  140. bool error = true;
  141.  
  142. bool has_root()
  143. {
  144. return copy != nullptr;
  145. }
  146.  
  147. template<typename node_type>
  148. bool check_is_root(node_type *ptr)
  149. {
  150. if (has_root()) return false; // already found root
  151.  
  152. return std::is_base_of<copyNodeType, node_type>::value;
  153. }
  154.  
  155. template<typename node_type>
  156. void set_root(std::unique_ptr<node_type> ptr)
  157. {
  158. copy = std::unique_ptr<copyNodeType>(ptr.release());
  159. error = false;
  160. }
  161.  
  162. template<typename node_type>
  163. void push_terminal(std::unique_ptr<node_type> ptr)
  164. {
  165. if (has_root() && openList.back() != nullptr)
  166. {
  167. openList.back()->add_child(ptr.release());
  168. }
  169. else if(check_is_root(ptr.get())) {
  170. set_root(std::move(ptr));
  171. }
  172. }
  173.  
  174. template<typename node_type>
  175. bool push_nonterminal(std::unique_ptr<node_type> ptr)
  176. {
  177. if (has_root() && openList.back() != nullptr) {
  178. auto raw_ptr = ptr.release();
  179.  
  180. openList.back()->add_child(raw_ptr);
  181. openList.push_back(raw_ptr);
  182.  
  183. return true;
  184. }
  185. else if (check_is_root(ptr.get()))
  186. {
  187. set_root(std::move(ptr));
  188.  
  189. openList.push_back(copy.get());
  190.  
  191. return true;
  192. }
  193.  
  194. return false;
  195. }
  196.  
  197. void pop_nonterminal()
  198. {
  199. openList.pop_back();
  200. }
  201.  
  202. void visit(realConstantNode& nod) override {
  203. auto next = std::make_unique<realConstantNode>(nod.value);
  204. push_terminal(std::move(next));
  205. }
  206.  
  207. void visit(sinNode& nod) override {
  208. auto next = std::make_unique<sinNode>();
  209.  
  210. if (push_nonterminal(std::move(next))) {
  211. nod.child->accept(*this);
  212. pop_nonterminal();
  213. }
  214. };
  215. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement