Пример простой грамматики Boost :: Spirit - PullRequest
5 голосов
/ 07 февраля 2012

Я изучаю уроки 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
-------------------------

Я также пытаюсь написать похожий парсер для автоматического приведения к соответствующим типам моего типа структуры. Я уверен, что упускаю что-то принципиально неправильное в определении правильной грамматики для входной строки, как указано выше, поэтому любая помощь будет принята с благодарностью!

Спасибо!

1 Ответ

10 голосов
/ 09 февраля 2012

+(char_) потребляет один или несколько символов, поэтому он также будет использовать запятые и никогда не перейдет на >> ','.Это жадно.

Вы должны написать +(char_ - ','), используя разностный оператор -:

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

Parser +(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_
//...
...