How to verify algebraic statements using boost::spirit?

前端 未结 1 689
别那么骄傲
别那么骄傲 2020-12-19 12:45

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 o

相关标签:
1条回答
  • 2020-12-19 13:35

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

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

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

    The demonstration program

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

    prints

    parse success
    result: true
    parse success
    result: false
    

    Sample program

    #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");
    }
    
    0 讨论(0)
提交回复
热议问题