1 #include "Parse.h" 2 3 #include "ParseImpl.h" 4 #include "EnumParser.h" 5 #include "ValueRefParser.h" 6 #include "EnumValueRefRules.h" 7 #include "EffectParser.h" 8 #include "ConditionParserImpl.h" 9 #include "MovableEnvelope.h" 10 11 #include "../universe/Condition.h" 12 #include "../universe/Effect.h" 13 #include "../universe/Species.h" 14 #include "../util/Directories.h" 15 16 #include <boost/spirit/include/phoenix.hpp> 17 18 19 #define DEBUG_PARSERS 0 20 21 #if DEBUG_PARSERS 22 namespace std { operator <<(ostream & os,const FocusType &)23 inline ostream& operator<<(ostream& os, const FocusType&) { return os; } operator <<(ostream & os,const std::vector<FocusType> &)24 inline ostream& operator<<(ostream& os, const std::vector<FocusType>&) { return os; } operator <<(ostream & os,const parse::effects_group_payload &)25 inline ostream& operator<<(ostream& os, const parse::effects_group_payload&) { return os; } operator <<(ostream & os,const std::pair<PlanetType,PlanetEnvironment> &)26 inline ostream& operator<<(ostream& os, const std::pair<PlanetType, PlanetEnvironment>&) { return os; } operator <<(ostream & os,const std::pair<const PlanetType,PlanetEnvironment> &)27 inline ostream& operator<<(ostream& os, const std::pair<const PlanetType, PlanetEnvironment>&) { return os; } operator <<(ostream & os,const std::map<PlanetType,PlanetEnvironment> &)28 inline ostream& operator<<(ostream& os, const std::map<PlanetType, PlanetEnvironment>&) { return os; } operator <<(ostream & os,const std::pair<const std::string,std::unique_ptr<Species>> &)29 inline ostream& operator<<(ostream& os, const std::pair<const std::string, std::unique_ptr<Species>>&) { return os; } operator <<(ostream & os,const std::map<std::string,std::unique_ptr<Species>> &)30 inline ostream& operator<<(ostream& os, const std::map<std::string, std::unique_ptr<Species>>&) { return os; } 31 } 32 #endif 33 34 namespace { 35 const boost::phoenix::function<parse::detail::is_unique> is_unique_; 36 37 struct SpeciesStuff { SpeciesStuff__anonf5bd12b80111::SpeciesStuff38 SpeciesStuff(const boost::optional<std::vector<FocusType>>& foci_, 39 const boost::optional<std::string>& preferred_focus_, 40 const std::set<std::string>& tags_, 41 const std::string& graphic_) : 42 foci(foci_), 43 preferred_focus(preferred_focus_), 44 tags(tags_), 45 graphic(graphic_) 46 {} 47 48 boost::optional<std::vector<FocusType>> foci; 49 boost::optional<std::string> preferred_focus; 50 std::set<std::string> tags; 51 std::string graphic; 52 }; 53 54 insert_species(std::map<std::string,std::unique_ptr<Species>> & species,const SpeciesStrings & strings,const boost::optional<std::map<PlanetType,PlanetEnvironment>> & planet_environments,const boost::optional<parse::effects_group_payload> & effects,boost::optional<parse::detail::MovableEnvelope<Condition::Condition>> & combat_targets,const SpeciesParams & params,const SpeciesStuff & foci_preferred_tags_graphic,bool & pass)55 void insert_species( 56 std::map<std::string, std::unique_ptr<Species>>& species, 57 const SpeciesStrings& strings, 58 const boost::optional<std::map<PlanetType, PlanetEnvironment>>& planet_environments, 59 const boost::optional<parse::effects_group_payload>& effects, 60 boost::optional<parse::detail::MovableEnvelope<Condition::Condition>>& combat_targets, 61 const SpeciesParams& params, 62 const SpeciesStuff& foci_preferred_tags_graphic, 63 bool& pass) 64 { 65 auto species_ptr = std::make_unique<Species>( 66 strings, 67 (foci_preferred_tags_graphic.foci ? *foci_preferred_tags_graphic.foci : std::vector<FocusType>()), 68 (foci_preferred_tags_graphic.preferred_focus ? *foci_preferred_tags_graphic.preferred_focus : std::string()), 69 (planet_environments ? *planet_environments : std::map<PlanetType, PlanetEnvironment>()), 70 (effects ? OpenEnvelopes(*effects, pass) : std::vector<std::unique_ptr<Effect::EffectsGroup>>()), 71 (combat_targets ? (*combat_targets).OpenEnvelope(pass) : nullptr), 72 params, 73 foci_preferred_tags_graphic.tags, 74 foci_preferred_tags_graphic.graphic); 75 76 species.insert(std::make_pair(species_ptr->Name(), std::move(species_ptr))); 77 } 78 79 BOOST_PHOENIX_ADAPT_FUNCTION(void, insert_species_, insert_species, 8) 80 81 82 using start_rule_payload = std::pair< 83 std::map<std::string, std::unique_ptr<Species>>, // species_by_name 84 std::vector<std::string> // census ordering 85 >; 86 using start_rule_signature = void(start_rule_payload::first_type&); 87 88 struct grammar : public parse::detail::grammar<start_rule_signature> { grammar__anonf5bd12b80111::grammar89 grammar(const parse::lexer& tok, 90 const std::string& filename, 91 const parse::text_iterator& first, const parse::text_iterator& last) : 92 grammar::base_type(start), 93 condition_parser(tok, label), 94 string_grammar(tok, label, condition_parser), 95 tags_parser(tok, label), 96 effects_group_grammar(tok, label, condition_parser, string_grammar), 97 one_or_more_foci(focus_type), 98 planet_type_rules(tok, label, condition_parser), 99 planet_environment_rules(tok, label, condition_parser) 100 { 101 namespace phoenix = boost::phoenix; 102 namespace qi = boost::spirit::qi; 103 104 using phoenix::construct; 105 using phoenix::insert; 106 using phoenix::push_back; 107 108 qi::_1_type _1; 109 qi::_2_type _2; 110 qi::_3_type _3; 111 qi::_4_type _4; 112 qi::_5_type _5; 113 qi::_6_type _6; 114 qi::_7_type _7; 115 qi::_8_type _8; 116 qi::_9_type _9; 117 qi::_pass_type _pass; 118 qi::_r1_type _r1; 119 qi::_val_type _val; 120 qi::eps_type eps; 121 qi::matches_type matches_; 122 qi::omit_type omit_; 123 qi::as_string_type as_string_; 124 const boost::phoenix::function<parse::detail::deconstruct_movable> deconstruct_movable_; 125 126 focus_type 127 = ( omit_[tok.Focus_] 128 > label(tok.Name_) > tok.string 129 > label(tok.Description_) > tok.string 130 > label(tok.Location_) > condition_parser 131 > label(tok.Graphic_) > tok.string 132 ) [ _val = construct<FocusType>(_1, _2, deconstruct_movable_(_3, _pass), _4) ] 133 ; 134 135 foci 136 = label(tok.Foci_) 137 > one_or_more_foci 138 ; 139 140 environment_map_element 141 = ( label(tok.Type_) > planet_type_rules.enum_expr 142 > label(tok.Environment_) > planet_environment_rules.enum_expr 143 ) [ _val = construct<std::pair<PlanetType, PlanetEnvironment>>(_1, _2) ] 144 ; 145 146 environment_map 147 = ('[' > +environment_map_element [ insert(_val, _1) ] > ']') 148 | environment_map_element [ insert(_val, _1) ] 149 ; 150 151 species_params 152 = (matches_[tok.Playable_] 153 > matches_[tok.Native_] 154 > matches_[tok.CanProduceShips_] 155 > matches_[tok.CanColonize_] 156 ) [ _val = construct<SpeciesParams>(_1, _2, _4, _3) ] 157 ; 158 159 species_strings 160 = ( tok.Species_ 161 > label(tok.Name_) > tok.string 162 > label(tok.Description_) > tok.string 163 > label(tok.Gameplay_Description_) > tok.string 164 ) [ _pass = is_unique_(_r1, _1, _2), 165 _val = construct<SpeciesStrings>(_2, _3, _4) ] 166 ; 167 168 species 169 = ( species_strings(_r1)// _1 170 > species_params // _2 171 > tags_parser // _3 172 > -foci // _4 173 > -as_string_[(label(tok.PreferredFocus_) > tok.string )] // _5 174 > -(label(tok.EffectsGroups_) > effects_group_grammar) // _6 175 > -(label(tok.CombatTargets_) > condition_parser) // _7 176 > -(label(tok.Environments_) > environment_map) // _8 177 > label(tok.Graphic_) > tok.string // _9 178 ) [ insert_species_(_r1, _1, _8, _6, _7, _2, 179 construct<SpeciesStuff>(_4, _5, _3, _9), 180 _pass) ] 181 ; 182 183 start 184 = +species(_r1) 185 ; 186 187 focus_type.name("Focus"); 188 foci.name("Foci"); 189 environment_map_element.name("Type = <type> Environment = <env>"); 190 environment_map.name("Environments"); 191 species_params.name("Species Flags"); 192 species_strings.name("Species Strings"); 193 species.name("Species"); 194 start.name("start"); 195 196 #if DEBUG_PARSERS 197 debug(focus_type); 198 debug(foci); 199 debug(environment_map_element); 200 debug(environment_map); 201 debug(species_params); 202 debug(species_strings); 203 debug(species); 204 debug(start); 205 #endif 206 207 qi::on_error<qi::fail>(start, parse::report_error(filename, first, last, _1, _2, _3, _4)); 208 } 209 210 using focus_type_rule = parse::detail::rule<FocusType ()>; 211 using foci_rule = parse::detail::rule<std::vector<FocusType> ()>; 212 using environment_map_element_rule = parse::detail::rule<std::pair<PlanetType, PlanetEnvironment> ()>; 213 using environment_map_rule = parse::detail::rule<std::map<PlanetType, PlanetEnvironment> ()>; 214 using species_params_rule = parse::detail::rule<SpeciesParams ()>; 215 using species_strings_rule = parse::detail::rule<SpeciesStrings (const start_rule_payload::first_type&)>; 216 using species_rule = parse::detail::rule<void (start_rule_payload::first_type&)>; 217 using start_rule = parse::detail::rule<start_rule_signature>; 218 219 parse::detail::Labeller label; 220 const parse::conditions_parser_grammar condition_parser; 221 const parse::string_parser_grammar string_grammar; 222 parse::detail::tags_grammar tags_parser; 223 parse::effects_group_grammar effects_group_grammar; 224 foci_rule foci; 225 focus_type_rule focus_type; 226 parse::detail::single_or_bracketed_repeat<focus_type_rule> one_or_more_foci; 227 environment_map_element_rule environment_map_element; 228 environment_map_rule environment_map; 229 species_params_rule species_params; 230 species_strings_rule species_strings; 231 species_rule species; 232 start_rule start; 233 parse::detail::planet_type_parser_rules planet_type_rules; 234 parse::detail::planet_environment_parser_rules planet_environment_rules; 235 }; 236 237 using manifest_start_rule_signature = void (std::vector<std::string>&); 238 239 struct manifest_grammar : public parse::detail::grammar<manifest_start_rule_signature> { manifest_grammar__anonf5bd12b80111::manifest_grammar240 manifest_grammar(const parse::lexer& tok, 241 const std::string& filename, 242 const parse::text_iterator& first, const parse::text_iterator& last) : 243 manifest_grammar::base_type(start) 244 { 245 namespace phoenix = boost::phoenix; 246 namespace qi = boost::spirit::qi; 247 248 using phoenix::push_back; 249 250 qi::_1_type _1; 251 qi::_2_type _2; 252 qi::_3_type _3; 253 qi::_4_type _4; 254 qi::_r1_type _r1; 255 qi::omit_type omit_; 256 257 species_manifest 258 = omit_[tok.SpeciesCensusOrdering_] 259 > *(label(tok.Tag_) > tok.string [ push_back(_r1, _1) ]) 260 ; 261 262 start 263 = +species_manifest(_r1) 264 ; 265 266 species_manifest.name("ParsedSpeciesCensusOrdering"); 267 268 #if DEBUG_PARSERS 269 debug(species_manifest); 270 #endif 271 272 qi::on_error<qi::fail>(start, parse::report_error(filename, first, last, _1, _2, _3, _4)); 273 } 274 275 using manifest_rule = parse::detail::rule<void (std::vector<std::string>&)>; 276 using start_rule = parse::detail::rule<manifest_start_rule_signature>; 277 278 parse::detail::Labeller label; 279 manifest_rule species_manifest; 280 start_rule start; 281 }; 282 } 283 284 namespace parse { species(const boost::filesystem::path & path)285 start_rule_payload species(const boost::filesystem::path& path) { 286 const lexer lexer; 287 start_rule_payload::first_type species_; 288 start_rule_payload::second_type ordering; 289 290 boost::filesystem::path manifest_file; 291 292 for (const auto& file : ListDir(path, IsFOCScript)) { 293 if (file.filename() == "SpeciesCensusOrdering.focs.txt" ) { 294 manifest_file = file; 295 continue; 296 } 297 298 /*auto success =*/ detail::parse_file<grammar, start_rule_payload::first_type>(lexer, file, species_); 299 } 300 301 if (!manifest_file.empty()) { 302 try { 303 /*auto success =*/ detail::parse_file<manifest_grammar, start_rule_payload::second_type>( 304 lexer, manifest_file, ordering); 305 306 } catch (const std::runtime_error& e) { 307 ErrorLogger() << "Failed to species census manifest in " << manifest_file << " from " << path 308 << " because " << e.what(); 309 } 310 } 311 312 return {std::move(species_), ordering}; 313 } 314 } 315