::提振精神::齐定义nullaries计算器 [英] Boost::spirit::qi defining a calculator for nullaries
问题描述
我试图写数学EX pressions那里命名变量在的boost ::精神
(版本1_51_0)nullaries解析器,而我'中号全新的。我定义的typedef的boost ::功能<双()>值
和我的规则将被宣布像这样:齐::规则<迭代器,价值()>前pression,期限,其他人,...;
I'm trying to write a parser for math expressions where named variables are nullaries in boost::spirit
(version 1_51_0), to which I'm completely new. I define typedef boost::function<double()> Value
and my rules will be declared like so: qi::rule<Iterator, Value()> expression, term, others, ...;
我在定义二元nullaries运营这个宏
I define binary operators on nullaries with this macro
#define BINARY_FUNCTOR(name, op) \
struct name \
{ \
name(Value x, Value y): x_(x), y_(y) {} \
double operator()() { return x_() op y_(); } \
Value x_, y_; \
};
和具有添加
, SUB
等,从我所看到的例子,我期望的是这样定义的规则:
and have ADD
, SUB
, etc. From the examples I've seen, I'd expect the rules to be defined like this:
expression = term
>> *( (lit('+') >> term[ADD(_val, _1)])
| (lit('-') >> term[SUB(_val, _1)])
);
但似乎并没有被正确的语法,因为我得到一个错误
but that doesn't seem to be the right syntax, as I get an error
boost/spirit/home/support/action_dispatch.hpp:162: error: no match for call to ‘(const<unnamed>::SUB) (boost::function<double ()()>&, boost::spirit::context<boost::fusion::cons<boost::function<double ()()>&, boost::fusion::nil>, boost::fusion::vector0<void> >&, bool&)’
SRParser.cpp:38: note: candidates are: double<unnamed>::SUB::operator()()
这在我看来就像 _1
不完全是我希望它是,即相关的值
下一个任期。什么是这样定义的规则正确的语法?
which looks to me like _1
isn't quite what I expect it to be, namely the Value
associated with the next term. What's the right syntax to define a rule like this?
推荐答案
解析器前pression看起来还好。
The parser expression looks okay.
你所困惑过上构建AST。显然,你已经决定使用语义动作这样做,但你的努力过于简略,我看到的只是如何(甚至是决定什么样你在这个基础)。
What you are confused over is on constructing the AST. Apparently, you have decided to use Semantic Actions to do so, but your effort is too sketchy for me to see just how (or even decide what sample you are basing this on).
在本质:它是什么,你想要的做的与你似乎的神奇的意志到你的规则添加/SUB的实例?
In essence: What is it that you want to do with the instances of 'ADD'/'SUB' that you seem to magically "will" into your rules?
现在,您只需使用的实例的直接的作为语义动作。这将导致显示的错误信息,它告诉你,直接,该实例的无效的作为语义动作。
Right now, you just use the instance directly as a semantic action. This leads to the error message shown, which tells you, directly, that the instance is not valid as a semantic action.
我假设你真的想用凤凰分配给二元运算分配给暴露的属性,来代替。这看起来像:
I assume you really wanted to use Phoenix assignment to assign the binary operation to the exposed attribute, instead. This looks like:
expression = term
>> *( (lit('+') >> term[ _val = phx::construct<ADD>(_val, _1)])
| (lit('-') >> term[ _val = phx::construct<SUB>(_val, _1)])
);
您会看到这与传统的前pression语法更紧密地匹配。
You'll see this matches much more closely with traditional expression grammars.
为了好玩我适应根据您的值一个完整的前pression解析器
键入并创造了这个工作演示: <一个href=\"http://liveworkspace.org/$c$c/3kgPJR%240\">http://liveworkspace.org/$c$c/3kgPJR$0
For fun I adapted a complete expression parser based on your Value
type and created this working demonstration: http://liveworkspace.org/code/3kgPJR$0
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
typedef std::function<double()> Value;
#define BINARY_FUNCTOR(name, op) \
struct name \
{ \
name(Value x, Value y): x_(x), y_(y) {} \
double operator()() { return x_() op y_(); } \
Value x_, y_; \
};
BINARY_FUNCTOR(ADD, +)
BINARY_FUNCTOR(SUB, -)
BINARY_FUNCTOR(MUL, *)
BINARY_FUNCTOR(DIV, /)
struct LIT
{
LIT(double x): x_(x) {}
double operator()() { return x_; }
double x_;
};
struct NEG
{
NEG(Value x): x_(x) {}
double operator()() { return -x_(); }
Value x_;
};
template <typename It, typename Skipper = qi::space_type>
struct parser : qi::grammar<It, Value(), Skipper>
{
parser() : parser::base_type(expression)
{
using namespace qi;
expression =
term [_val = _1]
>> *( ('+' >> term [_val = phx::construct<ADD>(_val, _1)])
| ('-' >> term [_val = phx::construct<SUB>(_val, _1)])
);
term =
factor [_val = _1]
>> *( ('*' >> factor [_val = phx::construct<MUL>(_val, _1)])
| ('/' >> factor [_val = phx::construct<DIV>(_val, _1)])
);
factor =
double_ [_val = phx::construct<LIT>(_1)]
| '(' >> expression [_val = _1] >> ')'
| ('-' >> factor [_val = phx::construct<NEG>(_1)])
| ('+' >> factor [_val = _1]);
BOOST_SPIRIT_DEBUG_NODE(expression);
BOOST_SPIRIT_DEBUG_NODE(term);
BOOST_SPIRIT_DEBUG_NODE(factor);
}
private:
qi::rule<It, Value(), Skipper> expression, term, factor;
};
Value doParse(const std::string& input)
{
typedef std::string::const_iterator It;
parser<It, qi::space_type> p;
Value eval;
auto f(begin(input)), l(end(input));
if (!qi::phrase_parse(f,l,p,qi::space,eval))
std::cerr << "parse failed: '" << std::string(f,l) << "'\n";
if (f!=l)
std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
return eval;
}
int main()
{
auto area = doParse("2 * (3.1415927 * (10*10))");
std::cout << "Area of a circle r=10: " << area() << "\n";
}
这将打印
Area of a circle r=10: 628.319
这篇关于::提振精神::齐定义nullaries计算器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!