Skip to content

Commit

Permalink
Support [switch] and [if] in [tag]
Browse files Browse the repository at this point in the history
Use this new feature to validate [effect] tags
  • Loading branch information
CelticMinstrel committed Mar 16, 2018
1 parent 09469e4 commit 6558669
Show file tree
Hide file tree
Showing 9 changed files with 483 additions and 37 deletions.
17 changes: 15 additions & 2 deletions data/schema/game_config.cfg
@@ -1,5 +1,3 @@
#textdomain wesnoth

{./macros.cfg}

[wml_schema]
Expand Down Expand Up @@ -161,6 +159,21 @@
name="server_address"
value="[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)+:\d+"
[/type]
[type]
name="effect_times"
[union]
[type]
link=int
[/type]
[type]
value="per level"
[/type]
[/union]
[/type]
[type]
name="effect_set_special_mode"
value="append|replace"
[/type]
[tag]
name="root"
min=1
Expand Down
6 changes: 1 addition & 5 deletions data/schema/units/animations.cfg
Expand Up @@ -79,6 +79,7 @@
[/tag]

# Specific animation tags
# Any new tag added here must also be linked from [effect]
[tag]
name="animation"
max=infinite
Expand Down Expand Up @@ -121,11 +122,6 @@
max=infinite
super="units/unit_type/$animation"
[/tag]
[tag]
name="defend"
max=infinite
super="units/unit_type/$animation"
[/tag]
[tag]
name="pre_movement_anim"
max=infinite
Expand Down
210 changes: 208 additions & 2 deletions data/schema/units/modifications.cfg
Expand Up @@ -7,8 +7,214 @@
max=infinite
# TODO: The schema of this tag depends on the value of apply_to...
{REQUIRED_KEY apply_to string}
{ANY_KEY string}
any_tag=yes
{DEFAULT_KEY times effect_times 1}
{FILTER_TAG "filter" unit ()}
[switch]
key=apply_to
[case]
value=new_attack
super="units/unit_type/attack"
[/case]
{FILTER_TAG "case" weapon value=remove_attacks}
{FILTER_TAG "case" weapon (
value=attack
{SIMPLE_KEY set_name string}
{SIMPLE_KEY set_description t_string}
{SIMPLE_KEY set_type string}
{SIMPLE_KEY set_icon string}
{SIMPLE_KEY set_range string}

{SIMPLE_KEY set_damage int}
{SIMPLE_KEY set_attacks int}
{SIMPLE_KEY set_parry int}
{SIMPLE_KEY set_accuracy int}
{SIMPLE_KEY set_movement_used int}

{SIMPLE_KEY increase_damage int}
{SIMPLE_KEY increase_attacks int}
{SIMPLE_KEY increase_parry int}
{SIMPLE_KEY increase_accuracy int}
{SIMPLE_KEY increase_movement_used int}

{SIMPLE_KEY attack_weight int}
{SIMPLE_KEY defense_weight int}
{SIMPLE_KEY remove_specials string_list}

[tag]
name="set_specials"
super="units/unit_type/attack/specials"
{DEFAULT_KEY mode effect_set_special_mode replace}
[/tag]
)}
[case]
value=max_attacks,max_experience
{SIMPLE_KEY increase int_percent}
[/case]
[case]
value=movement,vision,jamming,experience,recall_cost
{SIMPLE_KEY increase int_percent}
{SIMPLE_KEY set int}
[/case]
[case]
value=hitpoints
{SIMPLE_KEY increase int_percent}
{DEFAULT_KEY heal_full bool yes}
{SIMPLE_KEY increase_total int_percent}
{DEFAULT_KEY violate_maximum bool no}
[/case]
[case]
value=loyal
# Nothing allowed here
[/case]
[case]
value=movement_costs
{SIMPLE_KEY replace bool}
[link]
name="units/movetype/movement_costs"
[/link]
[/case]
[case]
value=vision_costs
{SIMPLE_KEY replace bool}
[link]
name="units/movetype/vision_costs"
[/link]
[/case]
[case]
value=jamming_costs
{SIMPLE_KEY replace bool}
[link]
name="units/movetype/jamming_costs"
[/link]
[/case]
[case]
value=defense
{SIMPLE_KEY replace bool}
[link]
name="units/movetype/defense"
[/link]
[/case]
[case]
value=resistance
{SIMPLE_KEY replace bool}
[link]
name="units/movetype/resistance"
[/link]
[/case]
[case]
value=variation,type
{SIMPLE_KEY name string}
[/case]
[case]
value=status
{SIMPLE_KEY add string_list}
{SIMPLE_KEY remove string_list}
[/case]
[case]
value=zoc
{SIMPLE_KEY value bool}
[/case]
[case]
value=profile
{SIMPLE_KEY portrait string}
{SIMPLE_KEY small_portrait string}
{SIMPLE_KEY description t_string}
[/case]
[case]
value=new_ability,remove_ability
[link]
name="units/unit_type/abilities"
[/link]
[/case]
[case]
value=new_animation
[link]
name="units/unit_type/animation"
[/link]
[link]
name="units/unit_type/defend"
[/link]
[link]
name="units/unit_type/death"
[/link]
[link]
name="units/unit_type/standing_anim"
[/link]
[link]
name="units/unit_type/movement_anim"
[/link]
[link]
name="units/unit_type/idle_anim"
[/link]
[link]
name="units/unit_type/attack_anim"
[/link]
[link]
name="units/unit_type/victory_anim"
[/link]
[link]
name="units/unit_type/pre_movement_anim"
[/link]
[link]
name="units/unit_type/post_movement_anim"
[/link]
[link]
name="units/unit_type/draw_weapon_anim"
[/link]
[link]
name="units/unit_type/sheath_weapon_anim"
[/link]
[link]
name="units/unit_type/leading_anim"
[/link]
[link]
name="units/unit_type/recruit_anim"
[/link]
[link]
name="units/unit_type/recruiting_anim"
[/link]
[link]
name="units/unit_type/healing_anim"
[/link]
[link]
name="units/unit_type/extra_anim"
[/link]
[/case]
[case]
value=image_mod,overlay
{SIMPLE_KEY replace string}
{SIMPLE_KEY add string}
[/case]
[case]
value=ellipse
{SIMPLE_KEY ellipse string}
[/case]
[case]
value=halo
{SIMPLE_KEY halo string}
[/case]
[case]
value=alignment
{SIMPLE_KEY set alignment}
[/case]
[case]
value=new_advancement
{SIMPLE_KEY replace bool}
{SIMPLE_KEY types string_list}
[link]
name="units/$modifications/advancement"
[/link]
[/case]
[case]
value=remove_advancement
{SIMPLE_KEY types string_list}
{SIMPLE_KEY amlas string_list}
[/case]
[default]
any_tag=yes
{ANY_KEY string}
[/default]
[/switch]
{WML_MERGE_KEYS}
[/tag]
{WML_MERGE_KEYS}
Expand Down
15 changes: 9 additions & 6 deletions src/serialization/parser.cpp
Expand Up @@ -184,6 +184,7 @@ void parser::parse_element()

std::string elname;
config* current_element = nullptr;
config* parent = nullptr;

switch(tok_.current_token().type) {
case token::STRING: // [element]
Expand All @@ -194,11 +195,12 @@ void parser::parse_element()
}

// Add the element
current_element = &(elements.top().cfg->add_child(elname));
parent = elements.top().cfg;
current_element = &(parent->add_child(elname));
elements.emplace(current_element, elname, tok_.get_start_line(), tok_.get_file());

if(validator_) {
validator_->open_tag(elname, tok_.get_start_line(), tok_.get_file());
validator_->open_tag(elname, *parent, tok_.get_start_line(), tok_.get_file());
}

break;
Expand All @@ -215,17 +217,18 @@ void parser::parse_element()
}

// Find the last child of the current element whose name is element
if(config& c = elements.top().cfg->child(elname, -1)) {
parent = elements.top().cfg;
if(config& c = parent->child(elname, -1)) {
current_element = &c;

if(validator_) {
validator_->open_tag(elname, tok_.get_start_line(), tok_.get_file(), true);
validator_->open_tag(elname, *parent, tok_.get_start_line(), tok_.get_file(), true);
}
} else {
current_element = &elements.top().cfg->add_child(elname);
current_element = &parent->add_child(elname);

if(validator_) {
validator_->open_tag(elname, tok_.get_start_line(), tok_.get_file());
validator_->open_tag(elname, *parent, tok_.get_start_line(), tok_.get_file());
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/serialization/schema_validator.cpp
Expand Up @@ -189,13 +189,13 @@ bool schema_validator::read_config_file(const std::string& filename)
* assume they all are on their place due to parser algorithm
* and validation logic
*/
void schema_validator::open_tag(const std::string& name, int start_line, const std::string& file, bool addittion)
void schema_validator::open_tag(const std::string& name, const config& parent, int start_line, const std::string& file, bool addittion)
{
if(!stack_.empty()) {
const class_tag* tag = nullptr;

if(stack_.top()) {
tag = stack_.top()->find_tag(name, root_);
tag = stack_.top()->find_tag(name, root_, parent);

if(!tag) {
wrong_tag_error(file, start_line, name, stack_.top()->get_name(), create_exceptions_);
Expand Down Expand Up @@ -243,7 +243,7 @@ void schema_validator::validate(const config& cfg, const std::string& name, int
// Please note that validating unknown tag keys the result will be false
// Checking all elements counters.
if(!stack_.empty() && stack_.top() && config_read_) {
for(const auto& tag : stack_.top()->tags()) {
for(const auto& tag : stack_.top()->tags(cfg)) {
int cnt = counter_.top()[tag.first].cnt;

if(tag.second.get_min() > cnt) {
Expand All @@ -259,7 +259,7 @@ void schema_validator::validate(const config& cfg, const std::string& name, int
}

// Checking if all mandatory keys are present
for(const auto& key : stack_.top()->keys()) {
for(const auto& key : stack_.top()->keys(cfg)) {
if(key.second.is_mandatory()) {
if(cfg.get(key.first) == nullptr) {
cache_.top()[&cfg].emplace_back(MISSING_KEY, file, start_line, 0, name, key.first);
Expand All @@ -274,7 +274,7 @@ void schema_validator::validate_key(
{
if(!stack_.empty() && stack_.top() && !stack_.top()->get_name().empty() && config_read_) {
// checking existing keys
const class_key* key = stack_.top()->find_key(name);
const class_key* key = stack_.top()->find_key(name, cfg);
if(key) {
bool matched = false;
for(auto& possible_type : utils::split(key->get_type())) {
Expand Down
2 changes: 1 addition & 1 deletion src/serialization/schema_validator.hpp
Expand Up @@ -52,7 +52,7 @@ class schema_validator : public abstract_validator
}

virtual void open_tag(
const std::string& name, int start_line = 0, const std::string& file = "", bool addittion = false);
const std::string& name, const config& parent, int start_line = 0, const std::string& file = "", bool addittion = false);
virtual void close_tag();
virtual void validate(const config& cfg, const std::string& name, int start_line, const std::string& file);
virtual void validate_key(const config& cfg,
Expand Down

0 comments on commit 6558669

Please sign in to comment.