gpt4 book ai didi

c++ - 我无法获取 token 的字符串值

转载 作者:可可西里 更新时间:2023-11-01 16:05:47 24 4
gpt4 key购买 nike

我尝试使用 Boost Spirit 为一种小型编程语言实现词法分析器。

我必须获取 token 的值,但出现了 bad_get 异常:

terminate called after throwing an instance of 'boost::bad_get'
what(): boost::bad_get: failed value get using boost::get Aborted

我在做的时候得到了这个异常:

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 的值?

最佳答案

您始终可以使用“默认” token 数据(即源迭代器类型的 iterator_range)。

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

在研究了 boost 存储库中的测试用例之后,我发现了一些事情:

  • 这是设计使然
  • 有更简单的方法
  • 更简单的方法在 Lex 语义操作(例如使用 _1)中以及在 Qi 中使用词法分析器标记时自动实现;赋值会自动转换为Qi属性类型
  • 这(确实)得到了文档中提到的“惰性、一次性、评估”语义

关键是 token 数据是变体,它从原始输入迭代器范围开始。只有在'a'强制赋值后,转换后的属性才会缓存在变体中。您可以见证转变:

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++ - 我无法获取 token 的字符串值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7765040/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com