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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
/*
* MRustC - Rust Compiler
* - By John Hodge (Mutabah/thePowersGang)
*
* ast/attrs.hpp
* - AST Attributes (#[foo] and #![foo])
*/
#ifndef _AST_ATTRS_HPP_
#define _AST_ATTRS_HPP_
namespace AST {
//
class Attribute;
::std::ostream& operator<<(::std::ostream& os, const Attribute& x);
/// A list of attributes on an item (searchable by the attribute name)
class AttributeList
{
public:
::std::vector<Attribute> m_items;
AttributeList() {}
AttributeList(::std::vector<Attribute> items):
m_items( mv$(items) )
{
}
// Move present
AttributeList(AttributeList&&) = default;
AttributeList& operator=(AttributeList&&) = default;
// No copy assign, but explicit copy
explicit AttributeList(const AttributeList&) = default;
AttributeList& operator=(const AttributeList&) = delete;
// Explicit clone
AttributeList clone() const;
void push_back(Attribute i);
const Attribute* get(const char *name) const;
Attribute* get(const char *name) {
return const_cast<Attribute*>( const_cast<const AttributeList*>(this)->get(name));
}
bool has(const char *name) const {
return get(name) != 0;
}
friend ::std::ostream& operator<<(::std::ostream& os, const AttributeList& x) {
for(const auto& i : x.m_items) {
os << "#[" << i << "]";
}
return os;
}
};
TAGGED_UNION(AttributeData, None,
(None, struct {}),
(String, struct {
::std::string val;
}),
(List, struct {
::std::vector<Attribute> sub_items;
})
);
// An attribute can has a name, and optional data:
// Data can be:
// - A parenthesised token tree
// > In 1.19 this was actually just sub-attributes
// - an associated (string) literal
class Attribute
{
Span m_span;
RcString m_name;
AttributeData m_data;
mutable bool m_is_used;
// TODO: Parse as a TT then expand?
public:
Attribute(Span sp, RcString name):
m_span(::std::move(sp)),
m_name(name),
m_data( AttributeData::make_None({}) )
{
}
Attribute(Span sp, RcString name, ::std::string str_val):
m_span(::std::move(sp)),
m_name(name),
m_data( AttributeData::make_String({mv$(str_val)}) )
{
}
Attribute(Span sp, RcString name, ::std::vector<Attribute> items):
m_span(::std::move(sp)),
m_name(name),
m_data( AttributeData::make_List({mv$(items)}) )
{
}
explicit Attribute(const Attribute& x):
m_span(x.m_span),
m_name(x.m_name),
m_is_used(x.m_is_used)
{
TU_MATCHA( (x.m_data), (e),
(None,
),
(String,
m_data = AttributeData::make_String({ e.val });
),
(List,
m_data = AttributeData::make_List({ ::std::vector<Attribute>(e.sub_items) });
)
)
}
Attribute& operator=(const Attribute& ) = delete;
Attribute(Attribute&& ) = default;
Attribute& operator=(Attribute&& ) = default;
Attribute clone() const;
void mark_used() const { m_is_used = true; }
bool is_used() const { return m_is_used; }
const Span& span() const { return m_span; }
const RcString& name() const { return m_name; }
const AttributeData& data() const { return m_data; }
// Legacy accessors/checkers
bool has_noarg() const { return m_data.is_None(); }
bool has_string() const { return m_data.is_String(); }
const ::std::string& string() const { return m_data.as_String().val; }
bool has_sub_items() const { return m_data.is_List(); }
const ::std::vector<Attribute>& items() const { return m_data.as_List().sub_items; }
::std::vector<Attribute>& items() { return m_data.as_List().sub_items; }
friend ::std::ostream& operator<<(::std::ostream& os, const Attribute& x) {
os << x.m_name;
TU_MATCHA( (x.m_data), (e),
(None,
),
(String,
os << "=\"" << e.val << "\"";
),
(List,
os << "(" << e.sub_items << ")";
)
)
return os;
}
};
} // namespace AST
#endif
|