10 #include "utf8_string.h"
11 #include "literal_data.h"
15 using namespace utakata;
16 using namespace utakata::literal;
17 using namespace utakata::utf8_string;
18 using namespace utakata::syntax;
20 // 原則としてそれぞれ単純に呼びだされるのみ。
24 TreeNode(node_pair p) : datum(p) {}
26 smart_ptr<TreeNode> parent;
27 smart_ptr<TreeNode> car;
28 smart_ptr<TreeNode> cdr;
29 std::vector<smart_ptr<TreeNode> > child;
31 Tree::node_pair datum;
35 //syntax::Tree::TreeNode::TreeNode(std::pair<DatumID, smart_ptr<literal::Literal> > p) : datum(p) {}
37 ////////////////////////////
38 // syntax::Tree::iterator //
39 ////////////////////////////
41 syntax::Tree::iterator::iterator() : node_(), current_()
45 syntax::Tree::iterator::iterator(smart_ptr<TreeNode>& node) : node_(node)
47 current_ = node->child.begin();
50 syntax::Tree::iterator::iterator(const Tree::iterator& i)
55 syntax::Tree::iterator& syntax::Tree::iterator::operator=(const Tree::iterator& rh)
61 void syntax::Tree::iterator::swap(const Tree::iterator& t)
64 current_ = t.current_;
67 Tree::iterator& Tree::iterator::operator++()
69 // 内部イテレータを巡回し、深さ優先探索と同様の流れになるようにす
72 // 1. current_が指すnodeに子がいる場合、current_の子のbeginを指定
74 // 2. current_が差すnodeに子がおらず、current_が現在のノードの子の
75 // 末尾ではない場合、current_++する。
76 // 3. current_がnode_->childの末尾である場合、parentに戻る。
77 // parentに戻った際、parent->parentが空では無い場合に限り、
78 // parent->parentの子から、node_->parentではないノードに戻る。
80 if (!current_->child.empty())
83 current_ = node_->child.begin();
85 else if (node_->child.end() != current_)
92 node_ = node_->parent;
94 while (!node_->parent.isNull())
96 std::vector<smart_ptr<Tree::TreeNode> >::iterator tmp = node_->parent->child.find(node_);
97 if (tmp != node_->parent->child.end())
102 node_ = node_->parent;
109 std::pair<DatumID, smart_ptr<literal::Literal> >& Tree::iterator::operator*()
111 // 現在のcurrent_が指すnodeのリテラルを返す。
112 return *(*current_)->datum;
115 std::pair<DatumID, smart_ptr<literal::Literal> >* Tree::iterator::operator->()
117 // 現在のcurrent_が指すnodeのリテラルを返す。
118 return &*((*current_)->datum);
126 Tree::Tree() : MAX_CONS_SIZE(2), node_()
129 node_.add(new TreeNode(node_pair(yntax::DatumID(syntax::DatumID::nil),
130 smart_ptr<literal::Literal>())));
133 Tree::iterator Tree::begin()
136 return iterator(node_);
139 Tree::iterator Tree::end()
143 smart_ptr<TreeNode> n(new TreeNode(node_pair(
144 syntax::DatumID(syntax::DatumID::nil),
145 smart_ptr<literal::Literal>())));
149 Tree::iterator Tree::appendChild(iterator it, Tree::node_pair p)
151 // itが指すnodeのcar,もしくはcdrに追加する。
152 // すでにcdrも追加されている場合には、例外を発生させる。
154 if (it.node_->child.size() == Tree::MAX_CONS_SIZE)
157 throw std::exception();
161 smart_ptr<TreeNode> n(new TreeNode(p));
164 n->parent = it.node_;
165 it.node_->child.push_back(n);
169 Tree::iterator Tree::appendChild(iterator it1, iterator it2)
171 // it1にit2のnode_を追加する。
173 if (it.node_->child.size() == Tree::MAX_CONS_SIZE)
176 throw std::exception();
180 it2.node_->parent = it.node_;
181 it.node_->child.push_back(it2.node_);
185 Tree::iterator Tree::insert(Tree::iterator it, node_pair pair)
187 // itが指す位置に、pairを設定する。
189 // 1. pairを持つTreeNodeを生成
190 // 2. 生成したTreeNodeを、itのcurrent_が指す位置にinsert
191 // 3. insert結果、MAX_CONS_SIZEを超えていたら、再び新規に
192 // TreeNodeを生成し、末尾の二つを配下に設定して、insertする。
194 // pairを持つnodeを作成し、親をitが現在指しているデータの親と同一にする。
195 smart_ptr<TreeNode> n(new TreeNode(pair));
196 n->parent = it.current_->parent;
198 // 現在位置に挿入する。この時、itのイテレータを更新する。
199 it.current_ = it.node_->child.insert(it.current_, n);
201 if (it.node_->child.size() > Tree::MAX_CONS_SIZE)
203 // 最大サイズを超えていた場合には、後ろの二つを新しいTreeNode
205 smart_ptr<TreeNode> n2(new TreeNode(makeListDatum()));
206 n2->child.insert(n2->child.begin(), ++(it.node_->child.begin()),
207 it.node_->child.end());
208 it.node_->child.erase(++(it.node_->child.begin()), it.node_->child.end());
209 it.node_->child.push_back(n2);
210 it.current_ = it.node_->child.begin();
216 Tree::iterator Tree::insert(Tree::iterator it1, iterator it2)
218 // it1が指す位置に、it2が指すオブジェクトを挿入する。
219 // 挿入する位置は、末尾になることはありえない。末尾に挿入する必要
220 // がある場合には、appendChildが利用されること。
222 // 1. it2が指すTreeNodeをit1のcurrentの位置に挿入する。
223 // 2. insert時点でMAX_CONS_SIZEだった場合、現在の末尾を
224 // it2が指すTreeNodeから辿った末尾=子が無いか、子が一つしかないTreeNode
226 // it2の末尾を取得するためには、it2をルートとする木を一度作成して、