|
FE 0.15.0
A C++23 toolkit for writing compiler/interpreter frontends.
|
The blueprint for a lexer with a buffer of K tokens to peek into the future (Lexer::ahead).
More...
#include <fe/lexer.h>
Classes | |
| struct | Ahead |
| A decoded code point together with the byte range it occupies. More... | |
Public Member Functions | |
| Lexer (std::string_view buf) | |
| Lexer (const Src &src) | |
Protected Member Functions | |
| Lexer (std::string_view buf, const Src *src) | |
| Delegate here to funnel both of the above into a single ctor of your own. | |
| char32_t | ahead (size_t i=0) const |
| Loc | peek () const |
| Location of the next character to be consumed (Lexer::ahead()); empty once the buffer is exhausted. | |
| void | start () |
| Invoke before assembling the next token. | |
Text | |
What has been lexed since Lexer::start. The whole source sits in Lexer::buf_, so Lexer::loc_ already is the token and Lexer::view costs nothing. | |
| std::string_view | view () const |
| std::string | lower () const |
| Lexer::view, case-folded - what a case-insensitive language like FORTRAN or SQL wants to intern. | |
| std::string | upper () const |
| std::string | fold (char32_t(*f)(char32_t) noexcept) const |
Accept | |
| char32_t | next () |
| Get next char32_t in Lexer::buf_ and extend Lexer::loc_ to cover it. | |
| bool | accept (auto pred) |
Accept next character in Lexer::buf_ and Lexer::next it, if pred holds. | |
| bool | accept (char32_t c) |
| bool | accept (char c) |
| bool | accept (char8_t c) |
| std::string_view | accept_while (auto pred) |
Lexer::next as long as pred holds. | |
| std::string_view | accept_while_none_of (char8_t a, char8_t b) |
Lexer::next up to - but not including - the next byte that is a or b. | |
| std::string_view | accept_while_none_of (char8_t a) |
| As Lexer::accept_while_none_of(char8_t, char8_t), but a single stop byte, which one memchr finds outright. | |
| std::string_view | accept_while_none_of (char a) |
| std::string_view | accept_while_none_of (char a, char b) |
| std::string_view | accept_until (std::string_view seq) |
Lexer::next up to - but not including - the next occurrence of seq. | |
Recover | |
Lexer::next input that cannot be part of a token, report it, and keep the current lexer going. Invoke after Lexer::start, so Lexer::loc_ spans exactly what was discarded. | |
| bool | recover_utf8 () |
| void | recover_char () |
| One character, reported as S::char_err. | |
Diagnostics | |
The defaults Each yields the Error it reported into, so a Note can be chained. | |
| fe::Error & | error () |
| const fe::Error & | error () const |
| fe::Error & | utf8_err () |
| Lexer::recover_utf8 discarded the malformed bytes at Lexer::loc_. | |
| fe::Error & | char_err (char32_t c) |
Lexer::recover_char discarded c at Lexer::loc_. | |
Protected Attributes | |
| std::string_view | buf_ |
| const Src * | src_ |
| size_t | cursor_ = 0 |
| Byte offset of the first not yet decoded character. | |
| Ring< Ahead, K > | ahead_ |
| Loc | loc_ |
| Location of the token we are currently constructing - see Lexer::view. | |
The blueprint for a lexer with a buffer of K tokens to peek into the future (Lexer::ahead).
You can "override" Lexer::next via CRTP (S is the child). The whole source has to sit in buf: a Pos is an index into it, so there is nothing left to keep track of - Lexer::next just hands out the byte range the code point it consumed occupied. S must provide somewhere to report to:
Lexer::utf8_err and Lexer::char_err come with a default; declare either in S to word it differently.
| struct fe::Lexer::Ahead |
|
inline |
|
inlineprotected |
Accept next character in Lexer::buf_ and Lexer::next it, if pred holds.
Definition at line 97 of file lexer.h.
References ahead().
Referenced by recover_utf8().
|
inlineprotected |
|
inlineprotected |
|
inlineprotected |
|
inlineprotected |
Lexer::next up to - but not including - the next occurrence of seq.
Where Lexer::accept_while_none_of takes a set of bytes, this one takes a sequence: only seq, spelled in exactly that order, ends the run - which is what closes a /* comment. Stops at the end of Lexer::buf_ if seq never shows up.
|
inlineprotected |
Lexer::next as long as pred holds.
An ASCII run is taken straight out of Lexer::buf_ - no code point is decoded and the lookahead is re-primed once at the end, which is what makes scanning an identifier or a stretch of white space cost a compare per byte. A character beyond ASCII falls back to Lexer::next, so pred may match one.
Definition at line 116 of file lexer.h.
References ahead(), ahead_, buf_, cursor_, fe::Loc::end, loc_, fe::Pos::off, and fe::Pos::Pos().
|
inlineprotected |
Definition at line 165 of file lexer.h.
References accept_while_none_of().
Referenced by accept_while_none_of().
|
inlineprotected |
Definition at line 166 of file lexer.h.
References accept_while_none_of().
Referenced by accept_while_none_of().
|
inlineprotected |
As Lexer::accept_while_none_of(char8_t, char8_t), but a single stop byte, which one memchr finds outright.
|
inlineprotected |
Lexer::next up to - but not including - the next byte that is a or b.
The stop bytes are a set: whichever comes first ends the run, and this is no substring search. Stops at the end of Lexer::buf_ if none of them ever shows up. No UTF-8 sequence spells an ASCII byte, so such a run needs no decoding at all: this is how to skip a comment or a string literal, where Lexer::accept_while pays a compare - and Lexer::next a whole utf8::decode - per character.
a or b either.
|
inlineprotected |
Definition at line 58 of file lexer.h.
References ahead_.
Referenced by accept(), accept_while(), and recover_char().
Lexer::recover_char discarded c at Lexer::loc_.
Definition at line 221 of file lexer.h.
References fe::Error::e(), error(), and loc_.
Definition at line 209 of file lexer.h.
Referenced by char_err(), and utf8_err().
|
inlineprotected |
|
inlineprotected |
Lexer::view, case-folded - what a case-insensitive language like FORTRAN or SQL wants to intern.
Definition at line 74 of file lexer.h.
References fold(), and fe::utf8::tolower().
|
inlineprotected |
Get next char32_t in Lexer::buf_ and extend Lexer::loc_ to cover it.
Definition at line 91 of file lexer.h.
References ahead_, fe::Loc::end, and loc_.
|
inlineprotected |
|
inlineprotected |
|
inlineprotected |
|
inlineprotected |
Definition at line 75 of file lexer.h.
References fold(), and fe::utf8::toupper().
Lexer::recover_utf8 discarded the malformed bytes at Lexer::loc_.
Definition at line 213 of file lexer.h.
References fe::Error::e(), error(), and loc_.
|
inlineprotected |
Definition at line 70 of file lexer.h.
References fe::Loc::begin, buf_, loc_, fe::Pos::off, and fe::Loc::size().
Referenced by fold().
Definition at line 232 of file lexer.h.
Referenced by accept_until(), accept_while(), accept_while_none_of(), accept_while_none_of(), ahead(), Lexer(), next(), and peek().
|
protected |
Definition at line 229 of file lexer.h.
Referenced by accept_until(), accept_while(), accept_while_none_of(), accept_while_none_of(), Lexer(), and view().
|
protected |
Byte offset of the first not yet decoded character.
Definition at line 231 of file lexer.h.
Referenced by accept_while(), and Lexer().
Location of the token we are currently constructing - see Lexer::view.
Definition at line 233 of file lexer.h.
Referenced by accept_while(), char_err(), next(), start(), utf8_err(), and view().