我通过组成C lambdas来实现解析器组合。
例如:
// rule_character.cpp
#include "rule_character.hpp"
LexerRule character_name =
(make_terminal("alarm") & replace_with("a")
| (make_terminal("backspace") & replace_with("b"))
| (make_terminal("delete") & replace_with("x7f"))
| (make_terminal("escape") & replace_with("x1b"))
| (make_terminal("newline") & replace_with("n"))
| (make_terminal("null") & replace_with(" "))
| (make_terminal("return") & replace_with("r"))
| (make_terminal("space") & replace_with(" "))
| (make_terminal("tab") & replace_with("t"))) / "character-name";
LexerRule character =
((make_terminal("#\") & ignore_string) +
(character_name
| ((make_terminal("x") & ignore_string)
+ (hex_scalar_value & replace_hex_scalar_value))
| (make_class([](char c) { return true; }, "any-character"))))
/ "character";
其中LexerRule
是std::function
类型的别名。
这是标题:
// rule_character.hpp
extern LexerRule character_name;
extern LexerRule character;
在main.cpp
中,正在抛出std::bad_function_call
:
// main.cpp
// When: you try to parse a series of identifier
skip_ws(lex);
// When: you try to parse a string
std::cout << (void*)(rules::character.target<LexResult (*) (LexerInput&)>() )
<< std::endl;
LexResult result = rules::character(lex);
while (result.is_token()) {
results.push_back(result);
skip_ws(lex);
result = rules::character(lex);
}
但是target
是0
或nullptr
。即使我确定两个 .cpp
源文件的各自的 .o
对象文件正在链接,为什么还会如此?为什么我的全球lambda剩下非专业化?
问题与静态初始化顺序有关。由于Lambdas经常彼此依靠已经以特定顺序初始化,因此初始化不会发生,并且全局lambdas将保持无效状态,从而在运行时导致std::bad_function_call
异常。
为了解决问题,我将全局lambda变量的初始化移至运行时。