Search code examples
c++arraysboost-spirit-qi

C++ Boost spirit, parse a 2D array (and more) into a struct


I am trying to modify the following example : http://www.boost.org/doc/libs/1_57_0/libs/spirit/example/qi/employee.cpp

I would like to add a 2D vector in the employee struct, such as :

struct employee
{
    int age;
    std::string surname;
    std::string forename;
    double salary;
    std::vector<std::vector<int> > work_hours;
};

To parse something like

employee{42, "Foo", "Bar", 0
1 2 3
4 5 6 7 8
}

So that work_hours = {{1,2,3},{4,5,6,7,8}}. (I really need a 2D array, because the subvectors can vary in length).

I modified the BOOST_ADAPT_STRUCT, and changed the parsing rule into :

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

Unfortunately, this rule makes spirit returns work_hours = {{1,2,3,4,5,6,7,8}}, and not : {{1,2,3},{4,5,6,7,8}}

Does anybody have a workaround ?

Thanks in advance


Solution

  • qi::eol is matched by the skip parser, so you have to do the list parsing in a lexeme directive. For example:

            start %=
                lit("employee")
                >> '{'
                >>  int_ >> ','
                >>  quoted_string >> ','
                >>  quoted_string >> ','
                >>  double_
                >>  *lexeme[int_ % ' '] // <-- here
                >>  '}'
                ;
    

    lexeme[int_ % ' '] does not use the skip parser, so it will match integers delimited by exactly one space. If you want to allow the integers to be delimited by more than one space (for indentation purposes or so), and depending on the way you want to handle tabs and other non-newline whitespace, you can use a more complex delimiter. Probably the closest to your original code is

                >>  *lexeme[int_ % +(ascii::space - '\n')]
    

    What exactly the best approach is is something you'll have to answer yourself, though.