/* ** Copyright (C) 2017 Dirk-Jan C. Binnema ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public License ** as published by the Free Software Foundation; either version 2.1 ** of the License, or (at your option) any later version. ** ** This library is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free ** Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA ** 02110-1301, USA. */ #ifndef TREE_HH__ #define TREE_HH__ #include #include #include #include #include namespace Mu { // A node in the parse tree struct Node { enum class Type { Empty, // only for empty trees OpAnd, OpOr, OpXor, OpAndNot, OpNot, Value, Range, Invalid }; Node(Type _type, std::unique_ptr&& _data) : type{_type}, data{std::move(_data)} {} Node(Type _type) : type{_type} {} Node(Node&& rhs) = default; Type type; std::unique_ptr data; static const char* type_name(Type t) { switch (t) { case Type::Empty: return ""; break; case Type::OpAnd: return "and"; break; case Type::OpOr: return "or"; break; case Type::OpXor: return "xor"; break; case Type::OpAndNot: return "andnot"; break; case Type::OpNot: return "not"; break; case Type::Value: return "value"; break; case Type::Range: return "range"; break; case Type::Invalid: return ""; break; default: throw Mu::Error(Error::Code::Internal, "unexpected type"); } } static constexpr bool is_binop(Type t) { return t == Type::OpAnd || t == Type::OpAndNot || t == Type::OpOr || t == Type::OpXor; } }; inline std::ostream& operator<<(std::ostream& os, const Node& t) { os << Node::type_name(t.type); if (t.data) os << t.data; return os; } struct Tree { Tree(Node&& _node) : node(std::move(_node)) {} Tree(Tree&& rhs) = default; void add_child(Tree&& child) { children.emplace_back(std::move(child)); } bool empty() const { return node.type == Node::Type::Empty; } Node node; std::vector children; }; inline std::ostream& operator<<(std::ostream& os, const Tree& tree) { os << '(' << tree.node; for (const auto& subtree : tree.children) os << subtree; os << ')'; return os; } } // namespace Mu #endif /* TREE_HH__ */