提振精神的语法不一致的行为 [英] inconsistent behavior of boost spirit grammar

查看:184
本文介绍了提振精神的语法不一致的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我想要使用一个工作项目有点语法。最低可执行的例子是:

I have a little grammar that I want to use for a work project. A minimum executable example is:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#pragma GCC diagnostic ignored "-Wunused-variable"
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi_grammar.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#pragma GCC diagnostic pop // pops

#include <iostream>

int main()

{
    typedef  unsigned long long ull;

    std::string curline = "1;2;;3,4;5";
    std::cout << "parsing:  " << curline << "\n";

    namespace qi = boost::spirit::qi;
    auto ids = -qi::ulong_long % ','; // '-' allows for empty vecs.
    auto match_type_res = ids % ';' ;
    std::vector<std::vector<ull> > r;
    qi::parse(curline.begin(), curline.end(), match_type_res, r);

    std::cout << "got:      ";
    for (auto v: r){
        for (auto i : v)
            std::cout << i << ",";
        std::cout << ";";
    }
    std::cout <<"\n";
}

在我个人的机器这将产生正确的输出:
解析:1; 2 ;; 3,4; 5
有:1,2,3,4 ;;; 5,;

On my personal machine this produces the correct output: parsing: 1;2;;3,4;5 got: 1,;2,;;3,4,;5,;

但在工作中它产生:
解析:1; 2 ;; 3,4; 5
有:1,; 2,; 3,

But at work it produces: parsing: 1;2;;3,4;5 got: 1,;2,;;3,

在换句话说,它未能尽快有一个以上的元素的解析长整数的向量在它

In other words, it fails to parse the vector of long integers as soon as there's more than one element in it.

现在,我已经确定了工作的系统使用的是提升1.56,而我的私人计算机使用的是1.57。这是什么原因?

Now, I have identified that the work system is using boost 1.56, while my private computer is using 1.57. Is this the cause?

Knowning我们有一些真正的精神的专家在这里堆栈溢出,我希望有人会知道这个问题是从哪里来的,或者至少可以缩小东西我需要检查的次数。

Knowning we have some real spirit experts here on stack overflow, I was hoping someone might know where this issue is coming from, or can at least narrow down the number of things I need to check.

如果增压版本的问题,我也许可以说服公司进行升级,而是一个解决方法是在任何情况下的欢迎。

If the boost version is the problem, I can probably convince the company to upgrade, but a workaround would be welcome in any case.

推荐答案

您是在调用未定义行为在code。

You're invoking Undefined Behaviour in your code.

特别是在您使用汽车来存储一个解析器前pression。该前pression模板包含临时的成为的dangling 在的含全EX pression结束的¹

Specifically where you use auto to store a parser expression. The Expression Template contains references to temporaries that become dangling at the end of the containing full-expression¹.

UB意味着,任何事情都有可能发生。这两种编译器是正确的!而最好的部分是,根据所使用的编译器标志,你可能会看到不同的行为。

UB implies that anything can happen. Both compilers are right! And the best part is, you will probably see varying behaviour depending on the compiler flags used.

通过对其进行修复或者:

Fix it either by using:


  • 齐::复制(或的boost ::原:: DEEP_COPY v.1.55 IIRC之前)

  • 使用 BOOST_SPIRIT_AUTO 而不是 BOOST_AUTO (主要是当且仅当您有帮助还支持C ++ 03)

  • 使用齐::规则&LT;&GT; 齐::语法&LT;&GT; (中<一href=\"http://www.boost.org/doc/libs/1_58_0/libs/spirit/doc/html/spirit/qi/reference/parser_concepts/nonterminal.html\"相对=nofollow>非终端)键入擦除和前pressions。这有性能的影响太多,但也提供了更多的功能,如

  • qi::copy (or boost::proto::deep_copy before v.1.55 IIRC)
  • use BOOST_SPIRIT_AUTO instead of BOOST_AUTO (mostly helpful iff you also support C++03)
  • use qi::rule<> and qi::grammar<> (the non-terminals) to type-erase and the expressions. This has performance impact too, but also gives more features like


  • 递归规则

  • 当地人和继承的属性

  • 宣布船长(方便,因为规则可以隐语义[] (见<一href=\"http://stackoverflow.com/questions/17072987/boost-spirit-skipper-issues/17073965#17073965\">here)

  • 更好code组织。

还要注意的是精神X3承诺砸自动使用有限制。这基本上是一个一大堆更加轻便由于使用C ++ 14的特性。请记住,这还不稳定。

  • Showing that GCC with -O2 shows undefined results; Live On Coliru

    固定的版本:

    <大骨节病> 住在Coliru

    //#pragma GCC diagnostic push
    //#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
    //#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
    //#pragma GCC diagnostic ignored "-Wunused-variable"
    #include <boost/spirit/include/karma.hpp>
    #include <boost/spirit/include/qi.hpp>
    //#pragma GCC diagnostic pop // pops
    
    #include <iostream>
    
    int main() {
        typedef  unsigned long long ull;
    
        std::string const curline = "1;2;;3,4;5";
        std::cout << "parsing: '" << curline << "'\n";
    
        namespace qi = boost::spirit::qi;
    
    #if 0 // THIS IS UNDEFINED BEHAVIOUR:
        auto ids     = -qi::ulong_long % ','; // '-' allows for empty vecs.
        auto grammar = ids % ';';
    #else // THIS IS CORRECT:
        auto ids     = qi::copy(-qi::ulong_long % ','); // '-' allows for empty vecs.
        auto grammar = qi::copy(ids % ';');
    #endif
    
        std::vector<std::vector<ull> > r;
        qi::parse(curline.begin(), curline.end(), grammar, r);
    
        std::cout << "got:      ";
        for (auto v: r){
            for (auto i : v)
                std::cout << i << ",";
            std::cout << ";";
        }
        std::cout <<"\n";
    }
    

    打印(也与GCC -O2!):

    Printing (also with GCC -O2!):

    parsing: '1;2;;3,4;5'
    got:      1,;2,;;3,4,;5,;
    


    ¹(这是基本上是下一个分号在这里;但在standardese)


    ¹ (that's basically "at the next semicolon" here; but in standardese)

    这篇关于提振精神的语法不一致的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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