3

我对 Boost Spirit 很陌生。理想情况下,我想使用 Phoenix 确保我的语法中有两个值。我想要工作的一个简化版本将是一个两个整数相等的元组。

我想解析一串“14,14,test”,但“14,12,test”失败,因为 14 不等于 12。我想打印下面的代码:

Good: (14 14 test)
Fail

目前两个输入都将通过,因为我允许 qi::int_ 解析第二个值而无需任何检查。

#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/spirit/include/qi_matches.hpp>

#include <string>
#include <vector>
#include <algorithm>

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


int main(){


    std::vector<std::string> test_inputs = {"14,14,test","14,12,test"};

    std::for_each(test_inputs.begin(),test_inputs.end(),[](const std::string& input){
        boost::fusion::vector<int,int,std::string> result;
        int i(0);

        auto res = qi::parse(input.begin(),input.end(),
            //works but also parses "14,12,test"
            qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_ >> qi::lit(",") >> +qi::char_,
            //Fails to compile
            //qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_(phx::val(i)) >> qi::lit(",") >> +qi::char_,
            //qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_(phx::ref(i)) >> qi::lit(",") >> +qi::char_,
            result);
        if(res){
            std::cout << "Good: " << result << std::endl;
        }
        else{
            std::cout << "Fail" << std::endl;
        }
    });         
}

我可以使用 phoenix::ref 捕获第一个值,但我无法确定测试我的第二个 qi::int_ 解析器的 i 值。我试过使用 phoenix::val 和 phoenix::ref 编译没有运气。理想情况下,我想捕获第二个 int 中的值,并认为 int_ 解析器会从 Phoenix 获取一个惰性文字。

感谢您对此的任何帮助。

4

1 回答 1

5

最简单的解决方法是i将从第一个 qi::int_ 获取的值提供给第二个,即:

qi::int_[phx::ref(i) = qi::_1] >> qi::lit(",") >> qi::int_(phx::ref(i)) >> qi::lit(",") >> +qi::char_,

带参数的 qi::_int 需要提供的值。

另一个需要考虑的替代方法是使用规则局部变量。你可以这样做:

typedef boost::fusion::vector<int,int,std::string> result_t;
result_t result;
qi::rule<std::string::const_iterator, result_t(),
     boost::spirit::qi::locals<int> > r;
r %= qi::int_[qi::_a = qi::_1] >> qi::lit(",") >> qi::int_(qi::_a) >> qi::lit(",") >> +qi::char_;

然后使用“r”代替您的规则。虽然我想如果你只是打算直接使用 qi::parse 运行规则,这是没有意义的。

于 2013-09-05T18:57:14.463 回答