2013-02-21 11 views
5

sto cercando di definire la mia propria grammatica utilizzando framework spirito spinta e sto definendo una regola di corrispondenza:spirito Boost ottenere tutta la partita come una stringa

value = (
     char_('"') >> 
     (*qi::lexeme[ 
       char_('\\') >> char_('\\') | 
       char_('\\') >> char_('"') | 
       graph - char_('"') | 
       char_(' ') 
     ])[some_func] >> 
     char_('"') 
); 

mi piacerebbe assing un'azione - some_func - per la parte di esso e passa l'intera stringa corrispondente come parametro. Ma sfortunatamente otterrò qualcosa come vector<boost::variant<boost::fusion::vector2 ..a lot of stuff...)...>. Posso in qualche modo ottenere tutti i dati come char *, std :: string o anche void * con dimensioni?

+0

ciò che è sbagliato con il vettore ? –

+0

Lo descrivo come un vettore >>> ma è stato modificato da sehe. – Dejwi

risposta

8

Guardate qi::as_string:

uscita del programma demo:

DEBUG: 'some\\"quoted\\"string.' 
parse success 

ad essere onesti, sembra che si sta veramente cercando di analizzare le stringhe letterali '' con possibili caratteri di fuga. Nel rispetto, l'uso di lexeme sembra sbagliato (gli spazi vengono mangiati). Se vuoi vedere esempi di parsing di stringhe con escape, vedi per es.

Un semplice riassetto che penso potrebbe essere fatto, almeno potrebbe apparire come:

value = qi::lexeme [ 
      char_('"') >> 
      qi::as_string [ 
      *(
       string("\\\\") 
       | string("\\\"") 
       | (graph | ' ') - '"' 
      ) 
      ] [some_func(_1)] >> 
      char_('"') 
     ]; 

nota, tuttavia, che si può semplicemente dichiarare la regola senza skipper e rilasciare il lexeme alltogether: http://liveworkspace.org/code/1oEhei$0

codice (in diretta su liveworkspace)

#include <boost/fusion/adapted.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 

namespace qi = boost::spirit::qi; 
namespace phx = boost::phoenix; 

struct some_func_t 
{ 
    template <typename> struct result { typedef void type; }; 
    template <typename T> 
     void operator()(T const& s) const 
     { 
      std::cout << "DEBUG: '" << s << "'\n"; 
     } 
}; 

template <typename It, typename Skipper = qi::space_type> 
    struct parser : qi::grammar<It, Skipper> 
{ 
    parser() : parser::base_type(value) 
    { 
     using namespace qi; 
     // using phx::bind; using phx::ref; using phx::val; 

     value = (
       char_('"') >> 
        qi::as_string 
        [ 
         (*qi::lexeme[ 
          char_('\\') >> char_('\\') | 
          char_('\\') >> char_('"') | 
          graph - char_('"') | 
          char_(' ') 
          ]) 
        ] [some_func(_1)] >> 
       char_('"') 
      ); 
     BOOST_SPIRIT_DEBUG_NODE(value); 
    } 

    private: 
    qi::rule<It, Skipper> value; 
    phx::function<some_func_t> some_func; 
}; 

bool doParse(const std::string& input) 
{ 
    typedef std::string::const_iterator It; 
    auto f(begin(input)), l(end(input)); 

    parser<It, qi::space_type> p; 

    try 
    { 
     bool ok = qi::phrase_parse(f,l,p,qi::space); 
     if (ok) 
     { 
      std::cout << "parse success\n"; 
     } 
     else  std::cerr << "parse failed: '" << std::string(f,l) << "'\n"; 

     if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n"; 
     return ok; 
    } catch(const qi::expectation_failure<It>& e) 
    { 
     std::string frag(e.first, e.last); 
     std::cerr << e.what() << "'" << frag << "'\n"; 
    } 

    return false; 
} 

int main() 
{ 
    bool ok = doParse("\"some \\\"quoted\\\" string.\""); 
    return ok? 0 : 255; 
} 
+1

+1 Stavo per rispondere con 'as_string' prima, ma non potevo trovarlo nei documenti - 'parser directives', duh! – ildjarn

+0

Aggiunta un'illustrazione concreta di cosa penserei _needs_ da correggere nell'uso di 'lexeme'. – sehe