我正在关注boost :: spirit的快速入门指南,当我包含时,我收到此编译器警告:"此标头已弃用.请使用:boost/spirit/include/classic_core.hpp"我应该担心这个吗?
(快速入门指南:http://spirit.sourceforge.net/distrib/spirit_1_8_5/libs/spirit/doc/quick_start.html,与节目我试图编译这里的全部源:HTTP://spirit.sourceforge. net/distrib/spirit_1_8_5/libs/spirit/example/fundamental/number_list.cpp)
编辑:此外,当我尝试使用推荐的classic_core.hpp和classic_push_back_actor.hpp标头编译时,我得到以下编译器错误:
test7.cpp: In function 'bool parse_numbers(const char*, __gnu_debug_def::vector<double, std::allocator<double> >&)':
test7.cpp:18: error: 'real_p' was not declared in this scope
test7.cpp:18: error: 'push_back_a' was not declared in this scope
test7.cpp:23: error: 'space_p' was not declared in this scope
test7.cpp:23: error: 'parse' was not declared in this scope
Run Code Online (Sandbox Code Playgroud) 我正在寻找使用boost :: spirit :: lex编写词法分析器,但我能找到的所有示例似乎都假设您已将整个文件首先读入RAM.我想写一个不需要整个字符串在RAM中的词法分析器,这可能吗?或者我需要使用其他东西吗?
我尝试使用istream_iterator,但是boost会给我一个编译错误,除非我使用const char*作为迭代器类型.
例如,我能找到的所有例子基本上都是这样做的:
lex_functor_type< lex::lexertl::lexer<> > lex_functor;
// assumes entire file is in memory
char const* first = str.c_str();
char const* last = &first[str.size()];
bool r = lex::tokenize(first, last, lex_functor,
boost::bind(lex_callback_functor(), _1, ... ));
Run Code Online (Sandbox Code Playgroud)
另外,是否有可能以某种方式确定lex令牌的行/列号?
谢谢!
我的目标是让我的qi::grammar返回属性.spirit::lexer尽管如此,我在这方面遇到了很大的困难.
我希望用下面给定的语法,如果我用它来调用它spirit::qi::parse(begin, end, grammar, output);,struct ident output它将具有解析的lexeme的内容.
该错误似乎主要流出这一行: start %= lexer.identifier;
g++ -g -c -O0 -Wall -DBOOST_SPIRIT_DEBUG -DBOOST_SPIRIT_LEXERTL_DEBUG -DBOOST_SPIRIT_USE_PHOENIX_V3 -DBOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT reduced.cpp
Run Code Online (Sandbox Code Playgroud)
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/home/lex.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/lexer.hpp>
#include <boost/spirit/home/qi.hpp>
namespace spirit = boost::spirit;
struct ident {
std::string value;
};
BOOST_FUSION_ADAPT_STRUCT(ident,
(std::string, value)
)
struct my_lexer : spirit::lex::lexer< spirit::lex::lexertl::actor_lexer<> > {
spirit::lex::token_def<std::string> identifier;
};
struct my_grammar : spirit::qi::grammar<my_lexer::iterator_type, ident()> {
my_grammar(const …Run Code Online (Sandbox Code Playgroud) 我有以下规则boost::spirit:
typedef boost::tuple<int, int> Entry;
qi::rule<Iterator, Entry(), Skipper> entry;
entry = qi::int_ >> qi::int_;
Run Code Online (Sandbox Code Playgroud)
但第二个int没有写入元组.有没有办法让它工作而不必使用boost::fusion::tuple?
如果我使用它,它可以工作std::pair,为什么我不能使用boost::tuple?
这是一个完整的编译示例:
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/tuple.hpp>
#include <boost/tuple/tuple.hpp>
namespace qi = boost::spirit::qi;
// works:
// #include <boost/fusion/include/std_pair.hpp>
// typedef std::pair<int, int> Entry;
// doesn't work:
typedef boost::tuple<int, int> Entry;
template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, Entry(), Skipper> {
MyGrammar() : MyGrammar::base_type(entry) {
entry = qi::int_ >> qi::int_;
} …Run Code Online (Sandbox Code Playgroud) 在Boost :: Spirit中,如何expectation_failure从绑定的函数中触发Boost::Bind?
背景:我解析包含复杂条目的大文件.当一个条目与前一个条目不一致时,我想失败并抛出一个expectation_failure(包含正确的解析位置信息).当我解析一个条目时,我绑定了一个函数,该函数决定该条目是否与之前看到的内容不一致.
我编写了一个小玩具示例,说明了这一点.在这里,我只是想抛出expectation_failure时int10是不能分开的:
#include <iostream>
#include <iomanip>
#include <boost/spirit/include/qi.hpp>
#include <boost/bind.hpp>
#include <boost/spirit/include/classic_position_iterator.hpp>
namespace qi = boost::spirit::qi;
namespace classic = boost::spirit::classic;
void checkNum(int const& i) {
if (i % 10 != 0) // >> How to throw proper expectation_failure? <<
std::cerr << "ERROR: Number check failed" << std::endl;
}
template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, int(), Skipper> {
MyGrammar() : MyGrammar::base_type(start) {
start %= qi::eps …Run Code Online (Sandbox Code Playgroud) 我的目标是创建一个解决方法,以便我可以在Boost Spirit Qi语义操作中使用C++ 11 lambdas,同时仍然可以访问更多扩展的qi占位符集,例如qi :: _ pass或qi :: _ r1,必须从上下文对象手动提取它们.我希望避免为一些非平凡的解析逻辑编写Phoenix lambdas,更喜欢C++ 11 lambdas中更直接的C++语法和语义.
下面的代码代表了我有一个解决方法的想法.我的想法是使用phoenix :: bind绑定到lambda并将它传递给我需要的特定占位符.但是,我得到了一个极长的模板编译器错误(gcc 4.7.0,Boost 1.54),我没有专业知识来解释.我选择了我认为最相关的部分并将其发布在代码下方.
我想知道我是否可以使用Boost Spirit在此代码中尝试做什么,如果有人能为我解释错误消息并告诉我出了什么问题.
#include <string>
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace phoenix = boost::phoenix;
int main() {
std::string input{"test1 test2 test3 FOO!"};
typedef decltype(input.begin()) StringIter;
qi::rule<StringIter, std::string()> parser =
*(
qi::char_
[
phoenix::bind(
[] (char value) {
std::cerr << value << std::endl;
},
qi::_1
)
]
);
qi::parse(input.begin(), input.end(), parser);
}
Run Code Online (Sandbox Code Playgroud)
(注意:我知道这个代码执行的特定任务对于直接的Phoenix结构会更简单,或者甚至可以通过Boost Spirit更新直接允许单参数C++ …
我正在尝试使用on_errorBoost :: Spirit :: qi 的机制来找出解析失败的原因.
我在on_error函数中设置了一个断点,并且正在调用函数,但没有输出(nada,nothing,void,...).
简单on_error:
on_error<fail>(level1,
boost::phoenix::ref(std::cout) << "I've failed.\n"
);
Run Code Online (Sandbox Code Playgroud)
复杂on_error(来自不同的网站):
on_error<fail>
(
start,
boost::phoenix::ref(std::cout)
<< val("Error! Expecting ")
<< _4
<< val(" here: \"")
<< construct<std::string>(qi::_3, qi::_2)
<< val("\"")
<< std::endl
);
Run Code Online (Sandbox Code Playgroud)
这是我的类包含简单on_error:
template <typename Iterator, typename Skipper>
struct Event_Compound
: qi::grammar<Iterator, Skipper>
{
Event_Compound ()
: Event_Compound::base_type(start, "Compound-Event")
{
using qi::lexeme;
using qi::lit;
using namespace qi;
using boost::spirit::ascii::char_;
relational_operator =
lit("&&")[Matched_Relational_AND]
|| lit("||")[Matched_Relational_OR]
; …Run Code Online (Sandbox Code Playgroud) 我正在尝试std::array使用boost :: spirit的最新版本x3(包含在boost 1.54中)将数字列表解析为固定大小的容器.由于std::array具有必要的功能,因此它被检测为容器,但缺少插入功能,使其不兼容.这是我想要完成的一个简短示例:
#include <boost/spirit/home/x3.hpp>
#include <array>
#include <iostream>
#include <string>
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
typedef std::array<double, 3> Vertex;
int main(int, char**) {
using x3::double_;
using ascii::blank;
std::string input = "3.1415 42 23.5";
auto iter = input.begin();
auto vertex = x3::rule<class vertex, Vertex>{} =
double_ >> double_ >> double_;
Vertex v;
bool const res = x3::phrase_parse(iter, input.end(), vertex, blank, v);
if (!res || iter != input.end()) return EXIT_FAILURE;
std::cout << "Match:" …Run Code Online (Sandbox Code Playgroud) 所以,我已经编写了我的语法,并希望提供一些调试信息,如行号,以便能够使用我自己的调试器逐步生成生成的可执行代码.
经过一些谷歌搜索后,我发现可以完全定义规则中使用的标记类,如下所示:
x3::rule<class CodeLine, ast::InstructionOrDirectiveAndArgs> const code_line = "code_line";
auto const code_line_def = ...
class CodeLine {
public:
template <typename T, typename Iterator, typename Context>
inline void on_success(Iterator const& first, Iterator const& last, T& ast, Context const& context) {
static std::uint64_t line = 0;
auto& error_handler = x3::get<error_handler_tag>(context).get();
error_handler.tag(ast, first, last);
ast.line_no = line;
if (*last == '\0') {
line = 0;
} else {
line += 1;
}
}
};
Run Code Online (Sandbox Code Playgroud)
在这个完全定义的标记类中,可以实现on_success方法,该方法在成功匹配规则时调用.所以我为匹配一行代码的规则实现了标记类.但由于我找不到从精神中获取当前行号的方法,因此我采用了跟踪当前行的静态变量.问题是要知道何时重置行计数器,正如你在我非常愚蠢的尝试中看到的那样.
这似乎是一种非常复杂的方式来跟踪行号,因此必须有更好的方法.
现在的问题是,获得当前行号的最佳或正确方法是什么?
谢谢阅读!
我正在将一个手写的解析器迁移到Boost.Spirit(2.5.4).第一印象是积极的,但由于我使用C++ 17,X3似乎是一个非常有吸引力的选择.
幸运的是,有很多关于X3的资源:
然而:
所以我很担心:X3是个好赌注吗?不仅仅是维护,而且它与前一代产品相比还能保留其产品吗?
我的作业很糟糕,其他地方也有类似的问题: