C++ 转换为令牌_def';s值类型

C++ 转换为令牌_def';s值类型,c++,boost,boost-spirit,boost-spirit-qi,boost-spirit-lex,C++,Boost,Boost Spirit,Boost Spirit Qi,Boost Spirit Lex,当我在词法分析器中定义 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); 那么,如何将字符串转换为正确的标记值类型的值(本例中为无符号int)?如果将自定义类型或浮点类型指定为标记值类型,会发生什么情况

当我在词法分析器中定义

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);

那么,如何将字符串转换为正确的标记值类型的值(本例中为
无符号int
)?如果将自定义类型或浮点类型指定为标记值类型,会发生什么情况?转换例程在哪里(我认为类似于从
boost::iterator\u range
double
转换的东西)?

实现所需的方法是专门化。您可以找到一个自定义类型的示例。如果您在令牌定义中使用
double
作为属性,spirit将在内部使用
qi::double
解析该值。(您可以找到double和其他基本类型的专门化)

愚蠢的例子,我将
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;
}

非常感谢。这太棒了!图书馆是如此的灵活,在最意想不到的情况下,它会为您提前考虑。我印象深刻…如何通过相应的正则表达式准确地表达?为了匹配他所有的案例,@Dukales我添加了我认为应该是基于该语法的标记定义。它在我的“愚蠢的例子”中起作用。FRAC的意思是,至少有一个数字放在点刺之前或之后。@Dukales我相信它现在更能代表语法。
#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;
}
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;
};