C++ 我能';无法获取令牌的字符串值
我试图用Boost Spirit为一种小编程语言实现一个Lexer 我必须获取令牌的值,但我得到了一个错误的\u get异常: 在抛出“boost::bad_get”实例后调用terminateC++ 我能';无法获取令牌的字符串值,c++,boost,boost-spirit,boost-spirit-lex,C++,Boost,Boost Spirit,Boost Spirit Lex,我试图用Boost Spirit为一种小编程语言实现一个Lexer 我必须获取令牌的值,但我得到了一个错误的\u get异常: 在抛出“boost::bad_get”实例后调用terminate what():boost::bad\u get:使用boost::get中止获取值失败 我在执行以下操作时获得此异常: std::string contents = "void"; base_iterator_type first = contents.begin(); base_iterator_t
what():boost::bad\u get:使用boost::get中止获取值失败 我在执行以下操作时获得此异常:
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;
std::string contents=“void”;
base_iterator_type first=contents.begin();
base_iterator_type last=contents.end();
SimpleLexer-lexer;
iter=lexer.begin(第一个,最后一个);
end=lexer.end();
std::cout self+=关键字|关键字|关键字|关键字|真|关键字|假|关键字|如果|关键字|其他|关键字|从|关键字|到|关键字| foreach;
这个->self+=整数| literal |字;
这->自我+=等于|不|等于|更大|等于|更少|更大|更少;
这个->self+=左|右|左|右|左|右|大括号;
这->自我+=逗号|停止;
这个->self+=赋值|交换|加|减|乘|除|模;
//忽略空白和注释
这->self+=空白[lex::_pass=lex::pass\u flags::pass\u ignore];
这->self+=注释[lex::\u pass=lex::pass\u flags::pass\u ignore];
}
lex::token_def word,literal,integer;
lex::token_def left_parenth,right_parenth,left_大括号,right_大括号;
lex::token_def stop,逗号;
标记定义赋值、交换、加法、减法、乘法、除法、模;
lex::token_def equals,not_equals,greater,less,greater_equals,less_equals;
//关键词
lex::token_def keyword_if、keyword_else、keyword_for、keyword_while、keyword_from、keyword_to、keyword_foreach;
lex::token_def keyword_true,keyword_false;
//忽略标记
lex::token_def空格;
lex::token_def注释;
};
是否有其他方法获取令牌的值?您始终可以使用“默认”令牌数据(这是源迭代器类型的迭代器范围) 在研究了boost存储库中的测试用例之后,我发现了一些事情:
- 这是故意的
- 有一个更简单的方法
- 在Lex语义操作中(例如使用_1)和在Qi中使用lexer标记时,更容易实现自动化;分配将自动转换为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;
看起来有点太复杂了,应该由精神来完成。在我的例子中,标记的类型化是为了获取它们的值,因此我从value()中获取变量,而不是直接从迭代器中获取变量。我还有一个int标记。使用您的技术,您不会利用value()提供的变量,否?哪一部分过于复杂?它所说的
std::string(iter->value().begin(),iter->value().end())
?我没有把它说清楚(你希望我们读入你的长篇样本来“理解”你的意思,你也不想读7行showtoken
来了解它是如何完成的?嗯。)我的样本可能看起来过于复杂了,因为它是一个完整的例子,说明了如何在现实生活中的解析器中使用它来实现,例如错误报告。很抱歉展示了你不感兴趣的东西:)我发现过于复杂的事情是,我们用手解析精神给予我们的东西。如果我有float、int、string和bool标记,我想得到它们的基本值,我必须创建4个解析函数,不是吗?通常这些值存储在boost::variant中。或者我不理解value()函数的返回值。我怀疑您可能误解了Lexer的用法。Lexer解析为标记(根据定义,这些标记只是源迭代器范围)。如果你想要简单而自动的值提取,可以使用灵气(当然,Lexer令牌可以提供给您。将在一点时间内更新答案。我已经计算出了进行求值的条件。我希望这些信息有帮助。再次阅读时,我注意到您指定lex::omit
作为令牌属性类型。这些令牌不会公开任何值数据(甚至不会公开迭代器对)。这可能是你的问题。否则,我衷心建议在令牌迭代器之上使用Qi进行解析:充分利用这两个方面。我验证了这一点,但遗憾的是,这不是问题所在。我只使用boost::get对一个类型良好且应该具有值的令牌进行解析。
std::string tokenvalue(iter->value().begin(), iter->value().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(1 == iter->value().which());
std::cout << "Value = " << s << std::endl;
#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;
}