Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.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++ 尝试分析带引号的字符串文字时,Spirit无法编译_C++_Parsing_Boost_Boost Spirit - Fatal编程技术网

C++ 尝试分析带引号的字符串文字时,Spirit无法编译

C++ 尝试分析带引号的字符串文字时,Spirit无法编译,c++,parsing,boost,boost-spirit,C++,Parsing,Boost,Boost Spirit,我正在尝试使用Boost::Spirit解析带有转义序列的带引号的字符串。不幸的是,在语法定义中包含引号似乎会导致大量编译时错误(正如Boost所预期的那样)。省略引号可以让程序编译,但显然它不会按预期的方式运行。这是代码(实际上是更大画面的一部分,但它说明了问题): #包括“boost/spirit/include/qi.hpp” #包括“boost/proto/deep_copy.hpp” #包括“boost/optional.hpp” #包括 使用boost::spirit::qi::ch

我正在尝试使用Boost::Spirit解析带有转义序列的带引号的字符串。不幸的是,在语法定义中包含引号似乎会导致大量编译时错误(正如Boost所预期的那样)。省略引号可以让程序编译,但显然它不会按预期的方式运行。这是代码(实际上是更大画面的一部分,但它说明了问题):

#包括“boost/spirit/include/qi.hpp”
#包括“boost/proto/deep_copy.hpp”
#包括“boost/optional.hpp”
#包括
使用boost::spirit::qi::char;
使用boost::spirit::qi::lexeme;
使用boost::proto::deep_copy;
自动字符串\文字=深度\复制(
词素[
//字符(““”)
/*>>*/*((char \-'''''-'\\')|(char \('\\')>>char \))
//>>字符(“”)
]);
模板
boost::可选的parse_字符串(迭代器优先、迭代器最后、语法和语法)
{
使用boost::spirit::qi::space;
使用boost::spirit::qi::短语解析;
std::字符串温度;
bool success=短语解析(
第一,
最后,,
gr,
空间
临时雇员
);
if(first==last&&success)
返回温度;
否则返回boost::无;
}
int main()
{
std::字符串str;

我花了一点时间才看到它

归根结底,问题在于[1]

合成

boost::variant<
    boost::fusion::vector2<char, char>,
    char>
您希望捕获带引号的原始字符串,而根本不关心公开的属性:

    qi::raw [
            '"' >>
                *(('\\' >> qi::char_) | (qi::char_ - '"'))
            >> '"'
        ]
后者使用从源迭代器对(
qi::raw[]
)到
std::string
(绑定属性)的隐式属性转换

现场观看完整内容:

#include <boost/spirit/include/qi.hpp>
#include <boost/proto/deep_copy.hpp>
#include <boost/optional.hpp>

#include <string>

namespace qi = boost::spirit::qi;

namespace {

    auto string_literal = boost::proto::deep_copy(
#if 1
        qi::lexeme [
                '"' >>
                    *(('\\' >> qi::char_) | (qi::char_ - '"'))
                >> '"'
            ]
#else
        qi::raw [
                '"' >>
                    *(('\\' >> qi::char_) | (qi::char_ - '"'))
                >> '"'
            ]
#endif
        );

}

template <class Iterator, class Grammar>
boost::optional<std::string> parse_string(Iterator first, Iterator last, Grammar&& gr)
{
    std::string temp;

    bool success = qi::phrase_parse(
        first,
        last,
        std::forward<Grammar>(gr),
        qi::space,
        temp
    );

    if (success && first == last)
        return temp;
    else return boost::none;
}


int main()
{
    std::string str;
    std::cout << "string_literal: ";

    getline(std::cin, str);

    auto presult = parse_string(str.begin(), str.end(), string_literal);
    if (presult) {
        std::cout << "parsed: '" << *presult << "'\n";
    } else
        std::cout << "failure\n";

    return 0;
}
#包括
#包括
#包括
#包括
名称空间qi=boost::spirit::qi;
名称空间{
自动字符串\u literal=boost::proto::deep\u copy(
#如果1
齐:词素[
'"' >>
*((“\\”>>qi::char|)(qi::char|-”)
>> '"'
]
#否则
齐:生的[
'"' >>
*((“\\”>>qi::char|)(qi::char|-”)
>> '"'
]
#恩迪夫
);
}
模板
boost::可选的parse_字符串(迭代器优先、迭代器最后、语法和语法)
{
std::字符串温度;
bool success=qi::短语解析(
第一,
最后,,
标准:正向(gr),
齐:空间,
临时雇员
);
if(success&&first==last)
返回温度;
否则返回boost::无;
}
int main()
{
std::字符串str;

std::我不能谢谢你。老实说,我不知道该怎么看待Spirit了,所有这些问题都变得越来越累,我想文档也相当缺乏。如果我从头到尾阅读文档,我会知道这一点吗?不管怎样,这非常有帮助-我很可能会使用
qi::raw[]
方法,因为我当前的设计最初将所有文本都视为原始字符串,然后使用单独的函数从中“提取”实际值。我想你应该知道:我只是将文档与
变量组合在一起,得到了
变体。如果你喜欢的话。也就是说,是的,Spirit有它的缺陷(尽管你不遵循常见的习惯用法,例如使用
deep\u copy
这一方式有点推动了Spirit v2的发展;顺便说一句,我喜欢由此产生的风格)。我花了大约10分钟才真正看到这个问题,所以你不会听到我说没有问题。再说一次,我很了解spirit,我自己也不会写这个bug(我在写它的时候会意识到
char('\\')
对合成属性的影响)所以也许你得给它一点时间。这肯定是一个折衷的办法,我过去也曾为Spirit做过一些案例。但我仍然认为它对一些工作来说是一个非常有价值的工具。我不想没有它。我的辩护是,
深拷贝
只是为了节省一些打字时间,因为我真的觉得我对它不够精通我想,这是一个继承自
qi::grammar
,带有
qi::rule
字段和默认构造函数的
struct
结构。你能举个例子说明一个惯用的
string\u literal
解析器的样子吗?包装结构的主要目的是允许使用不同的迭代器类型进行实例化:。因此,您可以将其视为“规则容器”(非惯用)或传递模板参数(非惯用)。我坚持使用
语法
(第一种方法)。
    qi::lexeme [
            '"' >>
                *(('\\' >> qi::char_) | (qi::char_ - '"'))
            >> '"'
        ]
    qi::raw [
            '"' >>
                *(('\\' >> qi::char_) | (qi::char_ - '"'))
            >> '"'
        ]
#include <boost/spirit/include/qi.hpp>
#include <boost/proto/deep_copy.hpp>
#include <boost/optional.hpp>

#include <string>

namespace qi = boost::spirit::qi;

namespace {

    auto string_literal = boost::proto::deep_copy(
#if 1
        qi::lexeme [
                '"' >>
                    *(('\\' >> qi::char_) | (qi::char_ - '"'))
                >> '"'
            ]
#else
        qi::raw [
                '"' >>
                    *(('\\' >> qi::char_) | (qi::char_ - '"'))
                >> '"'
            ]
#endif
        );

}

template <class Iterator, class Grammar>
boost::optional<std::string> parse_string(Iterator first, Iterator last, Grammar&& gr)
{
    std::string temp;

    bool success = qi::phrase_parse(
        first,
        last,
        std::forward<Grammar>(gr),
        qi::space,
        temp
    );

    if (success && first == last)
        return temp;
    else return boost::none;
}


int main()
{
    std::string str;
    std::cout << "string_literal: ";

    getline(std::cin, str);

    auto presult = parse_string(str.begin(), str.end(), string_literal);
    if (presult) {
        std::cout << "parsed: '" << *presult << "'\n";
    } else
        std::cout << "failure\n";

    return 0;
}