c++ - 从 Boost.Spirit 中的固定列表中解析选择

标签 c++ boost-spirit

Employee - Parsing into structs开始示例:

template <typename Iterator>
struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type>
{
    employee_parser() : employee_parser::base_type(start)
    {
        using qi::int_;
        using qi::lit;
        using qi::double_;
        using qi::lexeme;
        using ascii::char_;

        quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];

        start %=
            lit("employee")
            >> '{'
            >>  int_ >> ','
            >>  quoted_string >> ','
            >>  quoted_string >> ','
            >>  double_
            >>  '}'
            ;
    }

    qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
    qi::rule<Iterator, employee(), ascii::space_type> start;
};

假设我想将 quoted_string 替换为匹配给定容器中存储的任何字符串的规则。

例如,如果我有一个容器,例如:

std::array<std::string, 4> match_list =
   { "string0", "string1", "string2", "string3" };

并且我希望解析器仅将输入与数组中的值之一进行匹配(容器不必是数组)。

我敢肯定这很简单,但是 Spirit 帮助页面似乎没有解决这个问题。

最佳答案

很简单:https://www.boost.org/doc/libs/1_67_0/libs/spirit/doc/html/spirit/qi/reference/string/symbols.html

Live On Coliru

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;

struct employee {
    int id;
    std::string sym;
    std::string name;
    double value;
};

BOOST_FUSION_ADAPT_STRUCT(employee, id, sym, name, value) 

template <typename Iterator, typename Skipper = qi::space_type>
struct employee_parser : qi::grammar<Iterator, employee(), Skipper>
{
    employee_parser() : employee_parser::base_type(start)
    {
        using namespace qi;

        quoted_string = lexeme['"' >> +(char_ - '"') >> '"'];

        symbol_.add
            ("string0")
            ("string1")
            ("string2")
            ("string3")
            ;

        start =
            lit("employee")
            >> '{'
            >>  int_ >> ','
            >>  symbol_ >> ','
            >>  quoted_string >> ','
            >>  double_
            >>  '}'
            ;
    }

    qi::rule<Iterator, std::string(), Skipper> quoted_string;
    qi::rule<Iterator, employee(), Skipper> start;
    qi::symbols<char, std::string> symbol_;
};

int main() {
    std::string const input = "employee { 42, string3, \"more names or stuff\", 6.7 }";

    using It = std::string::const_iterator;
    It f = input.begin(), l = input.end();

    employee_parser<It> p;

    employee e;
    if (phrase_parse(f, l, p, qi::space, e)) {
        using boost::fusion::operator<<;
        std::cout << boost::fusion::tuple_delimiter(';');
        std::cout << "Parsed: " << e << "\n";
    } else {
        std::cout << "Parse failed\n";
    }

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

打印

Parsed: (42;;more names or stuff;6.7)

实际包含值:

    symbol_.add
        ("string0", "STRING0")
        ("string1", "STRING1")
        ("string2", "STRING2")
        ("string3", "STRING3")
        ;

打印 Live On Coliru

Parsed: (42;STRING3;more names or stuff;6.7)

或者您可以完全使用另一种类型:

    symbol_.add
        ("string0", 0)
        ("string1", 1)
        ("string2", 2)
        ("string3", 3)
        ;

    symbol_.add
        ("string0", 0)
        ("string1", 1)
        ("string2", 2)
        ("string3", 3)
        ;

打印 Live On Coliru

Parsed: (42;3;more names or stuff;6.7)

最后,您可以使用 raw[] 来“转换”输入序列,例如结合 qi::no_space[]: Live On Coliru

        >>  raw[no_case[symbol_]] >> ','

打印

Parsed: (42;sTrInG3;more names or stuff;6.7)

关于c++ - 从 Boost.Spirit 中的固定列表中解析选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51315726/

相关文章:

c++ - 使用 B 树和 B+-树的范围查询

c++ - C++中的引用速度

c++ - 提神气: change multiple target fields from semantic action

c++ - 如何使用Boost Spirit x3 Kleene Star?

c++ - MFC CView(CFormView)破坏崩溃

c++ - 添加多个 QDockWidget

c++ - 带有 boost 变体递归包装器的字符串解析器

c++ - x3::symbols 移动结果,因此将其从 symbol_parser 本身中删除

c++ - 尝试解析为 utree 时出现编译错误

c++ - 如何在Mac上使用C++创建图形