summaryrefslogtreecommitdiff
path: root/lib/parser/tree.hh
blob: 8303eedea70edb001964eba0b0717b100092cc88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
**  Copyright (C) 2017 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
**
**  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.
*/

#include <vector>
#include <string>
#include <iostream>

#include <parser/data.hh>

namespace Mux {

// 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>&& _data):
		type{_type}, data{std::move(_data)} {}
	Node(Type _type): type{_type} {}
	Node(Node&& rhs) = default;

	Type			type;
	std::unique_ptr<Data>   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 "<invalid>"; break;
		default:
			throw std::runtime_error ("bug");
		}
	}

	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<Tree>	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 Mux