27 wml_tag
any_tag(
"", 0, -1,
"",
true);
30 : name_(cfg[
"name"].str())
31 , min_(cfg[
"min"].to_int())
32 , max_(cfg[
"max"].str() ==
"infinite" ? -1 : cfg[
"max"].to_int(1))
33 , min_children_(cfg[
"min_tags"].to_int())
34 , max_children_(cfg[
"max_tags"].str() ==
"infinite" ? -1 : cfg[
"max_tags"].to_int(-1))
41 , fuzzy_(name_.find_first_of(
"*?+") !=
std::string::npos)
42 , any_tag_(cfg[
"any_tag"].to_bool())
52 super_ = cfg[
"super"].str();
66 std::string link_name = link[
"name"].str();
86 std::istringstream
i(s);
94 std::istringstream
i(s);
102 std::string::size_type pos_last = link.rfind(
'/');
104 std::string name_link = link.substr(pos_last + 1, link.length());
105 links_.emplace(name_link, link);
113 if(
cond.matches(match)) {
114 if(
auto key =
cond.find_key(name, match,
true)) {
120 const auto it_keys =
keys_.find(name);
121 if(it_keys !=
keys_.end()) {
122 return &(it_keys->second);
125 key_map::const_iterator it_fuzzy = std::find_if(
keys_.begin(),
keys_.end(), [&
name](
const key_map::value_type& key){
126 if(!key.second.is_fuzzy()) {
131 if(it_fuzzy !=
keys_.end()) {
132 return &(it_fuzzy->second);
136 for(
auto&
cond : conditions_) {
137 if(
cond.matches(match)) {
139 if(
auto key =
cond.find_key(name, match,
false)) {
145 if(
const wml_key* found_key = super_tag->find_key(name, match)) {
156 const auto it_links =
links_.find(name);
157 if(it_links !=
links_.end()) {
158 return &(it_links->second);
166 if(fullpath.empty()) {
170 std::string::size_type pos = fullpath.find(
'/');
172 std::string next_path;
174 if(pos != std::string::npos) {
175 name = fullpath.substr(0, pos);
176 next_path = fullpath.substr(pos + 1, fullpath.length());
184 if(
cond.matches(match)) {
185 if(
auto tag =
cond.find_tag(fullpath, root, match,
true)) {
191 const auto it_tags =
tags_.find(name);
192 if(it_tags !=
tags_.end()) {
193 if(next_path.empty()) {
194 return &(it_tags->second);
196 return it_tags->second.find_tag(next_path, root, match);
200 const auto it_links =
links_.find(name);
201 if(it_links !=
links_.end()) {
202 return root.
find_tag(it_links->second +
"/" + next_path, root, match);
205 const auto it_fuzzy = std::find_if(
tags_.begin(),
tags_.end(), [&
name](
const tag_map::value_type& tag){
206 if(!tag.second.fuzzy_) {
211 if(it_fuzzy !=
tags_.end()) {
212 if(next_path.empty()) {
213 return &(it_fuzzy->second);
215 return it_tags->second.
find_tag(next_path, root, match);
220 for(
auto&
cond : conditions_) {
221 if(
cond.matches(match)) {
223 if(
auto tag =
cond.find_tag(fullpath, root, match,
false)) {
229 if(
const wml_tag* found_tag = super_tag->
find_tag(fullpath, root, match)) {
244 for(
auto& tag :
tags_) {
245 tag.second.expand(root);
246 tag.second.expand_all(root);
250 cond.expand_all(root);
258 if(
i->second.get_type() ==
type) {
265 for(
auto& tag :
tags_) {
266 tag.second.remove_keys_by_type(type);
273 for(
int j = 0; j <
level; j++) {
278 << s <<
" name=\"" <<
name_ <<
"\"\n" 279 << s <<
" min=\"" <<
min_ <<
"\"\n" 280 << s <<
" max=\"" <<
max_ <<
"\"\n";
283 os << s <<
" super=\"" <<
super_ <<
"\"\n";
286 for(
auto& tag :
tags_) {
287 tag.second.printl(os, level + step, step);
290 for(
auto& link :
links_) {
294 <<
" name=\"" << link.second <<
"\"\n" 299 for(
auto& key :
keys_) {
300 key.second.print(os, level + step);
305 os << s <<
"[/tag]\n";
310 if(path.empty() || path ==
"/") {
313 if(it ==
tags_.end()) {
316 it->second.set_min(tag.
min_);
317 it->second.set_max(tag.
max_);
318 it->second.add_tags(tag.
tags_);
319 it->second.add_keys(tag.
keys_);
320 it->second.add_links(tag.
links_);
328 std::string::size_type pos = path.find(
'/');
329 std::string
name = path.substr(0, pos);
330 std::string next_path = path.substr(pos + 1, path.length());
332 auto it_links =
links_.find(name);
333 if(it_links !=
links_.end()) {
334 root.
add_tag(it_links->second +
"/" + next_path, tag, root);
337 auto it_tags =
tags_.find(name);
338 if(it_tags ==
tags_.end()) {
341 subtag.
add_tag(next_path, tag, root);
342 tags_.emplace(name, subtag);
346 it_tags->second.add_tag(next_path, tag, root);
359 if(super_tag !=
this) {
373 const std::string key = switch_cfg[
"key"];
374 bool allow_missing =
false;
375 for(
const auto& case_cfg : switch_cfg.
child_range(
"case")) {
376 if(case_cfg.has_attribute(
"value")) {
379 for(
const auto& value : values) {
387 default_cfg.
add_child(
"not")[key] = value;
389 if(!allow_missing && case_cfg[
"trigger_if_missing"].to_bool()) {
391 missing_filter[
"glob_on_" + key] =
"*";
392 allow_missing =
true;
407 default_cfg.
add_child(
"and")[
"glob_on_" + key] =
"*";
417 config filter = cond_cfg, else_filter;
421 else_filter.add_child(
"not", filter);
428 for(
auto elseif_cfg : cond_cfg.
child_range(
"elseif")) {
429 config elseif_filter = elseif_cfg, old_else_filter = else_filter;
431 else_filter.add_child(
"not", elseif_filter);
434 conditions_.emplace_back(elseif_cfg.child_or_empty(
"then"), elseif_filter);
460 current = base_tag.
tags_.begin();
461 condition_queue.push(&base_tag);
466 while(current == condition_queue.front()->tags_.end()) {
467 condition_queue.pop();
468 if(condition_queue.empty()) {
471 const wml_tag& new_base = *condition_queue.front();
472 current= new_base.
tags_.begin();
480 current = base_tag.
keys_.begin();
481 condition_queue.push(&base_tag);
486 while(current == condition_queue.front()->keys_.end()) {
487 condition_queue.pop();
488 if(condition_queue.empty()) {
491 const wml_tag& new_base = *condition_queue.front();
492 current = new_base.
keys_.begin();
499 if(condition.matches(match)) {
int max_children_
maximum number of children.
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
void ensure_valid_or_end()
bool matches(const config &filter) const
void clear_children(T... keys)
bool has_attribute(config_key_type key) const
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
child_itors child_range(config_key_type key)
REMOVE_EMPTY: remove empty elements.
void add_switch(const config &switch_cfg)
Stores information about tag.
bool wildcard_string_match(const std::string &str, const std::string &match)
Match using '*' as any number of characters (including none), '+' as one or more characters, and '?' as any one character.
void add_filter(const config &cond_cfg)
void remove_keys_by_type(const std::string &type)
Removes all keys with this type.
void append_children(const config &cfg)
Adds children from cfg.
const wml_key * find_key(const std::string &name, const config &match, bool ignore_super=false) const
Returns pointer to child key.
This file contains object "tag", which is used to store information about tags while annotation parsi...
void add_link(const std::string &link)
const wml_tag * find_tag(const std::string &fullpath, const wml_tag &root, const config &match, bool ignore_super=false) const
Returns pointer to tag using full path to it.
bool matches(const config &cfg) const
super_list super_refs_
super-tag references
void add_key(const wml_key &new_key)
tag_map tags_
children tags
std::vector< wml_condition > condition_list
std::string name_
name of tag.
static void push_new_tag_conditions(std::queue< const wml_tag *> &q, const config &match, const wml_tag &tag)
void add_tag(const wml_tag &new_tag)
wml_tag any_tag("", 0, -1, "", true)
condition_list conditions_
conditional partial matches
void init(const wml_tag &base_tag)
void printl(std::ostream &os, int level, int step=4)
the same as wml_tag::print(std::ostream&) but indents different levels with step space.
int min_
minimum number of occurrences.
void print(std::ostream &os)
Prints information about tag to outputstream, recursively is used to print tag info the format is nex...
wml_key is used to save the information about one key.
link_map links_
links to possible children.
static map_location::DIRECTION s
int max_
maximum number of occurrences.
bool any_tag_
whether this tag allows arbitrary subtags.
static map_location::DIRECTION sw
config & add_child(config_key_type key)
void set_name(const std::string &name)
void expand(wml_tag &root)
Expands all "super", storing direct references for easier access.
void expand_all(wml_tag &root)
Calls the expansion on each child.
std::vector< std::string > split(const config_attribute_value &val)
const std::string & get_name() const
void add_conditions(const condition_list &list)
static int cond(LexState *ls)
std::string super_
name of tag to extend "super-tag" Extension is smth like inheritance and is used in case when you nee...
static const char * match(MatchState *ms, const char *s, const char *p)
A config object defines a single node in a WML file, with access to child nodes.
const std::string * find_link(const std::string &name) const
Returns pointer to child link.