4 #include "c4/yml/detail/parser_dbg.hpp"
6 #include "c4/yml/detail/print.hpp"
8 #define _c4dbg_tree(...)
9 #define _c4dbg_node(...)
20 c += m_tree->has_key_anchor(n);
21 c += m_tree->has_val_anchor(n);
22 c += m_tree->is_key_ref(n);
23 c += m_tree->is_val_ref(n);
24 c += m_tree->has_key(n) && m_tree->key(n) ==
"<<";
25 for(
id_type ch = m_tree->first_child(n); ch !=
NONE; ch = m_tree->next_sibling(ch))
26 c += count_anchors_and_refs_(ch);
30 void ReferenceResolver::gather_anchors_and_refs__(
id_type n)
33 if(m_tree->has_key(n))
35 if(m_tree->key(n) ==
"<<")
37 _c4dbgpf(
"node[{}]: key is <<", n);
38 if(m_tree->has_val(n))
40 if(m_tree->is_val_ref(n))
42 _c4dbgpf(
"node[{}]: val ref, inheriting!", n);
48 _c4dbgpf(
"node[{}]: not ref!", n);
51 else if(m_tree->is_seq(n))
55 _c4dbgpf(
"node[{}]: is seq!", n);
56 for(
id_type ich = m_tree->first_child(n); ich !=
NONE; ich = m_tree->next_sibling(ich))
58 _c4dbgpf(
"node[{}]: val ref, inheriting multiple: {}", n, ich);
59 if(m_tree->is_container(ich))
61 detail::_report_err(m_tree->m_callbacks,
"ERROR: node {} child {}: refs for << cannot be containers.'", n, ich);
62 C4_UNREACHABLE_AFTER_ERR();
64 m_refs.push({
VALREF, ich,
NONE,
NONE, n, m_tree->next_sibling(n)});
70 detail::_report_err(m_tree->m_callbacks,
"ERROR: node {}: refs for << must be either val or seq", n);
71 C4_UNREACHABLE_AFTER_ERR();
74 else if(m_tree->is_key_ref(n))
76 _c4dbgpf(
"node[{}]: key ref: '{}'", n, m_tree->key_ref(n));
77 _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->key(n) !=
"<<");
78 _RYML_CB_CHECK(m_tree->m_callbacks, (!m_tree->has_key(n)) || m_tree->key(n).ends_with(m_tree->key_ref(n)));
83 if(m_tree->is_val_ref(n) && (!m_tree->has_key(n) || m_tree->key(n) !=
"<<"))
85 _c4dbgpf(
"node[{}]: val ref: '{}'", n, m_tree->val_ref(n));
86 RYML_CHECK((!m_tree->has_val(n)) || m_tree->val(n).ends_with(m_tree->val_ref(n)));
90 if(m_tree->has_key_anchor(n))
92 _c4dbgpf(
"node[{}]: key anchor: '{}'", n, m_tree->key_anchor(n));
93 RYML_CHECK(m_tree->has_key(n));
96 if(m_tree->has_val_anchor(n))
98 _c4dbgpf(
"node[{}]: val anchor: '{}'", n, m_tree->val_anchor(n));
99 RYML_CHECK(m_tree->has_val(n) || m_tree->is_container(n));
103 for(
id_type ch = m_tree->first_child(n); ch !=
NONE; ch = m_tree->next_sibling(ch))
104 gather_anchors_and_refs__(ch);
107 void ReferenceResolver::gather_anchors_and_refs_()
109 _c4dbgp(
"gathering anchors and refs...");
112 id_type num_anchors_and_refs = count_anchors_and_refs_(m_tree->root_id());
113 if(!num_anchors_and_refs)
115 m_refs.reserve(num_anchors_and_refs);
119 gather_anchors_and_refs__(m_tree->root_id());
121 _c4dbgpf(
"found {} anchors/refs", m_refs.size());
126 for(
auto &rd : m_refs)
128 rd.prev_anchor = prev_anchor;
129 if(rd.type.has_anchor())
133 _c4dbgp(
"gathering anchors and refs: finished");
136 id_type ReferenceResolver::lookup_(RefData *C4_RESTRICT ra)
138 RYML_ASSERT(ra->type.is_key_ref() || ra->type.is_val_ref());
139 RYML_ASSERT(ra->type.is_key_ref() != ra->type.is_val_ref());
141 if(ra->type.is_val_ref())
143 refname = m_tree->val_ref(ra->node);
147 RYML_ASSERT(ra->type.is_key_ref());
148 refname = m_tree->key_ref(ra->node);
150 while(ra->prev_anchor !=
NONE)
152 ra = &m_refs[ra->prev_anchor];
153 if(m_tree->has_anchor(ra->node, refname))
156 detail::_report_err(m_tree->m_callbacks,
"ERROR: anchor not found: '{}'", refname);
157 C4_UNREACHABLE_AFTER_ERR();
160 void ReferenceResolver::reset_(Tree *t_)
162 if(t_->callbacks() != m_refs.m_callbacks)
164 m_refs.m_callbacks = t_->callbacks();
172 _c4dbgp(
"resolving references...");
178 gather_anchors_and_refs_();
187 _c4dbgp(
"matching anchors/refs...");
188 for(
id_type i = 0, e = m_refs.size(); i < e; ++i)
190 RefData &C4_RESTRICT refdata = m_refs.top(i);
191 if( ! refdata.type.is_ref())
193 refdata.target = lookup_(&refdata);
195 _c4dbgp(
"matching anchors/refs: finished");
198 _c4dbgp(
"modifying tree...");
201 for(
id_type i = 0, e = m_refs.size(); i < e; ++i)
203 RefData
const& C4_RESTRICT refdata = m_refs[i];
204 _c4dbgpf(
"instance {}/{}...", i, e);
205 if( ! refdata.type.is_ref())
207 _c4dbgpf(
"instance {} is reference!", i);
208 if(refdata.parent_ref !=
NONE)
210 _c4dbgpf(
"ref {} has parent: {}", i, refdata.parent_ref);
211 _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->is_seq(refdata.parent_ref));
212 const id_type p = m_tree->parent(refdata.parent_ref);
213 const id_type after = (prev_parent_ref != refdata.parent_ref) ?
216 prev_parent_ref_after;
217 prev_parent_ref = refdata.parent_ref;
218 prev_parent_ref_after = m_tree->duplicate_children_no_rep(refdata.target, p, after);
219 m_tree->remove(refdata.node);
223 _c4dbgpf(
"ref {} has no parent", i, refdata.parent_ref);
224 if(m_tree->has_key(refdata.node) && m_tree->key(refdata.node) ==
"<<")
226 _c4dbgpf(
"ref {} is inheriting", i);
227 _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->is_keyval(refdata.node));
228 const id_type p = m_tree->parent(refdata.node);
229 const id_type after = m_tree->prev_sibling(refdata.node);
230 m_tree->duplicate_children_no_rep(refdata.target, p, after);
231 m_tree->remove(refdata.node);
233 else if(refdata.type.is_key_ref())
235 _c4dbgpf(
"ref {} is key ref", i);
236 _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->is_key_ref(refdata.node));
237 _RYML_CB_ASSERT(m_tree->m_callbacks, m_tree->has_key_anchor(refdata.target) || m_tree->has_val_anchor(refdata.target));
238 if(m_tree->has_val_anchor(refdata.target) && m_tree->val_anchor(refdata.target) == m_tree->key_ref(refdata.node))
240 _RYML_CB_CHECK(m_tree->m_callbacks, !m_tree->is_container(refdata.target));
241 _RYML_CB_CHECK(m_tree->m_callbacks, m_tree->has_val(refdata.target));
242 const type_bits existing_style_flags =
VAL_STYLE & m_tree->_p(refdata.target)->m_type.type;
244 m_tree->_p(refdata.node)->m_key.scalar = m_tree->val(refdata.target);
245 m_tree->_add_flags(refdata.node,
KEY | (existing_style_flags >> 1u));
249 _RYML_CB_CHECK(m_tree->m_callbacks, m_tree->key_anchor(refdata.target) == m_tree->key_ref(refdata.node));
250 m_tree->_p(refdata.node)->m_key.scalar = m_tree->key(refdata.target);
252 const type_bits existing_style_flags =
KEY_STYLE & m_tree->_p(refdata.target)->m_type.type;
253 m_tree->_add_flags(refdata.node,
KEY | existing_style_flags);
258 _c4dbgpf(
"ref {} is val ref", i);
259 _RYML_CB_ASSERT(m_tree->m_callbacks, refdata.type.is_val_ref());
260 if(m_tree->has_key_anchor(refdata.target) && m_tree->key_anchor(refdata.target) == m_tree->val_ref(refdata.node))
262 _RYML_CB_CHECK(m_tree->m_callbacks, !m_tree->is_container(refdata.target));
263 _RYML_CB_CHECK(m_tree->m_callbacks, m_tree->has_val(refdata.target));
265 const type_bits existing_style_flags = (
KEY_STYLE) & m_tree->_p(refdata.target)->m_type.type;
267 m_tree->_p(refdata.node)->m_val.scalar = m_tree->key(refdata.target);
268 m_tree->_add_flags(refdata.node,
VAL | (existing_style_flags << 1u));
272 m_tree->duplicate_contents(refdata.target, refdata.node);
277 _c4dbgp(
"modifying tree: finished");
280 _c4dbgp(
"clearing anchors/refs");
281 for(
auto const& C4_RESTRICT ar : m_refs)
283 m_tree->rem_anchor_ref(ar.node);
284 if(ar.parent_ref !=
NONE)
285 if(m_tree->type(ar.parent_ref) !=
NOTYPE)
286 m_tree->remove(ar.parent_ref);
288 _c4dbgp(
"clearing anchors/refs: finished");
293 _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 *t_)
Resolve references: for each reference, look for a matching anchor, and copy its contents to the ref ...