2012-11-15 20 views
6

मैंने अपने पिछले उदाहरण पर काम जारी रखने और नियमों का विस्तार करने की कोशिश की। मेरी समस्या यह है कि ID_IDENTIFIER का उपयोग करने वाले नियम काम नहीं करते हैं - हालांकि मुझे पता है कि लेक्सर काम कर रहा है (इकाई परीक्षणों का उपयोग करके)।यह बढ़ावा क्यों देता है :: भावना :: qi नियम आवेग से मेल नहीं खाता है?

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

namespace qi = boost::spirit::qi; 
namespace lex = boost::spirit::lex; 

enum LexerIDs { ID_IDENTIFIER, ID_WHITESPACE, ID_INTEGER, ID_FLOAT, ID_PUNCTUATOR }; 

template <typename Lexer> 
struct custom_lexer : lex::lexer<Lexer> 
{ 
    custom_lexer() 
     : identifier ("[a-zA-Z_][a-zA-Z0-9_]*") 
     , white_space ("[ \\t\\n]+") 
     , integer_value ("[1-9][0-9]*") 
     , hex_value  ("0[xX][0-9a-fA-F]+") 
     , float_value ("[0-9]*\\.[0-9]+([eE][+-]?[0-9]+)?") 
     , float_value2 ("[0-9]+\\.([eE][+-]?[0-9]+)?") 
     , punctuator ("\\[|\\]|\\(|\\)|\\.|&>|\\*\\*|\\*|\\+|-|~|!|\\/|%|<<|>>|<|>|<=|>=|==|!=|\\^|&|\\||\\^\\^|&&|\\|\\||\\?|:|,")// [ ] () . &> ** * + - ~ !/% << >> < > <= >= == !=^& | ^^ && || ? : , 
    { 
     using boost::spirit::lex::_start; 
     using boost::spirit::lex::_end; 

     this->self.add 
      (identifier , ID_IDENTIFIER) 
      /*(white_space , ID_WHITESPACE)*/ 
      (integer_value, ID_INTEGER) 
      (hex_value , ID_INTEGER) 
      (float_value , ID_FLOAT) 
      (float_value2 , ID_FLOAT) 
      (punctuator , ID_PUNCTUATOR); 

     this->self("WS") = white_space; 
    } 
    lex::token_def<std::string> identifier; 
    lex::token_def<lex::omit> white_space; 
    lex::token_def<int>   integer_value; 
    lex::token_def<int>   hex_value; 
    lex::token_def<double>  float_value; 
    lex::token_def<double>  float_value2; 
    lex::token_def<>   punctuator; 
}; 

template< typename Iterator, typename Skipper> 
struct custom_grammar : qi::grammar<Iterator, Skipper> 
{ 

    template< typename TokenDef > 
    custom_grammar(const TokenDef& tok) : custom_grammar::base_type(ges) 
    { 
     ges = qi::token(ID_IDENTIFIER); 
     BOOST_SPIRIT_DEBUG_NODE(ges); 
    } 
    qi::rule<Iterator, Skipper > ges; 
}; 

int main(int argc, _TCHAR* argv[]) 
{ 
    std::string test("testidentifier"); 

    typedef char const* Iterator; 
    typedef lex::lexertl::token<Iterator, lex::omit, boost::mpl::true_> token_type; 
    typedef lex::lexertl::lexer<token_type> lexer_type; 
    typedef qi::in_state_skipper<custom_lexer<lexer_type>::lexer_def> skipper_type; 

    typedef custom_lexer<lexer_type>::iterator_type iterator_type; 

    custom_lexer<lexer_type> my_lexer; 
    custom_grammar<iterator_type, skipper_type> my_grammar(my_lexer); 

    Iterator first = test.c_str(); 
    Iterator last = &first[test.size()]; 

    bool r = lex::tokenize_and_phrase_parse(first,last,my_lexer,my_grammar,qi::in_state("WS")[ my_lexer.self ]); 

    std::cout << std::boolalpha << r << "\n"; 
    std::cout << "Remaining unparsed: '" << std::string(first,last) << "'\n"; 
    return 0; 
} 

ID_INTEGER के साथ एक समान नियम के लिए ठीक से मेल खाता है "1234"

+0

अच्छा, धन्यवाद। वह जवाब था। –

+0

@ पोस्टरिटी 'के हित में @ एलोनसमिज़ आप इसे उत्तर के रूप में पोस्ट करना चाहते हैं? @ टोबीस लैंगनर आप [स्पिरिट लेक्स: जो टोकन परिभाषा इस टोकन को उत्पन्न करते हैं) से जुड़े दस्तावेज से परामर्श लेना चाह सकते हैं (http://stackoverflow.com/questions/11106718/spirit-lex-which-token-definition-generated- यह- टोकन/11128252 # 11128252) – sehe

उत्तर

3

समस्या तरह से आप अपने गणना में अपने टोकन आईडी को परिभाषित में निहित है:

यहाँ उदाहरण है। यदि आप ऐसा करते हैं तो ID_IDENTIFIER को 0 का मान मिलता है और यह मान्य लेक्स टोकन आईडी नहीं है। सौभाग्य से Spirit.Lex एक मान boost::spirit::lex::min_token_id परिभाषित करता है जिसका उपयोग आप यह सुनिश्चित करने के लिए कर सकते हैं कि आपको वैध टोकन मिलें। इसका उपयोग करके आपका enum होगा:

enum LexerIDs { ID_IDENTIFIER=boost::spirit::lex::min_token_id+1, ID_WHITESPACE, ID_INTEGER, ID_FLOAT, ID_PUNCTUATOR }; 
संबंधित मुद्दे