una separar por palabras palabra letras las frase extraer datos como comas caracteres cadena c++ boost boost-spirit boost-spirit-lex

separar - split cadena c++



No puedo obtener el valor de cadena de un token (1)

Siempre puede usar los datos del token ''predeterminado'' (que es iterator_range del tipo de iterador de origen).

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

Después de estudiar los casos de prueba en el repositorio de impulso, descubrí una serie de cosas:

  • esto es por diseño
  • Hay una manera más fácil
  • el camino más fácil viene automatizado en las acciones semánticas de Lex (por ejemplo, usando _1) y al usar el token lexer en Qi; la asignación se convertirá automáticamente al tipo de atributo Qi
  • esto tiene (de hecho) la semántica ''perezoso, de una sola vez, evaluación'' mencionado en los documentos

La gracia es que los datos del token son variantes, que comienzan como el rango del iterador de entrada sin formato. Solo después de la asignación " a " forzada, el atributo convertido se almacena en caché en la variante. Usted puede ser testigo de la transición:

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;

Como puede ver, la asignación de atributos se fuerza aquí, directamente utilizando la implementación de assign_to .

Demostración de trabajo completo:

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

Intento implementar un Lexer para un pequeño lenguaje de programación con Boost Spirit.

Tengo que obtener el valor de un token y obtengo una excepción bad_get:

finalizar llamado después de lanzar una instancia de ''boost :: bad_get''
what (): boost :: bad_get: valor fallido get using boost :: get Aborted

Obtengo esta excepción cuando hago:

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;

Mi lexer se define así:

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

¿Hay alguna otra forma de obtener el valor de un Token?