6

我正在阅读 Boost Spirit(和 Boost Fusion)教程(1.48.0 版)。我一直在玩玩具员工的例子。源链接在这里:

http://www.boost.org/doc/libs/1_48_0/libs/spirit/example/qi/employee.cpp

这是示例的语法:

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 %= lexeme['"' >> +(char_ - '"') >> '"'];
        start %=
            lit("employee")
            >> '{'
            >>  int_ >> ','
            >>  +(char_) >> ','
            >>  +(char_) >> ','
            >>  double_
            >>  '}'
            ;

我的假设是 char_ 包括所有字符,直到到达逗号。但是,使用以下字符串编译和运行会返回解析失败。

./employee
employee{10,my,name,20.0}
-------------------------
Parsing failed
-------------------------

我也在尝试编写一个类似的解析器来自动转换为我的结构类型的适当类型。我敢肯定,就像上面这样为输入字符串定义正确的语法而言,我遗漏了一些根本错误的东西,因此非常感谢任何帮助!

谢谢!

4

1 回答 1

11

+(char_)消耗一个或多个字符,因此它也会消耗逗号并且永远不会移动到>> ','. 这是贪婪的。

+(char_ - ',')您应该使用差异运算符编写-

//...
>>  int_ >> ','     
>>  +(char_ - ',') >> ','     
>>  +(char_ - ',') >> ','     
>>  double_
//...

解析器+(char_ - ',')将消耗每个字符,直到到达逗号。之后它将移动到>> ',',使用它,然后继续下一行+(char_ - ','),直到逗号,依此类推。

有关此运算符的更多信息,您可以在此处找到:http: //www.boost.org/doc/libs/1_48_0/libs/spirit/doc/html/spirit/qi/reference/operator/difference.html

或者

如果你想解析只包含字母的名字,你也可以考虑编写只接受字母的解析器:

//...
>>  int_ >> ','     
>>  +(char_("a-zA-Z")) >> ','     
>>  +(char_("a-zA-Z")) >> ','     
>>  double_
//...
于 2012-02-09T09:51:48.223 回答