FE 0.13.1
Header-only C++ frontend library
Loading...
Searching...
No Matches
fe::Parser< Tok, Tag, K, S > Class Template Reference

The blueprint for a recursive descent/ ascent parser using a K lookahead of Tokens. More...

#include <fe/parser.h>

Classes

class  Tracker
class  Anchor
 RAII helper that anchors a Tag for its lifetime; use Parser::anchor to build one. More...

Protected Member Functions

Construction
void init ()
Tracker

Track Location in the source file.

Use like this:

auto track = tracker();
auto foo = parse_foo();
auto bar = parse_bar();
auto foobar = new FooBar(track, foo, bar);
Tracker tracker()
Factory method to build a Parser::Tracker.
Definition parser.h:93
Tracker tracker ()
 Factory method to build a Parser::Tracker.
Tracker tracker (Pos begin)
 As above but start tracking at begin.
Tracker tracker (Loc begin)
Shift Token
Tok ahead (size_t i=0) const
Tok lex ()
 Invoke Lexer to retrieve next Token.
Tok accept (Tag tag)
 If Parser::ahead() is a tag, consume and return it, otherwise yield std::nullopt.
Tok expect (Tag tag, std::string_view ctxt)
 Parser::lex Parser::ahead() which must be a tag.
template<class... Args>
Tok expect (Tag tag, std::format_string< Args... > fmt, Args &&... args)
 As above but builds the context via std::format.
Tok eat (Tag tag)
 Consume Parser::ahead which must be a tag; asserts otherwise.
Anchor

An anchor is a Tag that an enclosing context is waiting for.

E.g., while parsing a parenthesized expression, ) is anchored: a nested parser must not swallow it but bail out, so the enclosing context can Parser::expect it. A ) that is not anchored, however, is simply bogus and Parser::recover discards it.

Anchor anchor (Tag tag)
 Factory method to build a Parser::Anchor; Parser::expect tag yourself at the end of the scope.
bool anchored (Tag tag) const
 Is tag anchored by an enclosing context?
template<std::predicate< Tag > P>
void recover (P pred, std::string_view ctxt)
 Parser::lex all Tokens whose Tag satisfies pred and that are not Parser::anchored; report each one as S::unanchored_err.
void recover (Tag tag, std::string_view ctxt)
 As above but only recovers from tag.
Diagnostics

The defaults S may replace with one of its own.

fe::Errorerror ()
const fe::Errorerror () const
void syntax_err (std::string_view what, Tok tok, std::string_view ctxt)
 Parser::expect did not find what while parsing ctxt.
void syntax_err (std::string_view what, std::string_view ctxt)
 As above but uses Parser::ahead as tok.
void syntax_err (Tag tag, std::string_view ctxt)
 As above but spells tag out via Parser::tag2str_.
void unanchored_err (Tok tok, std::string_view ctxt)
 Parser::recover discarded tok while parsing ctxt.

Static Protected Member Functions

static auto tag2str_ (Tag tag)
 Spells tag out via Tok::tag2str if there is one - a bare enumerator would render as its number.

Protected Attributes

Ring< Tok, K > ahead_
Loc curr_
std::deque< Tag > anchors_

Detailed Description

template<class Tok, class Tag, size_t K, class S>
requires std::is_default_constructible_v<Tok> && (std::is_convertible_v<Tok, bool> || std::is_constructible_v<bool, Tok>)
class fe::Parser< Tok, Tag, K, S >

The blueprint for a recursive descent/ ascent parser using a K lookahead of Tokens.

Parser::accept and Parser::expect indicate failure by constructing a Token with its default constructor. Hence, Tok must be default-constructible and testable as a bool (to check for that failure):

class Tok {
public:
enum class Tag {
Nil,
// ...
};
Tok() {} // default constructor yields the "failure" token
// ...
explicit operator bool() const { return tag_ != Tag::Nil; }
// ...
};
// Your Parser:
if (auto tok = accept(Tok::Tag::My_Tag)) {
do_something(tok);
}
Tok accept(Tag tag)
If Parser::ahead() is a tag, consume and return it, otherwise yield std::nullopt.
Definition parser.h:112

S must provide the Lexer to pull from and the Driver to report to:

class MyParser : public fe::Parser<Tok, Tok::Tag, K, MyParser> {
Lexer& lexer(); ///< Parser::lex pulls the next Tok%en from here.
fe::Driver& driver(); ///< The default diagnostics below land in its Driver::error.
friend fe::Parser<Tok, Tok::Tag, K, MyParser>; ///< Otherwise, these may be private.
};
The blueprint for a lexer with a buffer of K tokens to peek into the future (Lexer::ahead).
Definition lexer.h:30
The blueprint for a recursive descent/ ascent parser using a K lookahead of Tokens.
Definition parser.h:51
Use/derive from this class for "global" variables that you need all over the place.
Definition driver.h:22

Parser::syntax_err and Parser::unanchored_err come with a default; declare either in S to word it differently. All Parser::syntax_err overloads funnel through the one taking a what/Tok/ctxt; override just that one.

Warning
Declaring any syntax_err in S hides all of them, so add using Super::syntax_err;.

Definition at line 51 of file parser.h.

Member Function Documentation

◆ accept()

template<class Tok, class Tag, size_t K, class S>
Tok fe::Parser< Tok, Tag, K, S >::accept ( Tag tag)
inlineprotected

If Parser::ahead() is a tag, consume and return it, otherwise yield std::nullopt.

Definition at line 112 of file parser.h.

References ahead(), and lex().

◆ ahead()

template<class Tok, class Tag, size_t K, class S>
Tok fe::Parser< Tok, Tag, K, S >::ahead ( size_t i = 0) const
inlineprotected

Get lookahead.

Definition at line 101 of file parser.h.

References ahead_.

Referenced by accept(), eat(), expect(), expect(), init(), lex(), recover(), syntax_err(), syntax_err(), and tracker().

◆ anchor()

template<class Tok, class Tag, size_t K, class S>
Anchor fe::Parser< Tok, Tag, K, S >::anchor ( Tag tag)
inlinenodiscardprotected

Factory method to build a Parser::Anchor; Parser::expect tag yourself at the end of the scope.

Use like this:

if (accept(Tag::D_paren_l)) {
auto _ = this->anchor(Tag::D_paren_r);
auto expr = parse_expr();
expect(Tag::D_paren_r, "parenthesized expression");
return expr;
}
Tok expect(Tag tag, std::string_view ctxt)
Parser::lex Parser::ahead() which must be a tag.
Definition parser.h:119
Anchor anchor(Tag tag)
Factory method to build a Parser::Anchor; Parser::expect tag yourself at the end of the scope.
Definition parser.h:174

Definition at line 174 of file parser.h.

◆ anchored()

template<class Tok, class Tag, size_t K, class S>
bool fe::Parser< Tok, Tag, K, S >::anchored ( Tag tag) const
inlineprotected

Is tag anchored by an enclosing context?

Scans the innermost anchor first, but any enclosing context counts.

Definition at line 178 of file parser.h.

References anchors_.

Referenced by recover().

◆ eat()

template<class Tok, class Tag, size_t K, class S>
Tok fe::Parser< Tok, Tag, K, S >::eat ( Tag tag)
inlineprotected

Consume Parser::ahead which must be a tag; asserts otherwise.

Definition at line 134 of file parser.h.

References ahead(), and lex().

◆ error() [1/2]

template<class Tok, class Tag, size_t K, class S>
fe::Error & fe::Parser< Tok, Tag, K, S >::error ( )
inlineprotected

Definition at line 198 of file parser.h.

References fe::Error::error().

◆ error() [2/2]

template<class Tok, class Tag, size_t K, class S>
const fe::Error & fe::Parser< Tok, Tag, K, S >::error ( ) const
inlineprotected

Definition at line 199 of file parser.h.

References fe::Error::error().

◆ expect() [1/2]

template<class Tok, class Tag, size_t K, class S>
template<class... Args>
Tok fe::Parser< Tok, Tag, K, S >::expect ( Tag tag,
std::format_string< Args... > fmt,
Args &&... args )
inlineprotected

As above but builds the context via std::format.

Definition at line 127 of file parser.h.

References ahead(), and lex().

◆ expect() [2/2]

template<class Tok, class Tag, size_t K, class S>
Tok fe::Parser< Tok, Tag, K, S >::expect ( Tag tag,
std::string_view ctxt )
inlineprotected

Parser::lex Parser::ahead() which must be a tag.

Issue error with ctxt otherwise.

Definition at line 119 of file parser.h.

References ahead(), and lex().

◆ init()

template<class Tok, class Tag, size_t K, class S>
void fe::Parser< Tok, Tag, K, S >::init ( )
inlineprotected

Definition at line 59 of file parser.h.

References ahead(), ahead_, and curr_.

◆ lex()

template<class Tok, class Tag, size_t K, class S>
Tok fe::Parser< Tok, Tag, K, S >::lex ( )
inlineprotected

Invoke Lexer to retrieve next Token.

Definition at line 104 of file parser.h.

References ahead(), ahead_, curr_, and lex().

Referenced by accept(), eat(), expect(), expect(), lex(), and recover().

◆ recover() [1/2]

template<class Tok, class Tag, size_t K, class S>
template<std::predicate< Tag > P>
void fe::Parser< Tok, Tag, K, S >::recover ( P pred,
std::string_view ctxt )
inlineprotected

Parser::lex all Tokens whose Tag satisfies pred and that are not Parser::anchored; report each one as S::unanchored_err.

This turns an otherwise fatal Token into a mere error message and keeps the current parser going.

Definition at line 184 of file parser.h.

References ahead(), anchored(), and lex().

Referenced by recover().

◆ recover() [2/2]

template<class Tok, class Tag, size_t K, class S>
void fe::Parser< Tok, Tag, K, S >::recover ( Tag tag,
std::string_view ctxt )
inlineprotected

As above but only recovers from tag.

Definition at line 190 of file parser.h.

References recover().

◆ syntax_err() [1/3]

template<class Tok, class Tag, size_t K, class S>
void fe::Parser< Tok, Tag, K, S >::syntax_err ( std::string_view what,
std::string_view ctxt )
inlineprotected

As above but uses Parser::ahead as tok.

Definition at line 211 of file parser.h.

References ahead().

◆ syntax_err() [2/3]

template<class Tok, class Tag, size_t K, class S>
void fe::Parser< Tok, Tag, K, S >::syntax_err ( std::string_view what,
Tok tok,
std::string_view ctxt )
inlineprotected

Parser::expect did not find what while parsing ctxt.

Backtick what yourself if it is a literal token rather than a phrase.

Definition at line 203 of file parser.h.

◆ syntax_err() [3/3]

template<class Tok, class Tag, size_t K, class S>
void fe::Parser< Tok, Tag, K, S >::syntax_err ( Tag tag,
std::string_view ctxt )
inlineprotected

As above but spells tag out via Parser::tag2str_.

Definition at line 214 of file parser.h.

References ahead(), and tag2str_().

◆ tag2str_()

template<class Tok, class Tag, size_t K, class S>
auto fe::Parser< Tok, Tag, K, S >::tag2str_ ( Tag tag)
inlinestaticprotected

Spells tag out via Tok::tag2str if there is one - a bare enumerator would render as its number.

Definition at line 226 of file parser.h.

Referenced by syntax_err().

◆ tracker() [1/3]

template<class Tok, class Tag, size_t K, class S>
Tracker fe::Parser< Tok, Tag, K, S >::tracker ( )
inlineprotected

Factory method to build a Parser::Tracker.

Definition at line 93 of file parser.h.

References ahead(), and curr_.

◆ tracker() [2/3]

template<class Tok, class Tag, size_t K, class S>
Tracker fe::Parser< Tok, Tag, K, S >::tracker ( Loc begin)
inlineprotected

Definition at line 95 of file parser.h.

References fe::Loc::begin, and curr_.

◆ tracker() [3/3]

template<class Tok, class Tag, size_t K, class S>
Tracker fe::Parser< Tok, Tag, K, S >::tracker ( Pos begin)
inlineprotected

As above but start tracking at begin.

Definition at line 94 of file parser.h.

References curr_.

◆ unanchored_err()

template<class Tok, class Tag, size_t K, class S>
void fe::Parser< Tok, Tag, K, S >::unanchored_err ( Tok tok,
std::string_view ctxt )
inlineprotected

Parser::recover discarded tok while parsing ctxt.

Definition at line 217 of file parser.h.

Member Data Documentation

◆ ahead_

template<class Tok, class Tag, size_t K, class S>
Ring<Tok, K> fe::Parser< Tok, Tag, K, S >::ahead_
protected

Definition at line 233 of file parser.h.

Referenced by ahead(), init(), and lex().

◆ anchors_

template<class Tok, class Tag, size_t K, class S>
std::deque<Tag> fe::Parser< Tok, Tag, K, S >::anchors_
protected

Definition at line 235 of file parser.h.

Referenced by anchored().

◆ curr_

template<class Tok, class Tag, size_t K, class S>
Loc fe::Parser< Tok, Tag, K, S >::curr_
protected

Definition at line 234 of file parser.h.

Referenced by init(), lex(), tracker(), tracker(), and tracker().


The documentation for this class was generated from the following file: