如何使用boost ::精神,以验证的代数声明? [英] How to verify algebraic statements using boost::spirit?

查看:145
本文介绍了如何使用boost ::精神,以验证的代数声明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图延长计算器例如中,使,而不是分析和评估代数前pression,解析器会确定的代数陈述是真还是假。我的意思是一样的语句 1 + 5 * 5 - 10 = 19 - 3 (期望解析器的结果是真正)和 3 - 1 = 9 (期望解析器的结果是

I'm trying to extend the calculator example so that instead of parsing and evaluating an algebraic expression, the parser will determine if an algebraic statement is true or not. By this I mean statements like 1 + 5 * 5 - 10 = 19 - 3 (desired parser result is true) and 3 - 1 = 9 (desired parser result is false).

我得承认,我是新来的的boost ::精神和它的各种此刻压倒。不过,我觉得我理解的计算器例子不够好,至少取得一些进展。

I've got to admit I'm new to boost::spirit and it's all kind of overwhelming at the moment. However, I do feel I understand the calculator example good enough to at least make some headway.

使用所提供的示例作为出发点,语法如下:

Using the provided example as a starting point, the grammar looks like this:

calculator() : calculator::base_type(expression)
{
    using qi::uint_;
    using qi::_val;
    using qi::_1;

    expression =
        term                    [_val = _1]
            >> *( ('+' >> term  [_val = _val + _1])
                | ('-' >> term  [_val = _val - _1])
                );

        term =
            factor                [_val = _1]
            >> *( ('*' >> factor  [_val = _val * _1])
                | ('/' >> factor  [_val = _val / _1])
                );

        factor =
            uint_                 [_val = _1]
            |   '(' >> expression [_val = _1] >> ')'
            |   ('-' >> factor    [_val = -_1])
            |   ('+' >> factor    [_val = _1]);
}

在那里我已经放弃了调试宏简洁。

where I've dropped the debug macros for brevity.

要限制问题的范围,我决定只允许每条语句一个等号。由于它是没有意义的(至少在一个普通意义上)有平等的迹象出现一个封闭的圆括号内,我已经决定不让括号无论是。这简化了系数 -parser通过允许去除可选的(制造>>前pression [_val = _1] GT ;方式>')

To limit the scope of the problem, I've decided to allow only a single equality sign per statement. As it is meaningless (at least in a regular sense) to have equality signs appear inside a closed pair of parentheses, I've decided not to allow parentheses either. This simplifies the factor-parser by permitting the removal of the optional '(' >> expression [_val = _1] >> ')'.

在这一点上我有点卡住了。首先,我需要解析器接受一个等号。其次,我需要的语义动作来评价左侧(左)和语句的右手边(RHS)个人,最后才进行比较(或所以这是什么,我认为要做的需求)。

At this point I'm a little stuck. First of all, I need the parser to accept a single equality sign. Secondly, I need the semantic actions to evaluate the left hand side (LHS) and the right hand side (RHS) of the statement individually, before finally performing a comparison (or so this is what I think needs to be done).

我想知道如果最简单的方法是构建两个独立的分析程序,一个LHS和一个RHS,由第三解析器匹配等号分开。两个解析器LHS及RHS应该是相同的,除了语义动作而,很显然,需要对于这些最终相比的输入分成两个不同的类别,以便

I am wondering if the easiest approach would be to construct two separate parsers, one LHS and one RHS, separated by a third parser matching the equality sign. The two parsers LHS and RHS should be identical, except for the semantic action which, clearly, need to separate the input into two different categories in order for these to finally be compared.

试着写两个单独的解析器LHS和RHS之前,我想了解如何修改原来的解析器,以便它在存储前评估pressions在一个局部变量。 (我甚至不知道这将是任何地方可行的道路,但它似乎是朝着正确方向迈出的一步。)

Before trying to write two separate parsers LHS and RHS, I wanted to learn how to modify the original parser so that it stored the evaluated expressions in a local variable. (I'm not even sure that would be a viable path to anywhere, but it seems like a step in the right direction.)

这是我的尝试:

int result;

expression =
    term                            [result = _1]
    >> *(   ('+' >> term            [result = result + _1])
        |   ('-' >> term            [result = result - _1])
        );

但是这使得我的编译器(苹果LLVM编译器4.2,X code 4.6)想怎么样,我大叫了

but this makes my compiler (Apple LLVM compiler 4.2, Xcode 4.6) go nuts, yelling at me that

指定由不兼容的类型'诠释'常量_1_type(又名常量
  演员<参数< 0>>')

Assigning to 'int' from incompatible type 'const _1_type' (aka 'const actor< argument < 0 > >')

在事后看来,这使得课程的意义,因为 _val 从来没有必然 INT 在首位(毕竟解析器AFAIU应该是通用的)。换句话说,我需要弄清楚如何定义用于临时存储评估解析的前pression类型。

In hindsight, this makes sense of course, since _val was never bound to int in the first place (after all, the parsers are AFAIU supposed to be generic). In other words, I need to figure out how to define the type to use for temporary storing the evaluated parsed expression.

现在的问题是:任何人都可以给我一个正确的方向轻推?在是否和LHS RHS拆分看起来要走的路?

The question is: can anyone give me a nudge in the right direction? Does the split in LHS and RHS seem like the way to go?

任何建议大大AP preciated!

Any suggestion is greatly appreciated!

推荐答案

这可以工作,如果你问我会 <一个最简单的事情href=\"http://liveworkspace.org/$c$c/1fvc8x%240\">http://liveworkspace.org/$c$c/1fvc8x$0

The simplest thing that could work, if you ask me would be http://liveworkspace.org/code/1fvc8x$0

equation = (expression >> "=" >> expression) [ _val = _1 == _2 ];

这将解析两位前pressions,返回的属性是布尔,表示这两个前pressions是否评估,以相同的值。

This will parse two expressions, and the returned attribute is a bool that indicates whether both expressions evaluated to the same value.

演示程序

int main()
{
    doParse("1 + 2 * 3 = 7");
    doParse("1 + 2 * 3 = 8");
}

打印

parse success
result: true
parse success
result: false

示例程序

#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi    = boost::spirit::qi;
namespace phx   = boost::phoenix;

typedef unsigned attr_t;

template <typename It, typename Skipper = qi::space_type>
    struct calculator : qi::grammar<It, bool(), Skipper>
{
    calculator() : calculator::base_type(equation)
    {
        using qi::uint_;
        using qi::_val;
        using qi::_1;
        using qi::_2;

        equation = (expression >> "=" >> expression) [ _val = _1 == _2 ];

        expression =
            term                    [_val = _1]
                >> *( ('+' >> term  [_val = _val + _1])
                    | ('-' >> term  [_val = _val - _1])
                    );

            term =
                factor                [_val = _1]
                >> *( ('*' >> factor  [_val = _val * _1])
                    | ('/' >> factor  [_val = _val / _1])
                    );

            factor =
                uint_                 [_val = _1]
                |   '(' >> expression [_val = _1] >> ')'
                |   ('-' >> factor    [_val = -_1])
                |   ('+' >> factor    [_val = _1]);
    }

  private:
    qi::rule<It, unsigned(), Skipper> expression, term, factor;
    qi::rule<It, bool(), Skipper> equation;
};

bool doParse(const std::string& input)
{
    typedef std::string::const_iterator It;
    auto f(begin(input)), l(end(input));

    calculator<It, qi::space_type> p;
    bool result;

    try
    {
        bool ok = qi::phrase_parse(f,l,p,qi::space,result);
        if (ok)   
        {
            std::cout << "parse success\n";
            std::cout << "result: " << std::boolalpha << result << "\n";
        }
        else      std::cerr << "parse failed: '" << std::string(f,l) << "'\n";

        if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
        return ok;
    } catch(const qi::expectation_failure<It>& e)
    {
        std::string frag(e.first, e.last);
        std::cerr << e.what() << "'" << frag << "'\n";
    }

    return false;
}

int main()
{
    doParse("1 + 2 * 3 = 7");
    doParse("1 + 2 * 3 = 8");
}

这篇关于如何使用boost ::精神,以验证的代数声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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