29template<
class Tok,
class Tag,
size_t K,
class S>
30requires(std::is_convertible_v<Tok, bool> || std::is_constructible_v<bool, Tok>) || std::is_default_constructible_v<Tok>
33 S& self() {
return *
static_cast<S*
>(
this); }
34 const S& self()
const {
return *
static_cast<const S*
>(
this); }
39 void init(
const std::filesystem::path* path) {
41 for (
size_t i = 0; i != K; ++i) ahead_[i] = self().lexer().lex();
42 curr_ =
Loc(path, {1, 1});
62 Loc loc()
const {
return {curr_.path, start_, curr_.finis}; }
64 operator Loc()
const {
return loc(); }
80 Tok
ahead(
size_t i = 0)
const {
return ahead_[i]; }
84 auto result = ahead();
86 ahead_.put(self().lexer().lex());
92 if (tag != ahead().tag())
return {};
98 Tok
expect(Tag tag, std::string_view ctxt) {
99 if (ahead().tag() == tag)
return lex();
100 self().syntax_err(tag, ctxt);
105 Tok
eat([[maybe_unused]] Tag tag) {
106 assert(tag == ahead().tag() &&
"internal parser error");
Tracker(Pos start, Loc &curr)
The blueprint for a recursive descent/ ascent parser using a K lookahead of Tokens.
Tracker tracker(Pos begin)
As above but start tracking at begin.
Tracker tracker(Loc begin)
Tok lex()
Invoke Lexer to retrieve next Token.
Tok eat(Tag tag)
Consume Parser::ahead which must be a tag; asserts otherwise.
Tok expect(Tag tag, std::string_view ctxt)
Parser::lex Parser::ahead() which must be a tag.
Tok accept(Tag tag)
If Parser::ahead() is a tag, consume and return it, otherwise yield std::nullopt.
Tracker tracker()
Factory method to build a Parser::Tracker.
Tok ahead(size_t i=0) const
void init(const std::filesystem::path *path)
A ring buffer with N elements.
Position in a source file; pass around as value.