Domanda

Ho appena iniziato a scavare in Boost :: Spirito, la versione più recente, ormai - V2.4. L'essenza del mio problema è il seguente:

Vorrei stringhe parse come "1a2" o "3B4". Quindi l'uso regola che è:

  (double_ >> lit('b') >> double_)
| (double_ >> lit('a') >> double_);

L'attributo della regola deve essere "vector ". E sto leggendo nel contenitore.

Il codice completo:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cstring>

int main(int argc, char * argv[])
{
    using namespace std;
    using namespace boost::spirit;
    using namespace boost::spirit::qi;
    using boost::phoenix::arg_names::arg1;

    char const * first = "1a2";
    char const * last  = first + std::strlen(first);
    vector<double> h;

    rule<char const *, vector<double>()> or_test;
    or_test %=    (double_ >> lit('b') >> double_) 
            | (double_ >> lit('a') >> double_);

    if (parse(first, last, or_test,h)) {
           cout << "parse success: "; 
           for_each(h.begin(), h.end(), (cout << arg1 << " "));
           cout << "end\n";
    } else cout << "parse error\n" << endl;
    return 0;
 }

Sto compilando con g ++ 4.4.3. E si ritorna "1 1 2". Mentre mi aspetto "1 2".

Per quanto ho capito questo accade perché parser:

  • va alla prima alternativa
  • legge un double_ e lo memorizza nel contenitore
  • poi si ferma in "a", mentre aspettandosi acceso ( "b")
  • va alla seconda alternativa
  • legge due ulteriori doppie

La mia domanda è - È questo un comportamento corretto, e se sì, - perché

È stato utile?

Soluzione

comportamento che ci si aspetta. Durante backtracking Spirito non fa cambiamenti 'disfare' a attributi. Pertanto, è necessario utilizzare la direttiva hold[] costringendo esplicitamente il parser per tenere su di una copia dell'attributo (che consente di ripristinare ogni cambiamento attributo):

or_test =    
        hold[double_ >> lit('b') >> double_)]
    |   (double_ >> lit('a') >> double_)
    ; 

la presente direttiva deve essere applicato a tutte le alternative che modificano l'attributo, tranne l'ultimo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top