I am implementing parser combinators by composing C++ lambdas.
For example:
// 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("\0"))
| (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";
where LexerRule is an alias for a std::function type.
Here is the header:
// rule_character.hpp
extern LexerRule character_name;
extern LexerRule character;
In main.cpp, however, a std::bad_function_call is being thrown:
// 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);
}
But target is 0 or nullptr. Why would this be so even if I'm sure that the two .cpp source files' respective .o object files are being linked? Why is my global lambda left uninitialized?