Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在运行时动态组合Boost.Spirit.Qi规则(任意数量的备选方案)_C++_Boost_Runtime_Boost Spirit_Boost Spirit Qi - Fatal编程技术网

C++ 在运行时动态组合Boost.Spirit.Qi规则(任意数量的备选方案)

C++ 在运行时动态组合Boost.Spirit.Qi规则(任意数量的备选方案),c++,boost,runtime,boost-spirit,boost-spirit-qi,C++,Boost,Runtime,Boost Spirit,Boost Spirit Qi,我想知道Boost.Spirit.Qi中是否有一种方法可以在运行时动态组合任意数量的规则。对我来说,Boost.Spirit的内部工作机制仍然有点神秘,但由于规则是作为对象实现的,所以它似乎是可行的。我的动机是使语法的某些部分易于扩展 考虑以下人为的例子: namespace qi = boost::spirit::qi; namespace px = boost::phoenix; typedef std::string::const_iterator iterator_t; templa

我想知道Boost.Spirit.Qi中是否有一种方法可以在运行时动态组合任意数量的规则。对我来说,Boost.Spirit的内部工作机制仍然有点神秘,但由于规则是作为对象实现的,所以它似乎是可行的。我的动机是使语法的某些部分易于扩展

考虑以下人为的例子:

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

typedef std::string::const_iterator iterator_t;

template<typename Expr>
inline bool parse_full(const std::string& input, const Expr& expr)
{
    iterator_t first(input.begin()), last(input.end());

    bool result = qi::phrase_parse(first, last, expr, boost::spirit::ascii::space);

    return first == input.end() && result;
}

void no_op() {}

int main(int argc, char *argv[]) 
{
    int attr = -1;

    // "Static" version - Works fine!
    /*
    qi::rule<iterator_t, void(int&)> grammar;

    qi::rule<iterator_t, void(int&)> ruleA = qi::char_('a')[qi::_r1 = px::val(0)];
    qi::rule<iterator_t, void(int&)> ruleB = qi::char_('b')[qi::_r1 = px::val(1)];
    qi::rule<iterator_t, void(int&)> ruleC = qi::char_('c')[qi::_r1 = px::val(2)];

    grammar = 
        ruleA(qi::_r1) | //[no_op]
        ruleB(qi::_r1) | //[no_op]
        ruleC(qi::_r1);  //[no_op]
    */

    // "Dynamic" version - Does not compile! :(

    std::vector<qi::rule<iterator_t, void(int&)>> rules;

    rules.push_back(qi::char_('a')[qi::_r1 = px::val(0)]);
    rules.push_back(qi::char_('b')[qi::_r1 = px::val(1)]);
    rules.push_back(qi::char_('c')[qi::_r1 = px::val(2)]);

    std::vector<qi::rule<iterator_t, void(int&)>>::iterator i(rules.begin()), last(rules.end());

    qi::rule<iterator_t, void(int&)> grammar;

    grammar = (*i)(qi::_r1);

    for(++i; i!=last; ++i)
    {
        grammar = grammar.copy() | (*i)(qi::_r1);
    }

    // Tests

    if(parse_full("a", grammar(px::ref(attr)))) std::cout << attr << std::endl;
    if(parse_full("b", grammar(px::ref(attr)))) std::cout << attr << std::endl;
    if(parse_full("c", grammar(px::ref(attr)))) std::cout << attr << std::endl;

    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    return 0;
}
我怀疑这是由于没有将继承的属性传递给
grammar.copy()
。不幸的是,我找不到一个简单的方法来做这件事,所以我选择了一个变通方法。因此,我有了最后一个版本(我已经想感谢所有一直坚持到现在的人!)。这一条实际上似乎有效:

    // "Dynamic" version - Kind of works! :-/

    std::vector<qi::rule<iterator_t, void(int&)>> rules;

    rules.push_back(qi::char_('a')[qi::_r1 = px::val(0)]);
    rules.push_back(qi::char_('b')[qi::_r1 = px::val(1)]);
    rules.push_back(qi::char_('c')[qi::_r1 = px::val(2)]);

    std::vector<qi::rule<iterator_t, void(int&)>>::iterator i(rules.begin()), last(rules.end());

    qi::rule<iterator_t, int()> temp;

    temp = (*i)(qi::_val); //[no_op]

    for(++i; i!=last; ++i)
    {
        temp = temp.copy() | (*i)(qi::_val); //[no_op]
    }

    qi::rule<iterator_t, void(int&)> grammar;

    grammar = temp[qi::_r1 = qi::_1];
std::vector<qi::rule<iterator_t, void(int&)>> rules;

rules.push_back(qi::char_('a')[qi::_r1 = px::val(0)]);
rules.push_back(qi::char_('b')[qi::_r1 = px::val(1)]);
rules.push_back(qi::char_('c')[qi::_r1 = px::val(2)]);

std::vector<qi::rule<iterator_t, void(int&)>>::iterator
 i(rules.begin()), last(rules.end());

qi::rule<iterator_t, int()> temp;

for(; i!=last; ++i)
{
qi::rule<iterator_t, int()> tmp = (*i)(qi::_val)[no_op];

    temp = temp.copy() | tmp.copy();
}

qi::rule<iterator_t, void(int&)> grammar;

grammar = temp[qi::_r1 = qi::_1];

// Tests

int intres1;
int intres2;
int intres3;

bool res1 = parse_full("a", grammar(px::ref(intres1)) );
bool res2 = parse_full("b", grammar(px::ref(intres2)) );
bool res3 = parse_full("c", grammar(px::ref(intres3)) );
/“动态”版本-作品种类!:-/
向量规则;
规则。推回(qi::char_uu('a')[qi::r1=px::val(0)];
规则。推回(qi::char('b')[qi::r1=px::val(1)];
规则。推回(qi::char('c')[qi::r1=px::val(2)];
std::vector::迭代器i(rules.begin()),last(rules.end());
qi::规则温度;
温度=(*i)(合格证:)//[无图]
对于(++i;i!=last;++i)
{
temp=temp.copy()|(*i)(qi::_val);/[无操作]
}
规则语法;
语法=temp[qi::_r1=qi::_1];

然而,一旦我附加了一个简单的语义动作(比如“[no_op]”),这个行为就会变得非常奇怪。它不再像以前那样打印0,1,2,而是打印0,0,2。所以我想知道,我试图完成的是不是导致了未定义的行为?这是虫子吗?或者很可能,我只是以错误的方式使用了某些东西(例如语义动作?)吗?

是的,我不确定它在内部是如何工作的,但您没有复制for循环中的所有规则(只有左边的规则),因此这似乎是可行的:

    // "Dynamic" version - Kind of works! :-/

    std::vector<qi::rule<iterator_t, void(int&)>> rules;

    rules.push_back(qi::char_('a')[qi::_r1 = px::val(0)]);
    rules.push_back(qi::char_('b')[qi::_r1 = px::val(1)]);
    rules.push_back(qi::char_('c')[qi::_r1 = px::val(2)]);

    std::vector<qi::rule<iterator_t, void(int&)>>::iterator i(rules.begin()), last(rules.end());

    qi::rule<iterator_t, int()> temp;

    temp = (*i)(qi::_val); //[no_op]

    for(++i; i!=last; ++i)
    {
        temp = temp.copy() | (*i)(qi::_val); //[no_op]
    }

    qi::rule<iterator_t, void(int&)> grammar;

    grammar = temp[qi::_r1 = qi::_1];
std::vector<qi::rule<iterator_t, void(int&)>> rules;

rules.push_back(qi::char_('a')[qi::_r1 = px::val(0)]);
rules.push_back(qi::char_('b')[qi::_r1 = px::val(1)]);
rules.push_back(qi::char_('c')[qi::_r1 = px::val(2)]);

std::vector<qi::rule<iterator_t, void(int&)>>::iterator
 i(rules.begin()), last(rules.end());

qi::rule<iterator_t, int()> temp;

for(; i!=last; ++i)
{
qi::rule<iterator_t, int()> tmp = (*i)(qi::_val)[no_op];

    temp = temp.copy() | tmp.copy();
}

qi::rule<iterator_t, void(int&)> grammar;

grammar = temp[qi::_r1 = qi::_1];

// Tests

int intres1;
int intres2;
int intres3;

bool res1 = parse_full("a", grammar(px::ref(intres1)) );
bool res2 = parse_full("b", grammar(px::ref(intres2)) );
bool res3 = parse_full("c", grammar(px::ref(intres3)) );
std::向量规则;
规则。推回(qi::char_uu('a')[qi::r1=px::val(0)];
规则。推回(qi::char('b')[qi::r1=px::val(1)];
规则。推回(qi::char('c')[qi::r1=px::val(2)];
std::vector::迭代器
i(rules.begin()),last(rules.end());
qi::规则温度;
for(;i!=last;++i)
{
qi::规则tmp=(*i)(qi::_val)[无操作];
temp=temp.copy()| tmp.copy();
}
规则语法;
语法=temp[qi::_r1=qi::_1];
//测验
int intres1;
int intres2;
int intres3;
bool res1=parse_full(“a”,语法(px::ref(intres1));
bool res2=parse_full(“b”,语法(px::ref(intres2));
bool res3=parse_full(“c”,语法(px::ref(intres3));

谢谢!你的答案看起来很有希望。不幸的是,我现在没有任何方法来测试它。我一有机会就接受它!对迟到近2年表示诚挚的歉意。我现在来测试这个解决方案,它工作得很好!