2011-10-14 11 views
10

का स्ट्रिंग मान नहीं मिल रहा है, मैं बूस्ट स्पिरिट के साथ एक छोटी प्रोग्रामिंग भाषा के लिए लेक्सर को लागू करने का प्रयास करता हूं।मुझे टोकन

मैं एक टोकन का मान प्राप्त करने के लिए है और मैं एक bad_get अपवाद:

'को बढ़ावा देने :: bad_get' का एक उदाहरण फेंकने के बाद कहा जाता है को समाप्त
क्या(): बढ़ावा :: bad_get: में विफल रहा है मूल्य को बढ़ावा देने का उपयोग कर पाने :: निरस्त

मैं इस अपवाद प्राप्त हो जब कर रही:

std::string contents = "void"; 

base_iterator_type first = contents.begin(); 
base_iterator_type last = contents.end(); 

SimpleLexer<lexer_type> lexer; 

iter = lexer.begin(first, last); 
end = lexer.end(); 

std::cout << "Value = " << boost::get<std::string>(iter->value()) << std::endl; 

मेरे एल exer परिभाषित किया गया है कि:

typedef std::string::iterator base_iterator_type; 
typedef boost::spirit::lex::lexertl::token<base_iterator_type, boost::mpl::vector<unsigned int, std::string>> Tok; 
typedef lex::lexertl::actor_lexer<Tok> lexer_type; 

template<typename L> 
class SimpleLexer : public lex::lexer<L> { 
    private: 

    public: 
     SimpleLexer() { 
      keyword_for = "for"; 
      keyword_while = "while"; 
      keyword_if = "if"; 
      keyword_else = "else"; 
      keyword_false = "false"; 
      keyword_true = "true"; 
      keyword_from = "from"; 
      keyword_to = "to"; 
      keyword_foreach = "foreach"; 

      word = "[a-zA-Z]+"; 
      integer = "[0-9]+"; 
      litteral = "..."; 

      left_parenth = '('; 
      right_parenth = ')'; 
      left_brace = '{'; 
      right_brace = '}'; 

      stop = ';'; 
      comma = ','; 

      swap = "<>"; 
      assign = '='; 
      addition = '+'; 
      subtraction = '-'; 
      multiplication = '*'; 
      division = '/'; 
      modulo = '%'; 

      equals = "=="; 
      not_equals = "!="; 
      greater = '>'; 
      less = '<'; 
      greater_equals = ">="; 
      less_equals = "<="; 

      whitespaces = "[ \\t\\n]+"; 
      comments = "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"; 

      //Add keywords 
      this->self += keyword_for | keyword_while | keyword_true | keyword_false | keyword_if | keyword_else | keyword_from | keyword_to | keyword_foreach; 
      this->self += integer | litteral | word; 

      this->self += equals | not_equals | greater_equals | less_equals | greater | less ; 
      this->self += left_parenth | right_parenth | left_brace | right_brace; 
      this->self += comma | stop; 
      this->self += assign | swap | addition | subtraction | multiplication | division | modulo; 

      //Ignore whitespaces and comments 
      this->self += whitespaces [lex::_pass = lex::pass_flags::pass_ignore]; 
      this->self += comments [lex::_pass = lex::pass_flags::pass_ignore]; 
     } 

     lex::token_def<std::string> word, litteral, integer; 

     lex::token_def<lex::omit> left_parenth, right_parenth, left_brace, right_brace; 

     lex::token_def<lex::omit> stop, comma; 

     lex::token_def<lex::omit> assign, swap, addition, subtraction, multiplication, division, modulo; 
     lex::token_def<lex::omit> equals, not_equals, greater, less, greater_equals, less_equals; 

     //Keywords 
     lex::token_def<lex::omit> keyword_if, keyword_else, keyword_for, keyword_while, keyword_from, keyword_to, keyword_foreach; 
     lex::token_def<lex::omit> keyword_true, keyword_false; 

     //Ignored tokens 
     lex::token_def<lex::omit> whitespaces; 
     lex::token_def<lex::omit> comments; 
}; 

टोकन के मूल्य को पाने का कोई और तरीका है?

+3

फिर से पढ़ने पर, मुझे लगता है कि आपके द्वारा निर्दिष्ट 'लेक्स :: omit' टोकन विशेषता प्रकार के रूप में ध्यान दें। ये टोकन _any_ मान डेटा का खुलासा नहीं करेंगे (यहां तक ​​कि इटेटरेटर जोड़े भी नहीं)। यह आपकी समस्या हो सकती है। अन्यथा, मैं टोकन इटरेटर्स के शीर्ष पर क्यूई का उपयोग करके पार्सिंग की सलाह देता हूं: दोनों दुनिया के सर्वश्रेष्ठ प्राप्त करें। – sehe

+0

मैंने सत्यापित किया और दुख की बात यह समस्या नहीं है। मैं केवल बूस्ट :: एक टोकन पर अच्छा प्रकार का उपयोग करता हूं और उसके पास मूल्य होना चाहिए। –

उत्तर

9

आप हमेशा 'डिफ़ॉल्ट' टोकन डेटा (जो स्रोत इटरेटर प्रकार का iterator_range) का उपयोग कर सकते हैं।

std::string tokenvalue(iter->value().begin(), iter->value().end()); 

बढ़ावा भंडार में परीक्षण मामलों अध्ययन करने के बाद, मैं चीजों के एक नंबर पता चला:

  • इस डिजाइन के द्वारा होता है
  • एक आसान तरीका
  • आसान है लेक्स अर्थपूर्ण कार्यों (जैसे _1 का उपयोग करके) में स्वचालित रूप से आता है और क्यूई में लेक्सर टोकन का उपयोग करते समय; काम स्वचालित रूप से क्यूई में बदल जाएगा प्रकार
  • विशेषता यह (वास्तव में) है 'आलसी, एक बार, मूल्यांकन' अर्थ विज्ञान डॉक्स

चिंच कि टोकन डेटा प्रकार है है में उल्लेख किया गया है, जो कच्चे इनपुट इटरेटर रेंज के रूप में शुरू होता है। केवल 'के बाद मजबूर असाइनमेंट के बाद, रूपांतरित विशेषता को संस्करण में कैश किया जाता है।

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

assert(0 == iter->value().which()); 
std::cout << "Value = " << boost::get<boost::iterator_range<base_iterator_type> >(iter->value()) << std::endl; 

std::string s; 
boost::spirit::traits::assign_to(*iter, s); 
assert(1 == iter->value().which()); 
std::cout << "Value = " << s << std::endl; 

आप देख सकते हैं, विशेषता काम यहां मजबूर किया जाता है, सीधे assign_to विशेषता कार्यान्वयन का उपयोग: आप संक्रमण के गवाह कर सकते हैं।

पूर्ण काम कर प्रदर्शन:

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

#include <iostream> 
#include <string> 

namespace lex = boost::spirit::lex; 

typedef std::string::iterator base_iterator_type; 
typedef boost::spirit::lex::lexertl::token<base_iterator_type, boost::mpl::vector<int, std::string>> Tok; 
typedef lex::lexertl::actor_lexer<Tok> lexer_type; 

template<typename L> 
class SimpleLexer : public lex::lexer<L> { 
    private: 

    public: 
     SimpleLexer() { 
      word = "[a-zA-Z]+"; 
      integer = "[0-9]+"; 
      literal = "..."; 

      this->self += integer | literal | word; 
     } 

     lex::token_def<std::string> word, literal; 
     lex::token_def<int> integer; 
}; 

int main(int argc, const char* argv[]) { 
    SimpleLexer<lexer_type> lexer; 

    std::string contents = "void"; 

    base_iterator_type first = contents.begin(); 
    base_iterator_type last = contents.end(); 

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

    assert(0 == iter->value().which()); 
    std::cout << "Value = " << boost::get<boost::iterator_range<base_iterator_type> >(iter->value()) << std::endl; 

    std::string s; 
    boost::spirit::traits::assign_to(*iter, s); 
    assert(2 == iter->value().which()); 
    std::cout << "Value = " << s << std::endl; 

    return 0; 
} 
+0

आत्मा द्वारा किए जाने वाले किसी चीज़ के लिए थोड़ी अधिक जटिल लगती है। मेरे मामले में टोकन को उनके मूल्य प्राप्त करने के लिए टाइप किया जाता है, इसलिए मुझे मूल्य() से एक संस्करण मिलता है जो सीधे एक पुनरावर्तक नहीं होता है। मेरे पास एक int टोकन भी है। अपनी तकनीक के साथ, आप मूल्य() द्वारा प्रदान किए गए संस्करण का लाभ नहीं लेते हैं, नहीं? –

+1

क्या हिस्सा अधिक जटिल है? वह हिस्सा जहां उसने कहा था 'std :: string (iter-> मान()। प्रारंभ(), iter-> मान()। अंत()) '?मैंने इसे जादू नहीं दिया (आप उम्मीद करते हैं कि हम आपके लूओंग नमूने में '_get_' के लिए क्या मतलब है, और आप यह दिखाने के लिए 'शोटेकन' की 7 लाइनें पढ़ना नहीं चाहते हैं? एमएमएम।) मेरा नमूना शायद अधिक जटिल लगता है क्योंकि यह एक वास्तविक उदाहरण है कि इसे वास्तविक जीवन पार्सर में प्राप्त करने के लिए इसका उपयोग कैसे किया जाए, उदाहरण के लिए त्रुटि की सूचना देना। उन चीजों को दिखाने के लिए खेद है जो आपको रूचि नहीं देते :) – sehe

+0

जो चीज मुझे अधिक जटिल लगता है वह यह है कि हम हाथ से कुछ ऐसा करते हैं जो आत्मा को बढ़ावा देता है। अगर मेरे पास फ्लोट, इंट, स्ट्रिंग और बूल टोकन हैं और मैं उनके आदिम मूल्य प्राप्त करना चाहता हूं, तो मुझे पार्सिंग के 4 फ़ंक्शन बनाना होगा, नहीं? और आमतौर पर इन मानों को boost :: संस्करण में संग्रहीत किया जाता है। या शायद मैं मान() फ़ंक्शन के वापसी मान को समझ नहीं पा रहा हूं। –

संबंधित मुद्दे