C++ 振奋精神:可以';I don’我没能让另一个接线员像我期望的那样工作

C++ 振奋精神:可以';I don’我没能让另一个接线员像我期望的那样工作,c++,boost,boost-spirit,C++,Boost,Boost Spirit,我无法让这种精神发挥作用(或者说,做我期望的事情) 这是我的MCVE #include <string> #include <iostream> #include <boost/variant.hpp> #include <boost/spirit/include/qi_parse.hpp> #include <boost/spirit/include/qi.hpp> using namespace boost::spirit; n

我无法让这种精神发挥作用(或者说,做我期望的事情)

这是我的MCVE

#include <string>
#include <iostream>

#include <boost/variant.hpp>
#include <boost/spirit/include/qi_parse.hpp>
#include <boost/spirit/include/qi.hpp>

using namespace boost::spirit;
namespace charset = boost::spirit::qi::standard_wide;

using Expr = boost::variant<std::string, int >;

int main(int argc, char ** argv)
{
    std::string intToParse = "{int:  45}";
    std::string stringToParse = "{string:  \"foo\"}";

    using It = std::string::const_iterator;
    using Sk = qi::space_type;
    qi::rule<It, std::string(), Sk> parseString;
    qi::rule<It, int(), Sk> parseInt;
    qi::rule<It, std::string(),Sk> string_;
    
    qi::rule<It,Expr(),Sk > orParse;


    string_ =
            qi::lit('"')
            > *(charset::char_ - '"')
            > '"';
    
    parseString = qi::omit[  qi::string("string")] >  qi::lit(':') > string_;

    parseInt = qi::omit[ qi::string("int")] > qi::lit(':') > qi::uint_ ;

    orParse =  qi::omit[qi::lit('{')] >  parseString | parseInt >  '}';
    
    orParse.name_ =  "alternative parser";
    parseString.name_ = "string parser";
    parseInt.name_= "int parser";

    qi::debug(orParse);
    qi::debug(parseString);
    qi::debug(parseInt);

    Expr res2;
    qi::phrase_parse(stringToParse.cbegin(), stringToParse.cend(), orParse, qi::space, res2);
    std::cout << res2<< std::endl;


    Expr res;
    qi::phrase_parse(intToParse.cbegin(), intToParse.cend(), orParse, qi::space, res);
    std::cout << res << std::endl;
  
    return 0;
}
#包括
#包括
#包括
#包括
#包括
使用名称空间boost::spirit;
名称空间charset=boost::spirit::qi::standard\u-wide;
使用Expr=boost::variant;
int main(int argc,字符**argv)
{
std::string intToParse=“{int:45}”;
std::string stringToParse=“{string:\“foo\”}”;
使用它=std::string::const_迭代器;
使用Sk=qi::space\u类型;
qi::规则解析字符串;
qi::规则parseInt;
qi::规则字符串;
气:规则还是纵火;
串=
qi::lit(“”)
>*(字符集::字符-'“')
> '"';
parseString=qi::省略[qi::string(“string”)]>qi::lit(“:”)>string;
parseInt=qi::省略[qi::string(“int”)]>qi::lit(':')>qi::uint;
orParse=qi::省略[qi::lit('{')]>parseString | parseInt>'}';
orParse.name=“可选解析器”;
parseString.name=“字符串解析器”;
parseInt.name=“int parser”;
qi::debug(或parse);
qi::debug(解析字符串);
调试(parseInt);
Expr res2;
qi::phrase_parse(stringToParse.cbegin(),stringToParse.cend(),orParse,qi::space,res2);

std::cout
运算符>
在表中高于
运算符|
,因此需要括号:

orParse =  qi::omit[qi::lit('{')] >  (parseString | parseInt) >  '}';
//                              here ^             and here ^
结果:

<alternative parser>
  <try>{string:  "foo"}</try>
  <string parser>
    <try>string:  "foo"}</try>
    <success>}</success>
    <attributes>[[f, o, o]]</attributes>
  </string parser>
  <success></success>
  <attributes>[[f, o, o]]</attributes>
</alternative parser>
foo
<alternative parser>
  <try>{int:  45}</try>
  <string parser>
    <try>int:  45}</try>
    <fail/>
  </string parser>
  <int parser>
    <try>int:  45}</try>
    <success>}</success>
    <attributes>[45]</attributes>
  </int parser>
  <success></success>
  <attributes>[45]</attributes>
</alternative parser>
45

{string:“foo”}
字符串:“foo”}
}
[f,o,o]]
[f,o,o]]
福
{int:45}
int:45}
int:45}
}
[45]
[45]
45

因此,已经指出了优先级问题。请注意,您可以通过使用编译器的警告捕捉到这一点:

test.cpp|25 col 23| warning: suggest parentheses around comparison in operand of ‘|’ []8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wparentheses-Wparentheses]8;;]
还有许多其他问题。让我从有问题的问题开始:

在需要的地方使用词汇表 不要使用skipper,也不要在skipupper不能操作的地方使用wrap-in
qi::lexeme[]
。具体地说,您的
string\uu
规则可能不应该跳过空白

另见

其他问题
  • 字符集的用法有点不一致。这可能有什么大不了的。我通常使用默认值(
    qiL::char\uz,lit,string

  • 为什么要手动处理调试规则的内部内容

     BOOST_SPIRIT_DEBUG_NODES((orParse)(parseString)(parseInt))
    
  • 为什么省略不公开属性的指令上的属性

  • 如果要忽略属性,为什么要使用
    qi::string
    ?请改用
    lit

  • 请记住处理错误条件和部分解析

简化固定代码

#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;
namespace charset = boost::spirit::qi::standard_wide;

using Expr = boost::variant<std::string, int >;
using It = std::string::const_iterator;
using Sk = charset::space_type;

int main()
{
    // lexeme!
    qi::rule<It, std::string()> string_ 
        = '"' > *~charset::char_('"') > '"';

    // with skipper
    Sk skip;
    qi::rule<It, Expr(),        Sk> orParse;
    qi::rule<It, std::string(), Sk> parseString;
    qi::rule<It, int(),         Sk> parseInt;

    parseString = qi::lit("string") > ':' > string_;
    parseInt    = qi::lit("int")    > ':' > qi::uint_;
    orParse     = '{' > (parseString | parseInt) > '}';
    
    BOOST_SPIRIT_DEBUG_NODES((orParse)(parseString)(parseInt))

    for (std::string const input: { "{int:  45}", "{string:  \"foo\"}" }) {
        Expr res;
        It f = input.begin(), l = input.end();

        if (phrase_parse(f, l, orParse, skip, res)) {
            std::cout << "Parsed: " << res << std::endl;
        } else {
            std::cout << "Failed" << std::endl;
        }
        if (f != l) {
            std::cout << "Remaining: " << std::string(f,l) << "\n";
        }
    }
}
如果启用了调试:

<orParse>
  <try>{int:  45}</try>
  <parseString>
    <try>int:  45}</try>
    <fail/>
  </parseString>
  <parseInt>
    <try>int:  45}</try>
    <success>}</success>
    <attributes>[45]</attributes>
  </parseInt>
  <success></success>
  <attributes>[45]</attributes>
</orParse>
<orParse>
  <try>{string:  "foo"}</try>
  <parseString>
    <try>string:  "foo"}</try>
    <success>}</success>
    <attributes>[[f, o, o]]</attributes>
  </parseString>
  <success></success>
  <attributes>[[f, o, o]]</attributes>
</orParse>

{int:45}
int:45}
int:45}
}
[45]
[45]
{string:“foo”}
字符串:“foo”}
}
[f,o,o]]
[f,o,o]]

哦,是的!太简单了……我的错。注意到了更多的事情,所以发布了一个额外的答案
Parsed: 45
Parsed: foo
<orParse>
  <try>{int:  45}</try>
  <parseString>
    <try>int:  45}</try>
    <fail/>
  </parseString>
  <parseInt>
    <try>int:  45}</try>
    <success>}</success>
    <attributes>[45]</attributes>
  </parseInt>
  <success></success>
  <attributes>[45]</attributes>
</orParse>
<orParse>
  <try>{string:  "foo"}</try>
  <parseString>
    <try>string:  "foo"}</try>
    <success>}</success>
    <attributes>[[f, o, o]]</attributes>
  </parseString>
  <success></success>
  <attributes>[[f, o, o]]</attributes>
</orParse>