2012-11-13 19 views
5

के साथ समस्याएं मैं boost :: spirit का उपयोग करने के लिए सीखने का प्रयास करता हूं। ऐसा करने के लिए, मैं कुछ सरल लेक्सर बनाना चाहता था, उन्हें गठबंधन करना चाहता था और फिर आत्मा का उपयोग करके पार्सिंग शुरू करना चाहता था। मैंने उदाहरण को संशोधित करने का प्रयास किया, लेकिन यह अपेक्षित के रूप में नहीं चलता है (परिणाम आर सत्य नहीं है)।बूस्ट :: भावना :: लेक्स और व्हाइटस्पेस

यहाँ lexer है:

#include <boost/spirit/include/lex_lexertl.hpp> 

namespace lex = boost::spirit::lex; 

template <typename Lexer> 
struct lexer_identifier : lex::lexer<Lexer> 
{ 
    lexer_identifier() 
     : identifier("[a-zA-Z_][a-zA-Z0-9_]*") 
     , white_space("[ \\t\\n]+") 
    { 
     using boost::spirit::lex::_start; 
     using boost::spirit::lex::_end; 

     this->self = identifier; 
     this->self("WS") = white_space; 
    } 
    lex::token_def<> identifier; 
    lex::token_def<> white_space; 
    std::string identifier_name; 
}; 

और इस उदाहरण मैं चलाने के लिए कोशिश कर रहा हूँ है:

#include "stdafx.h" 

#include <boost/spirit/include/lex_lexertl.hpp> 
#include "my_Lexer.h" 

namespace lex = boost::spirit::lex; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    typedef lex::lexertl::token<char const*,lex::omit, boost::mpl::false_> token_type; 
    typedef lex::lexertl::lexer<token_type> lexer_type; 

    typedef lexer_identifier<lexer_type>::iterator_type iterator_type; 

    lexer_identifier<lexer_type> my_lexer; 

    std::string test("adedvied das934adf dfklj_03245"); 

    char const* first = test.c_str(); 
    char const* last = &first[test.size()]; 

    lexer_type::iterator_type iter = my_lexer.begin(first, last); 
    lexer_type::iterator_type end = my_lexer.end(); 

    while (iter != end && token_is_valid(*iter)) 
    { 
     ++iter; 
    } 

    bool r = (iter == end); 

    return 0; 
} 

आर तक सच के रूप में वहाँ स्ट्रिंग के अंदर केवल एक टोकन है। यह एक केस क्यों है?

सादर टोबियास

उत्तर

10

आप एक दूसरी lexer राज्य बनाया है, लेकिन यह कभी नहीं लाया।

सरल और लाभ:

this->self += identifier 
       | white_space [ lex::_pass = lex::pass_flags::pass_ignore ]; 
:


ज्यादातर मामलों के लिए, वांछित असर सबसे आसान तरीका एकल राज्य lexing उपयोग करने के लिए छोड़े जाने योग्य टोकन पर एक pass_ignore ध्वज के साथ होगा

ध्यान दें कि यह एक actor_lexer की आवश्यकता है अर्थ कार्रवाई के लिए अनुमति देने के लिए:

typedef lex::lexertl::actor_lexer<token_type> lexer_type; 
,210

पूर्ण नमूना:

#include <boost/spirit/include/lex_lexertl.hpp> 
#include <boost/spirit/include/lex_lexertl.hpp> 
namespace lex = boost::spirit::lex; 

template <typename Lexer> 
struct lexer_identifier : lex::lexer<Lexer> 
{ 
    lexer_identifier() 
     : identifier("[a-zA-Z_][a-zA-Z0-9_]*") 
     , white_space("[ \\t\\n]+") 
    { 
     using boost::spirit::lex::_start; 
     using boost::spirit::lex::_end; 

     this->self += identifier 
        | white_space [ lex::_pass = lex::pass_flags::pass_ignore ]; 
    } 
    lex::token_def<> identifier; 
    lex::token_def<> white_space; 
    std::string identifier_name; 
}; 

int main(int argc, const char *argv[]) 
{ 
    typedef lex::lexertl::token<char const*,lex::omit, boost::mpl::false_> token_type; 
    typedef lex::lexertl::actor_lexer<token_type> lexer_type; 

    typedef lexer_identifier<lexer_type>::iterator_type iterator_type; 

    lexer_identifier<lexer_type> my_lexer; 

    std::string test("adedvied das934adf dfklj_03245"); 

    char const* first = test.c_str(); 
    char const* last = &first[test.size()]; 

    lexer_type::iterator_type iter = my_lexer.begin(first, last); 
    lexer_type::iterator_type end = my_lexer.end(); 

    while (iter != end && token_is_valid(*iter)) 
    { 
     ++iter; 
    } 

    bool r = (iter == end); 
    std::cout << std::boolalpha << r << "\n"; 
} 

प्रिंटों

true 

एक स्किपर राज्य के रूप में "WS"


यह भी संभव है कि आप एक नमूना है कि के लिए दूसरा पार्सर राज्य का उपयोग करता है में आए कप्तान (lex::tokenize_and_phrase_parse)। इसके लिए एक कामकाजी नमूना बनाने के लिए मुझे एक मिनट या 10 मिनट दें।

#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/lex_lexertl.hpp> 
namespace lex = boost::spirit::lex; 
namespace qi = boost::spirit::qi; 

template <typename Lexer> 
struct lexer_identifier : lex::lexer<Lexer> 
{ 
    lexer_identifier() 
     : identifier("[a-zA-Z_][a-zA-Z0-9_]*") 
     , white_space("[ \\t\\n]+") 
    { 
     this->self  = identifier; 
     this->self("WS") = white_space; 
    } 
    lex::token_def<> identifier; 
    lex::token_def<lex::omit> white_space; 
}; 

int main() 
{ 
    typedef lex::lexertl::token<char const*, lex::omit, boost::mpl::true_> token_type; 
    typedef lex::lexertl::lexer<token_type> lexer_type; 

    typedef lexer_identifier<lexer_type>::iterator_type iterator_type; 

    lexer_identifier<lexer_type> my_lexer; 

    std::string test("adedvied das934adf dfklj_03245"); 

    { 
     char const* first = test.c_str(); 
     char const* last = &first[test.size()]; 

     // cannot lex in just default WS state: 
     bool ok = lex::tokenize(first, last, my_lexer, "WS"); 
     std::cout << "Starting state WS:\t" << std::boolalpha << ok << "\n"; 
    } 

    { 
     char const* first = test.c_str(); 
     char const* last = &first[test.size()]; 

     // cannot lex in just default state either: 
     bool ok = lex::tokenize(first, last, my_lexer, "INITIAL"); 
     std::cout << "Starting state INITIAL:\t" << std::boolalpha << ok << "\n"; 
    } 

    { 
     char const* first = test.c_str(); 
     char const* last = &first[test.size()]; 

     bool ok = lex::tokenize_and_phrase_parse(first, last, my_lexer, *my_lexer.self, qi::in_state("WS")[my_lexer.self]); 
     ok = ok && (first == last); // verify full input consumed 
     std::cout << std::boolalpha << ok << "\n"; 
    } 
} 
:

अद्यतन मुझे थोड़ा अधिक से कम 10 मिनट (waaaah) :) यहाँ एक तुलनात्मक परीक्षण, कैसे lexer राज्यों तरह व्यवहार करते हैं दिखा रहा है, और कैसे आत्मा स्किपर पार्स उपयोग करने के लिए दूसरा पार्सर राज्य आह्वान करने के लिए लिया

उत्पादन ** `एक स्किपर state` के रूप में" WS "के अंतर्गत डेमो के साथ" WS "राज्य दृष्टिकोण ** है

Starting state WS: false 
Starting state INITIAL: false 
true 
+0

जोड़ा गया। चीयर्स – sehe

+0

ओह। मैंने गलत टोकन_टाइप घोषणा की प्रतिलिपि बनाई है। ['HasState'] के लिए इसे 'mpl :: true_' की आवश्यकता है (http://www.boost.org/doc/libs/1_49_0/libs/spirit/doc/html/spirit/lex/abstracts/lexer_primitives/lexer_token_values.html # spirit.lex.abstracts.lexer_primitives.lexer_token_values.the_anatomy_of_a_token), जब राज्यव्यापी lexers से निपटने - जाहिर है! *** फिक्स्ड *** – sehe

+0

सबसे पहले - आपके व्यापक उदाहरण के लिए धन्यवाद। मेरे पास अभी भी कुछ प्रश्न हैं: लेक्स :: क्या करना है? और tokenize_and_parse कॉल के बारे में: my_lexer.self और qi :: in_state ("WS") [my_lexer.self] क्या है? –