From: <geo...@us...> - 2012-10-02 18:08:05
|
Revision: 5273 http://freeorion.svn.sourceforge.net/freeorion/revision/?rev=5273&view=rev Author: geoffthemedio Date: 2012-10-02 18:07:54 +0000 (Tue, 02 Oct 2012) Log Message: ----------- Partial rewrite of ValueRef parsing to simplify code a bit, and to add support for exponentiation with the ^ operator, support for several utility functions: sin, cos, log, min, and max, which take one or two parameters; and support for a random number generator (distinct from the Random condution) which operates as a function taking two parameters. Modified Paths: -------------- trunk/FreeOrion/parse/Double.h trunk/FreeOrion/parse/DoubleValueRefParser.cpp trunk/FreeOrion/parse/Int.h trunk/FreeOrion/parse/IntValueRefParser.cpp trunk/FreeOrion/parse/ValueRefParser.h trunk/FreeOrion/parse/ValueRefParserImpl.h trunk/FreeOrion/universe/Names.h Modified: trunk/FreeOrion/parse/Double.h =================================================================== --- trunk/FreeOrion/parse/Double.h 2012-10-01 16:14:40 UTC (rev 5272) +++ trunk/FreeOrion/parse/Double.h 2012-10-02 18:07:54 UTC (rev 5273) @@ -7,7 +7,6 @@ #include <boost/spirit/include/qi.hpp> namespace parse { - typedef boost::spirit::qi::rule< parse::token_iterator, double (), @@ -15,7 +14,6 @@ > double_parser_rule; extern double_parser_rule double_; - } #endif Modified: trunk/FreeOrion/parse/DoubleValueRefParser.cpp =================================================================== --- trunk/FreeOrion/parse/DoubleValueRefParser.cpp 2012-10-01 16:14:40 UTC (rev 5272) +++ trunk/FreeOrion/parse/DoubleValueRefParser.cpp 2012-10-02 18:07:54 UTC (rev 5273) @@ -1,10 +1,11 @@ #include "ValueRefParserImpl.h" -#include "Double.h" +//#include "Double.h" +//#include <GG/ReportParseError.h> -#include <GG/ReportParseError.h> +//extern name_token_rule first_token; // in IntValueRefParser.cpp +//extern name_token_rule container_token; // in IntValueRefParser.cpp - namespace { struct double_parser_rules { double_parser_rules() { @@ -18,7 +19,7 @@ const parse::lexer& tok = parse::lexer::instance(); final_token - %= tok.Industry_ + = tok.Industry_ | tok.TargetIndustry_ | tok.Research_ | tok.TargetResearch_ @@ -50,7 +51,8 @@ ; constant - = parse::double_ [ _val = new_<ValueRef::Constant<double> >(_1) ] + = tok.int_ [ _val = new_<ValueRef::Constant<double> >(static_cast_<double>(_1)) ] + | tok.double_ [ _val = new_<ValueRef::Constant<double> >(_1) ] ; variable @@ -80,7 +82,8 @@ initialize_numeric_statistic_parser<double>(statistic, final_token); - initialize_expression_parsers<double>(negate_expr, + initialize_expression_parsers<double>(function_expr, + exponential_expr, multiplicative_expr, additive_expr, expr, @@ -91,21 +94,24 @@ ; primary_expr - %= '(' > expr > ')' - | constant - | variable - | int_statistic - | statistic + = '(' > expr > ')' + | constant + | variable + | int_statistic + | statistic ; final_token.name("real number variable name (e.g., Growth)"); - constant.name("real number"); + constant.name("real number constant"); + + variable.name("real number variable"); statistic.name("real number statistic"); int_statistic.name("integer statistic"); - negate_expr.name("real number or real number expression"); - multiplicative_expr.name("real number or real number expression"); - additive_expr.name("real number or real number expression"); + function_expr.name("real number function expression"); + exponential_expr.name("real number exponential expression"); + multiplicative_expr.name("real number multiplication expression"); + additive_expr.name("real number additive expression"); expr.name("real number expression"); primary_expr.name("real number expression"); @@ -126,19 +132,19 @@ typedef parse::value_ref_parser_rule<double>::type rule; typedef variable_rule<double>::type variable_rule; typedef statistic_rule<double>::type statistic_rule; - typedef multiplicative_expr_rule<double>::type multiplicative_expression_rule; - typedef additive_expr_rule<double>::type additive_expression_rule; + typedef expression_rule<double>::type expression_rule; - name_token_rule final_token; - rule constant; - variable_rule variable; - statistic_rule statistic; - rule int_statistic; - rule negate_expr; - multiplicative_expression_rule multiplicative_expr; - additive_expression_rule additive_expr; - rule expr; - rule primary_expr; + name_token_rule final_token; + rule constant; + variable_rule variable; + statistic_rule statistic; + rule int_statistic; + expression_rule function_expr; + expression_rule exponential_expr; + expression_rule multiplicative_expr; + expression_rule additive_expr; + rule expr; + rule primary_expr; }; double_parser_rules& get_double_parser_rules() { Modified: trunk/FreeOrion/parse/Int.h =================================================================== --- trunk/FreeOrion/parse/Int.h 2012-10-01 16:14:40 UTC (rev 5272) +++ trunk/FreeOrion/parse/Int.h 2012-10-02 18:07:54 UTC (rev 5273) @@ -7,7 +7,6 @@ #include <boost/spirit/include/qi.hpp> namespace parse { - typedef boost::spirit::qi::rule< parse::token_iterator, int (), @@ -15,7 +14,6 @@ > int_parser_rule; extern int_parser_rule int_; - } #endif Modified: trunk/FreeOrion/parse/IntValueRefParser.cpp =================================================================== --- trunk/FreeOrion/parse/IntValueRefParser.cpp 2012-10-01 16:14:40 UTC (rev 5272) +++ trunk/FreeOrion/parse/IntValueRefParser.cpp 2012-10-02 18:07:54 UTC (rev 5273) @@ -1,6 +1,6 @@ #include "ValueRefParserImpl.h" -#include <GG/ReportParseError.h> +//#include <GG/ReportParseError.h> name_token_rule first_token; @@ -10,12 +10,8 @@ struct int_parser_rules { int_parser_rules() { qi::_1_type _1; - qi::_2_type _2; - qi::_3_type _3; - qi::_4_type _4; qi::_a_type _a; qi::_val_type _val; - qi::lit_type lit; using phoenix::new_; using phoenix::push_back; using phoenix::static_cast_; @@ -23,45 +19,45 @@ const parse::lexer& tok = parse::lexer::instance(); first_token - %= tok.Source_ - | tok.Target_ - | tok.LocalCandidate_ - | tok.RootCandidate_ + = tok.Source_ + | tok.Target_ + | tok.LocalCandidate_ + | tok.RootCandidate_ ; container_token - %= tok.Planet_ - | tok.System_ - | tok.Fleet_ + = tok.Planet_ + | tok.System_ + | tok.Fleet_ ; // TODO: Should we apply elements of this list only to certain // containers? For example, if one writes "Source.Planet.", // "NumShips" should not follow. final_token - %= tok.Owner_ - | tok.ID_ - | tok.CreationTurn_ - | tok.Age_ - | tok.ProducedByEmpireID_ - | tok.DesignID_ - | tok.FleetID_ - | tok.PlanetID_ - | tok.SystemID_ - | tok.FinalDestinationID_ - | tok.NextSystemID_ - | tok.PreviousSystemID_ - | tok.NumShips_ - | tok.LastTurnBattleHere_ + = tok.Owner_ + | tok.ID_ + | tok.CreationTurn_ + | tok.Age_ + | tok.ProducedByEmpireID_ + | tok.DesignID_ + | tok.FleetID_ + | tok.PlanetID_ + | tok.SystemID_ + | tok.FinalDestinationID_ + | tok.NextSystemID_ + | tok.PreviousSystemID_ + | tok.NumShips_ + | tok.LastTurnBattleHere_ ; constant - = tok.double_ [ _val = new_<ValueRef::Constant<int> >(static_cast_<int>(_1)) ] - | tok.int_ [ _val = new_<ValueRef::Constant<int> >(_1) ] + = tok.double_ [ _val = new_<ValueRef::Constant<int> >(static_cast_<int>(_1)) ] + | tok.int_ [ _val = new_<ValueRef::Constant<int> >(_1) ] ; variable - = ( + = ( ( first_token [ push_back(_a, _1) ] > '.' > -(container_token [ push_back(_a, _1) ] > '.') @@ -79,28 +75,36 @@ initialize_numeric_statistic_parser<int>(statistic, final_token); - initialize_expression_parsers<int>(negate_expr, - multiplicative_expr, - additive_expr, - expr, - primary_expr); + initialize_expression_parsers<int>(function_expr, + exponential_expr, + multiplicative_expr, + additive_expr, + expr, + primary_expr); + //double_statistic + // = double_var_statistic() [ _val = new_<ValueRef::StaticCast<double, int> >(_1) ] + // ; + primary_expr - %= '(' > expr > ')' - | constant - | variable - | statistic + = '(' > expr > ')' + | constant + | variable + //| double_statistic + | statistic ; first_token.name("Source, Target, LocalCandidate, or RootCandidate"); container_token.name("Planet, System, or Fleet"); final_token.name("integer variable name (e.g., FleetID)"); - constant.name("integer"); + constant.name("integer constant"); variable.name("integer variable"); statistic.name("integer statistic"); - negate_expr.name("integer or integer expression"); - multiplicative_expr.name("integer or integer expression"); - additive_expr.name("integer or integer expression"); + //double_statistic.name("real number statistic"); + function_expr.name("integer function expression"); + exponential_expr.name("integer exponential expression"); + multiplicative_expr.name("integer multiplication expression"); + additive_expr.name("integer additive expression"); expr.name("integer expression"); primary_expr.name("integer expression"); @@ -120,20 +124,21 @@ } typedef parse::value_ref_parser_rule<int>::type rule; - typedef variable_rule<int>::type variable_rule; - typedef statistic_rule<int>::type statistic_rule; - typedef multiplicative_expr_rule<int>::type multiplicative_expression_rule; - typedef additive_expr_rule<int>::type additive_expression_rule; + typedef variable_rule<int>::type variable_rule; + typedef statistic_rule<int>::type statistic_rule; + typedef expression_rule<int>::type expression_rule; - name_token_rule final_token; - rule constant; - variable_rule variable; - statistic_rule statistic; - rule negate_expr; - multiplicative_expression_rule multiplicative_expr; - additive_expression_rule additive_expr; - rule expr; - rule primary_expr; + name_token_rule final_token; + rule constant; + variable_rule variable; + statistic_rule statistic; + //rule double_statistic; + expression_rule function_expr; + expression_rule exponential_expr; + expression_rule multiplicative_expr; + expression_rule additive_expr; + rule expr; + rule primary_expr; }; int_parser_rules& get_int_parser_rules() { Modified: trunk/FreeOrion/parse/ValueRefParser.h =================================================================== --- trunk/FreeOrion/parse/ValueRefParser.h 2012-10-01 16:14:40 UTC (rev 5272) +++ trunk/FreeOrion/parse/ValueRefParser.h 2012-10-02 18:07:54 UTC (rev 5273) @@ -15,7 +15,7 @@ typedef boost::spirit::qi::rule< parse::token_iterator, // TODO: Investigate refactoring ValueRef to use variant, for increased locality of reference. - ValueRef::ValueRefBase<T>* (), // TODO: Rename this ValueRef::Base in the FO code. + ValueRef::ValueRefBase<T>* (), parse::skipper_type > type; }; @@ -47,7 +47,6 @@ template <> value_ref_parser_rule<StarType>::type& value_ref_parser<StarType>(); - } #endif Modified: trunk/FreeOrion/parse/ValueRefParserImpl.h =================================================================== --- trunk/FreeOrion/parse/ValueRefParserImpl.h 2012-10-01 16:14:40 UTC (rev 5272) +++ trunk/FreeOrion/parse/ValueRefParserImpl.h 2012-10-02 18:07:54 UTC (rev 5273) @@ -50,130 +50,132 @@ qi::locals< std::vector<adobe::name_t>, ValueRef::StatisticType, - Condition::ConditionBase* // TODO: Change spelling to Condition::Base in the universe code. + Condition::ConditionBase* >, parse::skipper_type > type; }; template <typename T> -struct operator_or_operand -{ typedef boost::variant<ValueRef::OpType, ValueRef::ValueRefBase<T>*> type; }; - -template <typename T> -struct operator_or_operand_vector -{ typedef std::vector<typename operator_or_operand<T>::type> type; }; - -template <typename T> -struct expression_value_type; - -template <typename T> -struct expression_value_type<std::vector<boost::variant<ValueRef::OpType, ValueRef::ValueRefBase<T>*> > > -{ typedef T type; }; - -template <typename T> -struct multiplicative_expr_rule +struct expression_rule { typedef qi::rule< parse::token_iterator, - void (typename operator_or_operand_vector<T>::type&), - qi::locals<ValueRef::OpType>, - parse::skipper_type - > type; -}; - -template <typename T> -struct additive_expr_rule -{ - typedef qi::rule< - parse::token_iterator, ValueRef::ValueRefBase<T>* (), qi::locals< - typename operator_or_operand_vector<T>::type, + ValueRef::ValueRefBase<T>*, + ValueRef::ValueRefBase<T>*, ValueRef::OpType >, parse::skipper_type > type; }; -struct make_expression_ { - template <typename Arg> - struct result - { typedef ValueRef::ValueRefBase<typename expression_value_type<Arg>::type>* type; }; - - template <typename Arg> - typename result<Arg>::type operator()(const Arg& arg) const - { - typedef typename expression_value_type<Arg>::type value_type; - std::vector<ValueRef::ValueRefBase<value_type>*> operand_stack; - operand_stack.reserve(arg.size()); - const typename Arg::const_iterator end_it = arg.end(); - for (typename Arg::const_iterator it = arg.begin(); it != end_it; ++it) { - if (const ValueRef::OpType* op = boost::get<ValueRef::OpType>(&*it)) { // operator - ValueRef::ValueRefBase<value_type>* right = operand_stack.back(); - operand_stack.pop_back(); - ValueRef::ValueRefBase<value_type>* left = operand_stack.back(); - operand_stack.pop_back(); - // TODO: Constant folding. - operand_stack.push_back(new ValueRef::Operation<value_type>(*op, left, right)); - } else { - operand_stack.push_back(boost::get<ValueRef::ValueRefBase<value_type>*>(*it)); - } - } - return operand_stack[0]; - } -}; -const boost::phoenix::function<make_expression_> make_expression; - template <typename T> void initialize_expression_parsers( - typename parse::value_ref_parser_rule<T>::type& negate_expr, - typename multiplicative_expr_rule<T>::type& multiplicative_expr, - typename additive_expr_rule<T>::type& additive_expr, - typename parse::value_ref_parser_rule<T>::type& expr, - typename parse::value_ref_parser_rule<T>::type& primary_expr ) + typename expression_rule<T>::type& function_expr, + typename expression_rule<T>::type& exponential_expr, + typename expression_rule<T>::type& multiplicative_expr, + typename expression_rule<T>::type& additive_expr, + typename parse::value_ref_parser_rule<T>::type& expr, + typename parse::value_ref_parser_rule<T>::type& primary_expr ) { qi::_1_type _1; qi::_a_type _a; qi::_b_type _b; + qi::_c_type _c; qi::_r1_type _r1; qi::_val_type _val; qi::lit_type lit; using phoenix::new_; using phoenix::push_back; - negate_expr - = '-' > primary_expr [ _val = new_<ValueRef::Operation<T> >(ValueRef::NEGATE, _1) ] - | primary_expr [ _val = _1 ] + const parse::lexer& tok = parse::lexer::instance(); + + function_expr + = ( + ( + ( + tok.Sin_ [ _c = ValueRef::SINE ] + | tok.Cos_ [ _c = ValueRef::COSINE ] + | tok.Log_ [ _c = ValueRef::LOGARITHM ] + ) + >> '(' > expr [ _val = new_<ValueRef::Operation<T> >(_c, _1) ] > ')' + ) + | ( + ( + tok.Min_ [ _c = ValueRef::MINIMUM ] + | tok.Max_ [ _c = ValueRef::MAXIMUM ] + | tok.Random_ [ _c = ValueRef::RANDOM_UNIFORM ] + ) + >> '(' > expr [ _a = _1 ] > ',' + > expr [ _val = new_<ValueRef::Operation<T> >(_c, _a, _1) ] > ')' + ) + | ( + primary_expr [ _val = _1 ] + ) + ) ; + exponential_expr + = ( + function_expr [ _a = _1 ] + >> '^' > function_expr + [ _val = new_<ValueRef::Operation<T> >( ValueRef::EXPONENTIATE, _a, _1 ) ] + ) + | function_expr [ _val = _1 ] + ; + multiplicative_expr - = negate_expr [ push_back(_r1, _1) ] - >> *( - ( - lit('*') [ _a = ValueRef::TIMES ] - | lit('/') [ _a = ValueRef::DIVIDE ] - ) - > negate_expr [ push_back(_r1, _1) ] - ) [ push_back(_r1, _a) ] + = ( + exponential_expr [ _a = _1 ] + > ( + *( + ( + ( + lit('*') [ _c = ValueRef::TIMES ] + | lit('/') [ _c = ValueRef::DIVIDE ] + ) + > exponential_expr [ _b = new_<ValueRef::Operation<T> >(_c, _a, _1) ] + ) [ _a = _b ] + ) + ) + ) + [ _val = _a ] ; additive_expr - = ( - multiplicative_expr(_a) - >> *( - ( - lit('+') [ _b = ValueRef::PLUS ] - | lit('-') [ _b = ValueRef::MINUS ] - ) - > multiplicative_expr(_a) - ) [ push_back(_a, _b) ] - ) - [ _val = make_expression(_a) ] + = + ( + ( + ( + multiplicative_expr [ _a = _1 ] + > ( + *( + ( + ( + lit('+') [ _c = ValueRef::PLUS ] + | lit('-') [ _c = ValueRef::MINUS ] + ) + > multiplicative_expr [ _b = new_<ValueRef::Operation<T> >(_c, _a, _1) ] + ) [ _a = _b ] + ) + ) + ) + [ _val = _a ] + ) + | ( + lit('-') > multiplicative_expr + [ _val = new_<ValueRef::Operation<T> >(ValueRef::NEGATE, _1) ] + ) + | ( + multiplicative_expr [ _val = _1 ] + ) + ) ; expr - %= additive_expr + = additive_expr ; } Modified: trunk/FreeOrion/universe/Names.h =================================================================== --- trunk/FreeOrion/universe/Names.h 2012-10-01 16:14:40 UTC (rev 5272) +++ trunk/FreeOrion/universe/Names.h 2012-10-02 18:07:54 UTC (rev 5273) @@ -55,6 +55,7 @@ (Construction) \ (ContainedBy) \ (Contains) \ + (Cos) \ (Count) \ (CounterClockwiseNextPlanetType) \ (CreateBuilding) \ @@ -136,6 +137,7 @@ (LaunchRate) \ (LocalCandidate) \ (Location) \ + (Log) \ (Low) \ (Max) \ (MaxDefense) \ @@ -294,6 +296,7 @@ (Ships) \ (Short_Description) \ (ShortRange) \ + (Sin) \ (Size) \ (SizeAsDouble) \ (Slot) \ |