2013-01-12 24 views
2

當我在詞法分析器限定轉換到token_def的值類型

typedef boost::mpl::vector<std::string, unsigned int, bool> 
      token_value_types; 
lex::token_def<unsigned int> lit_uint("[0-9]+", token_ids::lit_uint); 

,然後用它在一些語法如

primary_expr = 
     lexer.lit_uint 
    | lexer.true_or_false 
    | identifier 
    | '(' > expr > ')' 
    ; 

該字符串所以如何轉換爲正確令牌值的值鍵入(在這種情況下爲unsigned int)?如果將自定義類型或浮點類型指定爲令牌值類型,會發生什麼情況?轉換例程的存在在哪裏(我認爲類似boost::iterator_rangedouble轉換)?

回答

2

完成你想要的東西的方法是專精assign_to_attribute_from_iterators。您可以找到一個自定義類型here的示例。如果您在令牌定義中使用double作爲屬性,則spirit在內部使用qi::double_來解析該值。 (你可以找到here雙重和其他基本類型的專業化)。

傻的例子中我定義real令牌作爲任何不是一個,;顯示的double S中解析。

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

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


template <typename Lexer> 
struct my_lexer : lex::lexer<Lexer> 
{ 
    my_lexer() 
    { 
     real = "[^,;]*"; //anything that is not a , or ; is a real number 

     this->self=lex::token_def<lex::omit>(',')| ';'; 

     this->self.add(real); 
    } 
    lex::token_def<double> real; 
}; 


int main() 
{ 
    // the token type needs to know the iterator type of the underlying 
    // input and the set of used token value types 
    typedef lex::lexertl::token<std::string::iterator, 
     mpl::vector<double> > token_type; 

    // use actor_lexer<> here if your token definitions have semantic 
    // actions 
    typedef lex::lexertl::lexer<token_type> lexer_type; 

    // this is the iterator exposed by the lexer, we use this for parsing 
    typedef lexer_type::iterator_type iterator_type; 

    // create a lexer instance 
    std::string input("3.4,2,.4,4.,infinity,NaN,-3.8,1e2,1.5E3;"); 
    std::string::iterator s = input.begin(); 

    my_lexer<lexer_type> lex; 
    iterator_type b = lex.begin(s, input.end()); 

    // use the embedded token_def as a parser, it exposes its token value type 
    // as its parser attribute type 
    std::vector<double> result; 
    qi::rule<iterator_type,double()> number= lex.real; 
    qi::rule<iterator_type,std::vector<double>()> sequence= number >> *(',' >> number) >> ';'; 
    BOOST_SPIRIT_DEBUG_NODE(number); 
    BOOST_SPIRIT_DEBUG_NODE(sequence); 
    if (!qi::parse(b, lex.end(), sequence, result)) 
    { 
     std::cerr << "Parsing failed!" << std::endl; 
     return -1; 
    } 

    std::cout << "Parsing succeeded:" << std::endl; 
    for(auto& n : result) 
     std::cout << n << std::endl; 
    return 0; 
} 

編輯:我用正則表達式的經驗非常少,但我相信,定義等同於評論鏈接的語法令牌(我認爲應該有fractional_constant >> -exponent_part,而不是fractional_constant >> !exponent_part)會:

template <typename Lexer> 
struct my_lexer : lex::lexer<Lexer> 
{ 
    my_lexer() 
    { 
     this->self.add_pattern("SIGN","[\\+\\-]"); 
     this->self.add_pattern("NAN","(1\\.0#)?(?i:nan)(\\([^\\)]\\))?"); 
     this->self.add_pattern("INF","(?i:inf(inity)?)"); 
     this->self.add_pattern("DIGIT","[0-9]"); 
     this->self.add_pattern("FRACT_CONST","{DIGIT}*\\.{DIGIT}+|{DIGIT}+\\.?"); 
     this->self.add_pattern("EXP","[eE]{SIGN}?{DIGIT}+"); 

     real = "{SIGN}?({NAN}|{INF}|{FRACT_CONST}{EXP}?|{DIGIT}+{EXP})"; 

     this->self=lex::token_def<lex::omit>(',')| ';'; 

     this->self.add(real); 
    } 
    lex::token_def<double> real; 
}; 
+0

謝謝!這真是太棒了!圖書館非常靈活,它在最令人意想不到的情況下爲您提前思考。我印象深刻...... – Orient

+0

如何正確表達[語法](http://www.boost.org/doc/libs/1_52_0/libs/spirit/doc/html/spirit/qi/reference/numeric/real。 html#spirit.qi.reference.numeric.real._code__phrase_role__identifier__realpolicies__phrase ___ code_)通過相應的正則表達式?匹配他所有的案例。 – Orient

+1

@Dukales我已經添加了我認爲應該是基於該語法的令牌定義。它在我的「愚蠢的例子」中起作用。 – 2013-01-12 12:51:18