我无法获取令牌的字符串值
I can't get the string value of a token
我尝试用Boost Spirit实现一个小编程语言的Lexer。
我必须得到一个令牌的值,我得到一个bad_get异常:
抛出'boost::bad_get'实例后终止调用
what(): boost::bad_get: failed value
我在执行
时得到这个异常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;
我的词法分析器定义如下:
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;
};
是否有其他方法来获取Token的值?
你总是可以使用'default'标记data(它是源迭代器类型的iterator_range)。
std::string tokenvalue(iter->value().begin(), iter->value().end());
在研究了boost存储库中的测试用例之后,我发现了许多事情:
- 这是由设计
- 有一个更简单的方法
- 更容易的方式在Lex语义操作(例如使用_1)和Qi中使用词法分析器令牌时自动实现;赋值将自动转换为Qi属性类型
- 这(确实)得到了文档 中提到的"懒惰,一次性,评估"语义。
问题在于令牌数据是可变的,它从原始输入迭代器范围开始。只有在'和'强制赋值之后,转换后的属性才缓存在变体中。您可以见证转换:
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
trait实现。
完整的工作演示:
#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;
}
相关文章:
- 是否可以在多行字符串文本中使用 C/C++ 预处理器令牌
- 如何在没有运算符>>的情况下从字符串流返回下一个令牌?
- 如何将字符串作为预处理器令牌传递
- 如何使用向量字符串令牌构建表达树
- C 令牌字符串并存储在向量中
- 在C 中的令牌字符串中区分操作数和操作员
- 为什么我的字符串令牌在我的C 野牛程序中最终减少时会获得新线
- 使用令牌解析字符串并分配给变量
- 将字符串拆分为令牌-不包含操作系统特定的函数
- C++:函数返回静态库中的字符串给出错误:在令牌之前':'预期的"="、""、";"、'asm'或'__attribute__'
- 当捕获boost::bad_exical_cast时,我可以访问要强制转换的字符串/令牌吗
- 如何避免在转换字符串令牌流时重复istringstream构造
- C++预处理器能否判断令牌是否为字符串
- C++:仅使用 STL 从字符串中提取令牌
- 如何使 Boost.Spirit.Lex 令牌值成为匹配序列的子字符串(最好通过正则表达式匹配组)
- 如何使"strtok function"一次使用多个令牌字符串? 函数指针会解决这个问题吗?
- C++ 基于/使用(提升)正则表达式拆分字符串以查找令牌
- 分析boost中的令牌时基础字符串的索引
- 获取令牌之间的子字符串
- 获取字符串令牌/参数作为解析