2012-02-07 4 views
5

Я читаю уроки Boost Spirit (и Boost Fusion) (версия 1.48.0). Я играл с примером игрушечного сотрудника. Ссылка на источник здесь:Boost :: Пример простой грамматики духа

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 
------------------------- 

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

Спасибо!

ответ

10

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

... это были бы только буквы ASCII, то ... Хосе не удивлен. ;-) – DevSolar

Смежные вопросы