2013-02-21 9 views
5

Ich versuche, meine eigene Grammatik mit boost Geist Rahmen zu definieren, und ich definieren eine solche passende Regel:Boost-Geist das ganze Spiel als String bekommen

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

Ich möchte eine Aktion assing - some_func - zu dem Teil davon, und übergeben Sie die gesamte passende Zeichenfolge als Parameter. Aber leider bekomme ich so etwas wie vector<boost::variant<boost::fusion::vector2 ..a lot of stuff...)...>. Kann ich irgendwie die ganzen Daten als char *, std :: string oder gar void * mit der Größe bekommen?

+0

was mit Vektor ist falsch ? –

+0

Ich beschreibe es als Vektor >>> aber es wurde von sehe bearbeitet. – Dejwi

Antwort

8

Blick auf qi::as_string:

Ausgabe der Demo-Programm:

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

Um ehrlich zu sein, es sieht aus wie Sie wirklich versuchen, 'wörtlich' Strings mit möglichen Flucht Zeichen zu analysieren. In der Hinsicht scheint die Verwendung von lexeme falsch (die Räume werden gegessen). Wenn Sie Beispiele für das Parsen von Escape-Strings sehen möchten, lesen Sie z.

Eine einfache Umlagerung, die ich denken kann gemacht werden, zumindest könnte folgendermaßen aussehen:

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

ist jedoch zu beachten, dass man einfach die Regel ohne Skipper erklären könnte und die lexeme fallen alltogether: http://liveworkspace.org/code/1oEhei$0

-Code (live auf 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 Ich würde früher mit 'as_string' antworten, aber konnte nicht für das Leben von mir finden es in den Dokumenten - 'Parser-Anweisungen', duh! – ildjarn

+0

Eine konkrete Illustration von dem, was ich denke, _needs_ in der Verwendung von 'Lexem' behoben werden soll. – sehe