gct*_*gct 5 c++ parsing c++11 std-function
我正在研究一个解析器组合库,我真的很喜欢我的解析器只是一个可调用的对象:
typedef std::function<parse_result(parse_stream)> parser;
Run Code Online (Sandbox Code Playgroud)
这使得解析器组合器很好,例如:
parser operator &(parser a, parser b) { return both(a,b); }
Run Code Online (Sandbox Code Playgroud)
但我想要两个功能:
1)我希望自动将字符串文字提升为解析器,以便您可以执行以下操作:
parser option = "<" & regexp("[^+>]+");
Run Code Online (Sandbox Code Playgroud)
2)我希望解析器有一个名称,我可以用它来进行错误格式化.在上面的"both"解析器的情况下,我可以打印我预期的a.name()和b.name().
到目前为止我尝试过的两个选项是
一个可调用的解析器类,这让我可以从字符串和std :: function实例构建,但是一般的callable必须首先转换为std :: function并从那里转换为解析器,而C++不会进行两次隐式转换
继承自std :: function所以我可以隐式转换函数,但这似乎有很多陷阱只是将callables转换为解析器.
有没有人对如何构建这个有任何想法?
你不需要 std 函数的原始 typedef ;你的解析器不仅仅是一个标准函数。
struct parser: std::function<parse_result(parse_stream)>{
using base = std::function<parse_result(parse_stream)>;
using base::base;
};
Run Code Online (Sandbox Code Playgroud)
这应该允许
parser p = []( parse_stream str ) { return parse_result(7); };
Run Code Online (Sandbox Code Playgroud)
因为我们使用继承构造函数来std::function公开parser.
虽然您可以覆盖:
parser operator&(parser a, parser b) { return both(a,b); }
Run Code Online (Sandbox Code Playgroud)
通过放入or&的命名空间来使用 typedef 版本,我建议不要这样做;标准中已经有讨论限制这种模板参数 ADL。对于裸类型,放置此类运算符重载的位置是明确的。parse_resultparse_streamparser
此外,某些类型不能在类外部重载,例如&=. 有了 astruct你就可以在那里做。
这些都没有修复
parser option = "<" & regexp("[^+>]+");
Run Code Online (Sandbox Code Playgroud)
因为这里的问题是右侧不知道左侧在做什么(除非regexp是返回解析器的函数)。
首先这样做:
struct parser: std::function<parse_result(parse_stream)>{
using base = std::function<parse_result(parse_stream)>;
parser( char const* str ):
base( [str=std::string(str)](parse_stream stream)->parse_result { /* do work */ } )
{}
parser( char c ):
base( [c](parse_stream str)->parse_result { /* do work */ } )
{}
using base::base;
};
Run Code Online (Sandbox Code Playgroud)
然后你可以添加
namespace parsing {
// parser definition goes here
inline namespace literals {
inline parser operator""_p( char const* str ) { return str; }
}
}
Run Code Online (Sandbox Code Playgroud)
meansusing namespace parsing::literals是"hello"_p一个尝试解析字符串的解析器"hello"。
| 归档时间: |
|
| 查看次数: |
192 次 |
| 最近记录: |