преобразование в тип значения 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_range в double преобразование)?

2

Решение

Способ выполнить то, что вы хотите, это специализация assign_to_attribute_from_iterators. Вы можете найти пример с пользовательским типом Вот. Если вы используете double как атрибут в вашем определении токена, Spirit внутренне использует qi::double_ разобрать значение. (Ты можешь найти Вот специализация для двойных и остальных основных типов).

Глупый пример, где я определяю real маркер как все, что не является , или ; показать разбор doubles.

#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;
};
2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector