【发布时间】:2020-10-05 23:05:13
【问题描述】:
我正在尝试编写一个可以像 DnD、Munchkin 等一样掷骰子的计算器。所以我需要计算像 2*(2d5+3d7) 这样的表达式,其中我应该 2d5 代表用 5 个面掷出 2 个骰子的结果。我以一个原始计算器为基础,它可以工作。现在我正在尝试使用语义操作添加滚动规则。每次出现表达式 XdY 时,我都想调用 roll 函数并将其结果添加到当前值。但似乎我不能只在语义动作中做_val+=roll(dice_number, dice_value)。那么,这样做的方法是什么?完整代码在这里:
#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/bind.hpp>
#include <boost/phoenix/bind/bind_function.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <boost/random.hpp>
std::time_t now = std::time(0);
boost::random::mt19937 gen{static_cast<std::uint32_t>(now)};
int roll(int dice_number, int dice_value, int use_crits=false)
{
int res=0;
boost::random::uniform_int_distribution<> dist{1, value};
for(int i=0; i<dice_number; i++)
{
res+=dist(gen);
}
return res;
}
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
using boost::phoenix::push_back;
using boost::phoenix::ref;
//calculator grammar
template <typename Iterator>
struct calculator : qi::grammar<Iterator, int(), ascii::space_type>
{
calculator() : calculator::base_type(expression)
{
qi::_val_type _val;
qi::_1_type _1, _2;
qi::uint_type uint_;
qi::int_type int_;
int dice_num, dice_value;
roll =
(int_ [ref(dice_num)=_1]>> 'd' >> int_ [ref(dice_value)=_1]) [_val+=roll(dice_num, dice_value)] ;//The problem is here
expression =
term [_val = _1]
>> *( ('+' >> term [_val += _1])
| ('-' >> term [_val -= _1])
)
;
term =
factor [_val = _1]
>> *( ('*' >> factor [_val *= _1])
| ('/' >> factor [_val /= _1])
)
;
factor =
roll [_val=_1]
| uint_ [_val = _1]
| '(' >> expression [_val = _1] >> ')'
| ('-' >> factor [_val = -_1])
| ('+' >> factor [_val = _1])
;
}
qi::rule<Iterator, int(), ascii::space_type> roll, expression, term, factor;
};
}
int
main()
{
std::cout << "/////////////////////////////////////////////////////////\n\n";
std::cout << "Expression parser...\n\n";
std::cout << "/////////////////////////////////////////////////////////\n\n";
std::cout << "Type an expression...or [q or Q] to quit\n\n";
typedef std::string::const_iterator iterator_type;
typedef client::calculator<iterator_type> calculator;
boost::spirit::ascii::space_type space; // skipper
calculator calc; // grammar
std::string str;
int result;
while (std::getline(std::cin, str))
{
if (str.empty() || str[0] == 'q' || str[0] == 'Q')
break;
std::string::const_iterator iter = str.begin();
std::string::const_iterator end = str.end();
bool r = phrase_parse(iter, end, calc, space, result);
if (r && iter == end)
{
std::cout << "-------------------------\n";
std::cout << "Parsing succeeded\n";
std::cout << "result = " << result << std::endl;
std::cout << "-------------------------\n";
}
else
{
std::string rest(iter, end);
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "stopped at: \" " << rest << "\"\n";
std::cout << "-------------------------\n";
}
}
std::cout << "Bye... :-) \n\n";
return 0;
}
【问题讨论】:
标签: c++ boost boost-spirit boost-spirit-qi