1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-29 08:21:15 +03:00

Replace recursion with iteration in ParseTree (and some related walkers)

This commit is contained in:
mariadb-AndreyPiskunov
2023-04-18 17:34:54 +03:00
parent 765dd46b61
commit 6ff121a91c
5 changed files with 404 additions and 111 deletions

View File

@ -195,33 +195,102 @@ void ObjectReader::writeParseTree(const ParseTree* tree, messageqcpp::ByteStream
return;
}
b << (id_t)PARSETREE;
writeParseTree(tree->left(), b);
writeParseTree(tree->right(), b);
if (tree->data() == NULL)
b << (id_t)NULL_CLASS;
else
tree->data()->serialize(b);
DFSStack stack;
stack.emplace_back(const_cast<ParseTree*>(tree));
while (!stack.empty())
{
auto [node, dir] = stack.back();
if (node == NULL)
{
b << (id_t)NULL_CLASS;
stack.pop_back();
continue;
}
if (dir == ParseTree::GoTo::Left)
{
b << (id_t)PARSETREE;
stack.back().direction = ParseTree::GoTo::Right;
stack.emplace_back(node->left());
}
else if (dir == ParseTree::GoTo::Right)
{
stack.back().direction = ParseTree::GoTo::Up;
stack.emplace_back(node->right());
}
else
{
if (node->data() == NULL)
b << (id_t)NULL_CLASS;
else
node->data()->serialize(b);
stack.pop_back();
}
}
}
ParseTree* ObjectReader::createParseTree(messageqcpp::ByteStream& b)
{
CLASSID id = ZERO;
ParseTree* ret;
DFSStack stack;
b >> (id_t&)id;
if (id == NULL_CLASS)
return NULL;
if (id != PARSETREE)
throw UnserializeException("Not a ParseTree");
ret = new ParseTree();
ret->left(createParseTree(b));
ret->right(createParseTree(b));
ret->data(createTreeNode(b));
stack.emplace_back(ret);
while (!stack.empty())
{
auto [node, dir] = stack.back();
if (dir == ParseTree::GoTo::Left)
{
id = ZERO;
ParseTree* cur = NULL;
b >> (id_t&)id;
if (id == NULL_CLASS)
{
stack.back().node->left(cur);
stack.back().direction = ParseTree::GoTo::Right;
continue;
}
if (id != PARSETREE)
throw UnserializeException("Not a ParseTree");
cur = new ParseTree();
stack.back().direction = ParseTree::GoTo::Right;
stack.back().node->left(cur);
stack.emplace_back(node->left());
}
else if (dir == ParseTree::GoTo::Right)
{
id = ZERO;
ParseTree* cur = NULL;
b >> (id_t&)id;
if (id == NULL_CLASS)
{
stack.back().node->right(cur);
stack.back().direction = ParseTree::GoTo::Up;
continue;
}
if (id != PARSETREE)
throw UnserializeException("Not a ParseTree");
cur = new ParseTree();
stack.back().direction = ParseTree::GoTo::Up;
stack.back().node->right(cur);
stack.emplace_back(node->right());
}
else
{
stack.back().node->data(createTreeNode(b));
stack.pop_back();
}
}
return ret;
}