- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我已经开始研究基于 Boost.Spirit 的简单解析器,它将解析类似 C++ 的文件(唯一类似 C++ 的部分是内置模板类型;例如 map<string, smart_ptr<int>> name_object_map;
- 但这是内置的编译器,用户不能声明模板类)。尽管如此,语法旨在包含数据结构声明,而不是表达式,除了用于枚举器声明初始化的常量表达式; enum E { a = 4 * 5 + 3 };
已验证。这对我来说目前不是问题,因为我无法解析 E
我想要的方式:)
我昨天在阅读文档和示例后做了以下内容,但它没有编译:
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <cassert>
#include <memory>
#include <string>
#include <utility>
struct context {};
class foo {
std::string name;
const context *ctx;
public:
foo(const std::string &name, const context *ctx) : name(name), ctx(ctx) {}
};
using foo_ref = std::shared_ptr<foo>;
template <typename Iterator>
struct skipper : boost::spirit::qi::grammar<Iterator> {
skipper() : skipper::base_type(start) {
using namespace boost::spirit;
qi::char_type char_;
ascii::space_type space;
start = space // tab/space/cr/lf
| "/*" >> *(char_ - "*/") >> "*/" // C-style comments
;
}
boost::spirit::qi::rule<Iterator> start;
};
template <typename Iterator>
struct the_parser : boost::spirit::qi::grammar<Iterator, std::vector<foo_ref>(),
skipper<Iterator>> {
the_parser() : the_parser::base_type(start), current_context(&root) {
using namespace boost::spirit;
namespace phx = boost::phoenix;
identifier = qi::lexeme[qi::alpha >> *qi::alnum];
start = *(foo_decl); // currently, no semantic action attached.
// This will create the root decl in ast.
foo_decl = (lit("foo") >> identifier)[qi::_val = std::make_shared<foo>(
qi::_1, current_context)] >>
qi::char_('{') >> qi::char_('}') >> qi::char_(';');
BOOST_SPIRIT_DEBUG_NODES((identifier)(start)(foo_decl));
}
boost::spirit::qi::rule<Iterator, std::string(), skipper<Iterator>>
identifier;
boost::spirit::qi::rule<Iterator, std::vector<foo_ref>(), skipper<Iterator>>
start;
boost::spirit::qi::rule<Iterator, foo_ref(), skipper<Iterator>> foo_decl;
context root;
const context *current_context;
};
int main() {
the_parser<std::string::const_iterator> parser;
std::vector<foo_ref> root;
const std::string content = "foo john_doe { };";
auto first = content.cbegin(), last = content.cend();
bool r = boost::spirit::qi::phrase_parse(
first, last, parser, skipper<std::string::const_iterator>(), root);
assert(r && first == last);
}
在 Mac 上用 clang 编译(第一行是 std::make_shared
):
error: no matching constructor for initialization of 'foo'
__second_(_VSTD::forward<_Args2>(_VSTD::get<_I2>(__second_args))...)
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
note: candidate constructor not viable: no known conversion from 'const boost::phoenix::actor<boost::spirit::argument<0> >' to 'const std::string' (aka
'const basic_string<char, char_traits<char>, allocator<char> >') for 1st argument
foo(const std::string &name, const context *ctx) : name(name), ctx(ctx) {}
^
在foo_decl
s 语义 Action ,它不能构造一个 foo
(通过 std::make_shared
),因为第一个属性的结果无法转换为 std::string
.但是,如果我添加一个类成员 std::string s
,并改为执行此操作,它有效:
foo_decl = (lit("foo") >> identifier)[boost::phoenix::ref(s) = qi::_1] >>
qi::char_('{') >> qi::char_('}') >> qi::char_(';');
同样,如果我尝试 std::cout
它,我可以看到john_doe
打印出来。
如果我用 phoenix 绑定(bind)一个成员函数调用,它也有效:
foo_decl = (lit("foo") >> identifier)[qi::_val =
boost::phoenix::bind(&the_parser, this, qi::_1)] >>
qi::char_('{') >> qi::char_('}') >> qi::char_(';');
foo_ref make_foo(const std::string &n) {
return std::make_shared(n, current_context);
}
这最后三个解决方法意味着有一个来自 decltype(qi::_1)
的隐式转换序列至 std::string
;这不对吗?
如果您能指出我的错误或我对语义操作和占位符工作原理的理解上的差距,我将非常高兴。为什么std::make_shared
我觉得很奇怪不起作用。
谢谢!
最佳答案
首先:
我会避开 Spirit 中的智能指针
如果您不需要语义操作(您不需要),我会避开它们 Boost Spirit: "Semantic actions are evil"?
问题出在占位符上:不能静态使用,需要在惰性表达式中使用(凤凰 Actor )
使用第一个链接中的 phoenix::function:
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <cassert>
#include <memory>
#include <string>
#include <utility>
namespace {
template <typename T> struct make_shared_f {
template <typename... A> struct result { typedef std::shared_ptr<T> type; };
template <typename... A> typename result<A...>::type operator()(A &&... a) const {
return std::make_shared<T>(std::forward<A>(a)...);
}
};
template <typename T> using make_shared_ = boost::phoenix::function<make_shared_f<T> >;
}
struct context {};
class foo {
std::string name;
const context *ctx;
public:
foo(const std::string &name, const context *ctx) : name(name), ctx(ctx) {}
};
using foo_ref = std::shared_ptr<foo>;
template <typename Iterator> struct skipper : boost::spirit::qi::grammar<Iterator> {
skipper() : skipper::base_type(start) {
using namespace boost::spirit;
qi::char_type char_;
ascii::space_type space;
start = space // tab/space/cr/lf
| "/*" >> *(char_ - "*/") >> "*/" // C-style comments
;
}
boost::spirit::qi::rule<Iterator> start;
};
template <typename Iterator>
struct the_parser : boost::spirit::qi::grammar<Iterator, std::vector<foo_ref>(), skipper<Iterator> > {
the_parser() : the_parser::base_type(start), current_context(&root) {
using namespace boost::spirit;
namespace phx = boost::phoenix;
identifier = qi::alpha >> *qi::alnum;
// This will create the root decl in ast.
foo_decl = ("foo" >> identifier) [qi::_val = make_shared_<foo>{}(qi::_1, current_context)] >>
'{' >> '}' >> ';';
start = *foo_decl; // currently, no semantic action attached.
BOOST_SPIRIT_DEBUG_NODES((identifier)(start)(foo_decl));
}
boost::spirit::qi::rule<Iterator, std::string()> identifier;
boost::spirit::qi::rule<Iterator, foo_ref(), skipper<Iterator> > foo_decl;
boost::spirit::qi::rule<Iterator, std::vector<foo_ref>(), skipper<Iterator> > start;
context root;
const context *current_context;
};
int main() {
the_parser<std::string::const_iterator> parser;
std::vector<foo_ref> root;
const std::string content = "foo johndoe { };";
auto first = content.cbegin(), last = content.cend();
bool r = boost::spirit::qi::phrase_parse(first, last, parser, skipper<std::string::const_iterator>(), root);
if (r)
std::cout << "success\n";
else
std::cout << "failed\n";
if (first != last)
std::cout << "remaining unparsed: '" << std::string(first,last) << "'\n";
}
打印
success
连同
的调试输出<start>
<try>foo johndoe { };</try>
<foo_decl>
<try>foo johndoe { };</try>
<identifier>
<try>johndoe { };</try>
<success> { };</success>
<attributes>[[j, o, h, n, d, o, e]]</attributes>
</identifier>
<success></success>
<attributes>[0x60600000ebb0]</attributes>
</foo_decl>
<foo_decl>
<try></try>
<fail/>
</foo_decl>
<success></success>
<attributes>[[0x60600000ebb0]]</attributes>
</start>
关于c++ - 无法从 Boost.Spirit 中的占位符构造 std::string,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38221690/
我正在开发一个小型图书馆,我需要做的一件事是让访问者访问一些数据并返回结果。 在一些较旧的 C++ 代码中,访问者需要声明一个 typedef return_type .例如,boost::stati
我正在尝试使用std:map类型的键和值制作std::any Visual Studio 2017 std::map m("lastname", "Ivanov"); std::cout (m["la
我已经在 C++ 的 map 中声明了一个集合为 std::map> .如何循环访问或打印设定值? 最佳答案 如果你知道如何迭代 std::map或 std::set单独地,您应该可以毫无问题地组合迭
如何循环? 我已经试过了: //----- code std::vector >::iterator it; for ( it = users.begin(); it != users.end();
我有两个用例。 A.我想同步访问两个线程的队列。 B.我想同步两个线程对队列的访问并使用条件变量,因为其中一个线程将等待另一个线程将内容存储到队列中。 对于用例 A,我看到了使用 std::lock_
我正在查看这两种类型特征的文档,但不确定有什么区别。我不是语言律师,但据我所知,它们都适用于“memcpy-able”类型。 它们可以互换使用吗? 最佳答案 不,这些术语不能互换使用。这两个术语都表示
我有以下测试代码,其中有一个参数 fS,它是 ofstream 的容器: #include #include #include #include int
这是这个问题的延续 c++ function ptr in unorderer_map, compile time error 我试图使用 std::function 而不是函数指针,并且只有当函数是
std::unordered_map str_bool_map = { {"a", true}, {"b", false}, {"c", true} }; 我们可以在此映射上使
我有以下对象 std::vector> vectorList; 然后我添加到这个使用 std::vector vec_tmp; vec_tmp.push_back(strDRG); vec_tmp.p
为什么 std::initializer_list不支持std::get<> , std::tuple_size和 std::tuple_element ?在constexpr中用得很多现在的表达式,
我有一个像这样定义的变量 auto drum = std::make_tuple ( std::make_tuple ( 0.3f , Ex
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
问题 我正在尝试将 lambda 闭包传递给 std::thread,它使用任意封闭参数调用任意封闭函数。 template std::thread timed_thread(Function&& f
我想创建一个模板类,可以容纳容器和容器的任意组合。例如,std::vector或 std::map ,例如。 我尝试了很多组合,但我必须承认模板的复杂性让我不知所措。我编译的关闭是这样的: templ
我有一个 std::vector>我将其分配给相同类型的第二个 vector 。 我收到这个编译器错误: /opt/gcc-8.2.0/include/c++/8.2.0/bits/stl_algob
有时候,我们有一个工厂可以生成一个 std::unique_ptr vector ,后来我们想在类/线程/你命名的之间共享这些指针。因此,最好改用 std::shared_ptr 。当然有一种方法可以
这个问题在这里已经有了答案: Sorting a vector of custom objects (14 个答案) 关闭 6 年前。 我创建了一个 vector vector ,我想根据我定义的参
我有三个类(class)成员: public: std::vector > getObjects(); std::vector > getObjects() const; privat
我是一名优秀的程序员,十分优秀!