::提振精神::齐定义nullaries计算器 [英] Boost::spirit::qi defining a calculator for nullaries

查看:186
本文介绍了::提振精神::齐定义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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆