工作于1.46的规则提升::精神并停止了提升精神1.55

时间:2015-07-08 19:00:31

标签: boost boost-spirit

constant_double_quotation_string %= char_( '"' ) >> 
    *( spirit::qi::string( "\\\"" )[ _val += _1 ] | 
     ( char_ - '"' ) ) >> char_( '"' ); 

constant_single_quotation_string %= char_( '\'' ) >> 
    *( spirit::qi::string( "\\\'" )[ _val += _1 ] | 
     ( char_ - '\'' ) ) >> char_( '\'' ); 

现在它说char不是gcc 4.7.2的类或结构或联合类型?

2 个答案:

答案 0 :(得分:1)

您甚至没有指定constant_single_quotation_string规则的声明类型。

以下是一些观察和工作方法:

既然你

  • 显然不希望合成的属性值成为输入序列 unescaped 您可以简单地使用qi::raw[]指令直接镜像输入序列。通过这种方式,您可以简化规则本身
  • 您根本不需要%=(自动规则分配)或语义操作([_val+=_1]); ¹

    相反,如果你是不希望开/关报价作为一部分 属性,只需将qi::char_('"')替换为qi::lit('"')(或实际上只是'"'

简化为:

qi::rule<It, std::string()> 
    dq_literal,
    sq_literal;

dq_literal = raw [ '"' >> *("\\\"" | ~char_('"')) >> '"' ]; 
sq_literal = raw [ "'" >> *("\\'"  | ~char_("'")) >> "'" ]; 

完整演示

<强> Live On Coliru

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

namespace qi = boost::spirit::qi;

template <typename It, typename Skipper = qi::space_type>
struct my_grammar : qi::grammar<It, std::string(), Skipper> {

    my_grammar() : my_grammar::base_type(start) {
        using namespace qi;

        start = dq_literal 
              | sq_literal;

        dq_literal = raw [ '"' >> *("\\\"" | ~char_('"')) >> '"' ]; 
        sq_literal = raw [ "'" >> *("\\'"  | ~char_("'")) >> "'" ]; 

        BOOST_SPIRIT_DEBUG_NODES(
                (start)(dq_literal)(sq_literal)
            )
    }

  private:
    qi::rule<It, std::string(), Skipper> start;

    // drop skipper to make these rules implicitly 'lexeme'
    // see: https://stackoverflow.com/questions/17072987/boost-spirit-skipper-issues/17073965#17073965
    qi::rule<It, std::string()> 
        dq_literal,
        sq_literal;
};

int main() {
    using It = std::string::const_iterator;
    my_grammar<It> g;

    for (std::string const& input : {
            "\"hello world\"",
            "\"hello \\\"world\\\"\"",
            "'bye world'",
            "'bye \"\\'world\\'\"'",
            "bogus" })
    {
        std::cout << "\n------- Parsing: " << input << '\n';
        It f = input.begin(), l = input.end();

        std::string result;
        bool ok = qi::phrase_parse(f, l, g, qi::space, result);

        if (ok)
            std::cout << "Parse success: " << result << "\n";
        else
            std::cout << "Parse failed\n";

        if (f!=l)
            std::cout << "Remaining unparsed input '"  << std::string(f,l) << "'\n";
    }
}

印刷:

------- Parsing: "hello world"
Parse success: "hello world"

------- Parsing: "hello \"world\""
Parse success: "hello \"world\""

------- Parsing: 'bye world'
Parse success: 'bye world'

------- Parsing: 'bye "\'world\'"'
Parse success: 'bye "\'world\'"'

------- Parsing: bogus
Parse failed
Remaining unparsed input 'bogus'

¹另见Boost Spirit: "Semantic actions are evil"?

答案 1 :(得分:1)

  

阐述我的earlier answer

如果您确实想要公开未转义值,我建议:

  • 不使用raw(显然,因为我们不希望在存在转义字符的情况下镜像确切的输入序列)
  • 仍然 不使用语义操作
  • 改为使用lit('\\')聪明地与匹配转义字符,而不将其添加到输出序列。

在这里,我选择对双引号/单引号文字解析器使用单一规则定义。相反,我将预期的引用字符作为inherited attribute传递:

qi::rule<It, std::string(char)> 
     q_literal;

q_literal = lit(_r1) >> *('\\' >> char_ | (char_ - lit(_r1))) >> lit(_r1);
start     = q_literal('"') | q_literal('\'');

演示

<强> Live On Coliru

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

namespace qi = boost::spirit::qi;

template <typename It, typename Skipper = qi::space_type>
struct my_grammar : qi::grammar<It, std::string(), Skipper> {

    my_grammar() : my_grammar::base_type(start) {
        using namespace qi;

        start     = q_literal('"') | q_literal('\'');

        q_literal = lit(_r1) >> *('\\' >> char_ | (char_ - lit(_r1))) >> lit(_r1);

        BOOST_SPIRIT_DEBUG_NODES( (start)(q_literal) )
    }

  private:
    qi::rule<It, std::string(), Skipper> start;

    // drop skipper to make these rules implicitly 'lexeme'
    // see: https://stackoverflow.com/questions/17072987/boost-spirit-skipper-issues/17073965#17073965
    qi::rule<It, std::string(char)> q_literal;
};

int main() {
    using It = std::string::const_iterator;
    my_grammar<It> g;

    for (std::string const& input : {
            "\"hello world\"",
            "\"hello \\\"world\\\"\"",
            "'bye world'",
            "'bye \"\\'world\\'\"'",
            "bogus" })
    {
        std::cout << "\n------- Parsing: " << input << '\n';
        It f = input.begin(), l = input.end();

        std::string result;
        bool ok = qi::phrase_parse(f, l, g, qi::space, result);

        if (ok)
            std::cout << "Parse success: " << result << "\n";
        else
            std::cout << "Parse failed\n";

        if (f!=l)
            std::cout << "Remaining unparsed input '"  << std::string(f,l) << "'\n";
    }
}

打印未转义的文字:

------- Parsing: "hello world"
Parse success: hello world

------- Parsing: "hello \"world\""
Parse success: hello "world"

------- Parsing: 'bye world'
Parse success: bye world

------- Parsing: 'bye "\'world\'"'
Parse success: bye "'world'"

------- Parsing: bogus
Parse failed
Remaining unparsed input 'bogus'