3 #include "c4/yml/detail/parser_dbg.hpp"
5 #include "c4/yml/detail/print.hpp"
7 #define _c4dbg_tree(...)
8 #define _c4dbg_node(...)
19 c += m_tree->has_key_anchor(n);
20 c += m_tree->has_val_anchor(n);
21 c += m_tree->is_key_ref(n);
22 c += m_tree->is_val_ref(n);
23 c += m_tree->has_key(n) && m_tree->key(n) ==
"<<";
24 for(
id_type ch = m_tree->first_child(n); ch !=
NONE; ch = m_tree->next_sibling(ch))
25 c += count_anchors_and_refs_(ch);
29 void ReferenceResolver::gather_anchors_and_refs__(
id_type n)
32 if(m_tree->has_key(n))
34 if(m_tree->key(n) ==
"<<")
36 _c4dbgpf(
"node[{}]: key is <<", n);
37 if(m_tree->has_val(n))
39 if(m_tree->is_val_ref(n))
41 _c4dbgpf(
"node[{}]: instance[{}]: val ref, inheriting! '{}'", n, m_refs.size(), m_tree->val_ref(n));
47 _c4dbgpf(
"node[{}]: not ref!", n);
50 else if(m_tree->is_seq(n))
54 _c4dbgpf(
"node[{}]: is seq!", n);
55 for(
id_type ich = m_tree->first_child(n); ich !=
NONE; ich = m_tree->next_sibling(ich))
57 _c4dbgpf(
"node[{}]: instance [{}]: val ref, inheriting multiple: {} '{}'", n, m_refs.size(), ich, m_tree->val_ref(ich));
58 if(m_tree->is_container(ich))
60 detail::_report_err(m_tree->m_callbacks,
"ERROR: node {} child {}: refs for << cannot be containers.'", n, ich);
61 C4_UNREACHABLE_AFTER_ERR();
63 m_refs.push({
VALREF, ich,
NONE,
NONE, n, m_tree->next_sibling(n)});
69 detail::_report_err(m_tree->m_callbacks,
"ERROR: node {}: refs for << must be either val or seq", n);
70 C4_UNREACHABLE_AFTER_ERR();
73 else if(m_tree->is_key_ref(n))
75 _c4dbgpf(
"node[{}]: instance[{}]: key ref: '{}', key='{}'", n, m_refs.size(), m_tree->key_ref(n), m_tree->has_key(n) ? m_tree->key(n) : csubstr{
"-"});
76 _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->key(n) !=
"<<");
77 _RYML_CB_CHECK(m_tree->m_callbacks, (!m_tree->has_key(n)) || m_tree->key(n).ends_with(m_tree->key_ref(n)));
82 if(m_tree->is_val_ref(n) && (!m_tree->has_key(n) || m_tree->key(n) !=
"<<"))
84 _c4dbgpf(
"node[{}]: instance[{}]: val ref: '{}'", n, m_refs.size(), m_tree->val_ref(n));
85 RYML_CHECK((!m_tree->has_val(n)) || m_tree->val(n).ends_with(m_tree->val_ref(n)));
89 if(m_tree->has_key_anchor(n))
91 _c4dbgpf(
"node[{}]: instance[{}]: key anchor: '{}'", n, m_refs.size(), m_tree->key_anchor(n));
92 RYML_CHECK(m_tree->has_key(n));
95 if(m_tree->has_val_anchor(n))
97 _c4dbgpf(
"node[{}]: instance[{}]: val anchor: '{}'", n, m_refs.size(), m_tree->val_anchor(n));
98 RYML_CHECK(m_tree->has_val(n) || m_tree->is_container(n));
102 for(
id_type ch = m_tree->first_child(n); ch !=
NONE; ch = m_tree->next_sibling(ch))
103 gather_anchors_and_refs__(ch);
106 void ReferenceResolver::gather_anchors_and_refs_()
108 _c4dbgp(
"gathering anchors and refs...");
111 id_type num_anchors_and_refs = count_anchors_and_refs_(m_tree->root_id());
112 if(!num_anchors_and_refs)
114 m_refs.reserve(num_anchors_and_refs);
118 gather_anchors_and_refs__(m_tree->root_id());
120 _c4dbgpf(
"found {} anchors/refs", m_refs.size());
125 for(
auto &rd : m_refs)
127 rd.prev_anchor = prev_anchor;
128 if(rd.type.has_anchor())
132 _c4dbgp(
"gathering anchors and refs: finished");
135 id_type ReferenceResolver::lookup_(RefData
const* C4_RESTRICT ra)
141 RYML_ASSERT(ra->type.is_key_ref() || ra->type.is_val_ref());
142 RYML_ASSERT(ra->type.is_key_ref() != ra->type.is_val_ref());
144 _c4dbgpf(
"instance[{}:node{}]: lookup from node={}...", instance, node, ra->node);
145 if(ra->type.is_val_ref())
147 refname = m_tree->val_ref(ra->node);
148 _c4dbgpf(
"instance[{}:node{}]: valref: '{}'", instance, node, refname);
152 RYML_ASSERT(ra->type.is_key_ref());
153 refname = m_tree->key_ref(ra->node);
154 _c4dbgpf(
"instance[{}:node{}]: keyref: '{}'", instance, node, refname);
156 while(ra->prev_anchor !=
NONE)
158 ra = &m_refs[ra->prev_anchor];
159 _c4dbgpf(
"instance[{}:node{}]: lookup '{}' at [{}:node{}]: keyref='{}' valref='{}'", instance, node, refname, ra-m_refs.m_stack, ra->node,
160 (m_tree->has_key_anchor(ra->node) ? m_tree->key_anchor(ra->node) : csubstr(
"~")),
161 (m_tree->has_val_anchor(ra->node) ? m_tree->val_anchor(ra->node) : csubstr(
"~")));
162 if(m_tree->has_anchor(ra->node, refname))
164 _c4dbgpf(
"instance[{}:node{}]: got it at [{}:node{}]!", instance, node, ra-m_refs.m_stack, ra->node);
168 detail::_report_err(m_tree->m_callbacks,
"ERROR: anchor not found: '{}'", refname);
169 C4_UNREACHABLE_AFTER_ERR();
172 void ReferenceResolver::reset_(Tree *t_)
174 if(t_->callbacks() != m_refs.m_callbacks)
176 m_refs.m_callbacks = t_->callbacks();
182 void ReferenceResolver::resolve_()
189 _c4dbgp(
"matching anchors/refs...");
190 for(
id_type i = 0, e = m_refs.size(); i < e; ++i)
192 RefData &C4_RESTRICT refdata = m_refs.top(i);
193 if( ! refdata.type.is_ref())
195 refdata.target = lookup_(&refdata);
197 _c4dbgp(
"matching anchors/refs: finished");
200 _c4dbgp(
"modifying tree...");
203 for(
id_type i = 0, e = m_refs.size(); i < e; ++i)
205 RefData
const& C4_RESTRICT refdata = m_refs[i];
206 _c4dbgpf(
"instance[{}:node{}]: {}/{}...", i, refdata.node, i+1, e);
207 if( ! refdata.type.is_ref())
209 _c4dbgpf(
"instance[{}:node{}]: is reference!", i, refdata.node);
210 if(refdata.parent_ref !=
NONE)
212 _c4dbgpf(
"instance[{}:node{}] has parent: {}", i, refdata.node, refdata.parent_ref);
213 _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->is_seq(refdata.parent_ref));
214 const id_type p = m_tree->parent(refdata.parent_ref);
215 const id_type after = (prev_parent_ref != refdata.parent_ref) ?
218 prev_parent_ref_after;
219 prev_parent_ref = refdata.parent_ref;
220 prev_parent_ref_after = m_tree->duplicate_children_no_rep(refdata.target, p, after);
221 m_tree->remove(refdata.node);
225 _c4dbgpf(
"instance[{}:node{}] has no parent", i, refdata.node, refdata.parent_ref);
226 if(m_tree->has_key(refdata.node) && m_tree->key(refdata.node) ==
"<<")
228 _c4dbgpf(
"instance[{}:node{}] is inheriting", i, refdata.node);
229 _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->is_keyval(refdata.node));
230 const id_type p = m_tree->parent(refdata.node);
231 const id_type after = m_tree->prev_sibling(refdata.node);
232 _c4dbgpf(
"instance[{}:node{}] p={} after={}", i, refdata.node, p, after);
233 m_tree->duplicate_children_no_rep(refdata.target, p, after);
234 m_tree->remove(refdata.node);
236 else if(refdata.type.is_key_ref())
238 _c4dbgpf(
"instance[{}:node{}] is key ref", i, refdata.node);
239 _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->is_key_ref(refdata.node));
240 _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->has_key_anchor(refdata.target) || m_tree->has_val_anchor(refdata.target));
241 if(m_tree->has_val_anchor(refdata.target) && m_tree->val_anchor(refdata.target) == m_tree->key_ref(refdata.node))
243 _c4dbgpf(
"instance[{}:node{}] target.anchor==val.anchor=={}", i, refdata.node, m_tree->val_anchor(refdata.target));
244 _RYML_CB_CHECK(m_tree->m_callbacks, !m_tree->is_container(refdata.target));
245 _RYML_CB_CHECK(m_tree->m_callbacks, m_tree->has_val(refdata.target));
246 const type_bits existing_style_flags =
VAL_STYLE & m_tree->_p(refdata.target)->m_type.type;
248 m_tree->_p(refdata.node)->m_key.scalar = m_tree->val(refdata.target);
249 m_tree->_add_flags(refdata.node,
KEY | (existing_style_flags >> 1u));
253 _c4dbgpf(
"instance[{}:node{}] don't inherit container flags", i, refdata.node);
254 _RYML_CB_CHECK(m_tree->m_callbacks, m_tree->key_anchor(refdata.target) == m_tree->key_ref(refdata.node));
255 m_tree->_p(refdata.node)->m_key.scalar = m_tree->key(refdata.target);
257 const type_bits existing_style_flags =
KEY_STYLE & m_tree->_p(refdata.target)->m_type.type;
258 m_tree->_add_flags(refdata.node,
KEY | existing_style_flags);
263 _c4dbgpf(
"instance[{}:node{}] is val ref", i, refdata.node);
264 _RYML_CB_ASSERT(m_tree->m_callbacks, refdata.type.is_val_ref());
265 if(m_tree->has_key_anchor(refdata.target) && m_tree->key_anchor(refdata.target) == m_tree->val_ref(refdata.node))
267 _c4dbgpf(
"instance[{}:node{}] target.anchor==key.anchor=={}", i, refdata.node, m_tree->val_anchor(refdata.target));
268 _RYML_CB_CHECK(m_tree->m_callbacks, !m_tree->is_container(refdata.target));
269 _RYML_CB_CHECK(m_tree->m_callbacks, m_tree->has_val(refdata.target));
271 const type_bits existing_style_flags = (
KEY_STYLE) & m_tree->_p(refdata.target)->m_type.type;
273 m_tree->_p(refdata.node)->m_val.scalar = m_tree->key(refdata.target);
274 m_tree->_add_flags(refdata.node,
VAL | (existing_style_flags << 1u));
278 _c4dbgpf(
"instance[{}:node{}] duplicate contents", i, refdata.node);
279 m_tree->duplicate_contents(refdata.target, refdata.node);
289 _c4dbgp(
"resolving references...");
295 gather_anchors_and_refs_();
304 _c4dbgp(
"clearing anchors/refs");
305 auto clear_ = [
this]{
306 for(
auto const& C4_RESTRICT ar : m_refs)
308 m_tree->rem_anchor_ref(ar.node);
309 if(ar.parent_ref !=
NONE)
310 if(m_tree->type(ar.parent_ref) !=
NOTYPE)
311 m_tree->remove(ar.parent_ref);
319 gather_anchors_and_refs_();
321 _c4dbgp(
"clearing anchors/refs: finished");
327 _c4dbgp(
"resolving references: finished");
Common utilities and infrastructure used by ryml.
uint32_t type_bits
the integral type necessary to cover all the bits for NodeType_e
@ VALANCH
the val has an &anchor
@ NOTYPE
no node type or style is set
@ VALREF
a *reference: the val references an &anchor
@ VAL_STYLE
mask of all the scalar styles for val (not container styles!)
@ VAL
a scalar: has a scalar (ie string) value, possibly empty. must be a leaf node, and cannot be MAP or S...
@ KEY_STYLE
mask of all the scalar styles for key (not container styles!)
@ KEYREF
a *reference: the key references an &anchor
@ KEYANCH
the key has an &anchor
RYML_ID_TYPE id_type
The type of a node id in the YAML tree; to override the default type, define the macro RYML_ID_TYPE t...
void resolve(Tree *tree, bool clear_anchors=true)
Resolve references: for each reference, look for a matching anchor, and copy its contents to the ref ...