使用 X3 的解析器依赖注入
Dependency injection of parsers using X3
有时我在解析器之间有紧密的耦合/循环依赖。我可能有这样的东西:
parser.hpp
#pragma once
namespace parser {
using a_type = x3::rule<class a_class>;
a_type const a = "a";
using b_type = x3::rule<class b_class>;
b_type const b = "b";
auto const a_def = "(" >> b >> ")";
auto const b_def = "<" >> a >> ">";
BOOST_SPIRIT_DEFINE(a, b);
}
但是,我想将它们分成不同的 headers,因为这将在我进行单元测试时缩短编译时间,并且有多个 header 文件(而不是一个整体文件) .实际上,我有的不仅仅是 2 个解析器。
我希望能够做这样的事情:
a.hpp
#pragma once
#include "b.hpp"
namespace parser {
using a_type = x3::rule<class a_class>;
a_type const a = "a";
auto const a_def = "(" >> b_wrapper<a>::b >> ")";
BOOST_SPIRIT_DEFINE(a);
}
b.hpp
#pragma once
namespace parser {
template <auto Injected>
struct b_wrapper {
using b_type = x3::rule<class b_class>;
static b_type const b = "b";
static auto const b_def = "(" >> Injected >> ")";
BOOST_SPIRIT_DEFINE(b);
};
}
这自然不行。如何使用解析器实现依赖注入?
我不关心注入的确切语法。但是,我真的需要这些点:
- 能够测试 a.hpp 和 b.hpp 而无需同时包含两个 header test-files(
a
也可以很容易地注入其依赖项)
- 能够用另一个解析器替换注入的解析器以简化测试
如果我每次注入不同的解析器时都必须有一堆样板,我也没关系。
您可以通过函数生成 foo_def
对象。也就是说,b.hpp 看起来像这样:
#pragma once
namespace parser {
template <typename Injected>
auto b_impl(Injected const& injected) {
return "(" >> injected >> ")";
}
}
在你想注入实际解析器的地方,你可以这样做:
using b_type = x3::rule<class b_class>;
b_type const b = "b";
auto const b_def = b_impl(a);
BOOST_SPIRIT_DEFINE(b);
请注意,当您要创建解析器时,仍然存在一些样板文件。
有时我在解析器之间有紧密的耦合/循环依赖。我可能有这样的东西:
parser.hpp
#pragma once
namespace parser {
using a_type = x3::rule<class a_class>;
a_type const a = "a";
using b_type = x3::rule<class b_class>;
b_type const b = "b";
auto const a_def = "(" >> b >> ")";
auto const b_def = "<" >> a >> ">";
BOOST_SPIRIT_DEFINE(a, b);
}
但是,我想将它们分成不同的 headers,因为这将在我进行单元测试时缩短编译时间,并且有多个 header 文件(而不是一个整体文件) .实际上,我有的不仅仅是 2 个解析器。
我希望能够做这样的事情:
a.hpp
#pragma once
#include "b.hpp"
namespace parser {
using a_type = x3::rule<class a_class>;
a_type const a = "a";
auto const a_def = "(" >> b_wrapper<a>::b >> ")";
BOOST_SPIRIT_DEFINE(a);
}
b.hpp
#pragma once
namespace parser {
template <auto Injected>
struct b_wrapper {
using b_type = x3::rule<class b_class>;
static b_type const b = "b";
static auto const b_def = "(" >> Injected >> ")";
BOOST_SPIRIT_DEFINE(b);
};
}
这自然不行。如何使用解析器实现依赖注入?
我不关心注入的确切语法。但是,我真的需要这些点:
- 能够测试 a.hpp 和 b.hpp 而无需同时包含两个 header test-files(
a
也可以很容易地注入其依赖项) - 能够用另一个解析器替换注入的解析器以简化测试
如果我每次注入不同的解析器时都必须有一堆样板,我也没关系。
您可以通过函数生成 foo_def
对象。也就是说,b.hpp 看起来像这样:
#pragma once
namespace parser {
template <typename Injected>
auto b_impl(Injected const& injected) {
return "(" >> injected >> ")";
}
}
在你想注入实际解析器的地方,你可以这样做:
using b_type = x3::rule<class b_class>;
b_type const b = "b";
auto const b_def = b_impl(a);
BOOST_SPIRIT_DEFINE(b);
请注意,当您要创建解析器时,仍然存在一些样板文件。