2012-02-07 16 views
5

Sto passando attraverso le esercitazioni Boost Spirit (e Boost Fusion) (versione 1.48.0). Ho giocato con l'esempio di impiegato giocattolo. Il link alla fonte è qui:Boost :: Esempio di grammatica semplice di Spirit

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

Ecco la grammatica della esempio:

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; 

E le mie modifiche togliere il trattamento delle citazioni e solo analizza qualsiasi carattere tra il delimitatore e assegna che alla struttura su cui è mappato il parser.

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

La mia ipotesi è che char_ include tutti i caratteri finché non viene raggiunta una virgola. Tuttavia, la compilazione e l'esecuzione con la seguente stringa restituiscono un errore di analisi.

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

Sto anche cercando di scrivere un parser simile per lanciare automaticamente ai tipi appropriati di mio tipo struct. Sono sicuro che mi manca qualcosa di fondamentalmente sbagliato per quanto riguarda la definizione della grammatica corretta per una stringa di input come sopra, quindi qualsiasi aiuto è molto apprezzato!

Grazie!

risposta

10

+(char_) consuma uno o più caratteri, quindi consumerà anche virgole e non si sposterà mai verso >> ','. È goloso.

Si dovrebbe scrivere +(char_ - ','), utilizzando l'operatore differenza -:

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

Parser +(char_ - ',') consumerebbe ogni carattere fino al raggiungimento virgola. Dopodiché si sposterà su >> ',', lo consumerà e quindi continuerà con la riga successiva +(char_ - ',') fino alla virgola e così via.

più su questo operatore si possono trovare qui: http://www.boost.org/doc/libs/1_48_0/libs/spirit/doc/html/spirit/qi/reference/operator/difference.html

O

Se si desidera analizzare i nomi che contiene solo lettere, si può anche non crei parser che accettano solo lettere:

//... 
>> int_ >> ','  
>> +(char_("a-zA-Z")) >> ','  
>> +(char_("a-zA-Z")) >> ','  
>> double_ 
//... 
+2

... che sarebbe solo lettere ASCII, quindi ... José non è divertito. ;-) – DevSolar