37 : m_iterator{iterator}, m_end{
end} {}
40 [[nodiscard]]
auto at_end() const noexcept ->
bool {
return m_iterator >= m_end; }
43 throw std::runtime_error(
"Can't dereference at end");
44 return m_iterator.operator->();
48 throw std::runtime_error(
"Can't dereference at end");
49 return m_iterator.operator*();
55 throw std::runtime_error(
"Can't increment past end");
62 throw std::runtime_error(
"Can't increment past end");
138 constexpr TokenRange(
auto&& begin,
int end) : m_span{begin.base(), static_cast<size_t>(
end)} {}
141 operator span<Token>()
const {
return m_span; }
163 template <
typename T,
typename U>
static auto ts(T&& begin, U&&
end) -> span<Token> {
164 return TokenRange{std::forward<T>(begin), std::forward<U>(
end)};
168 return span<Token>{entry.base(),
tokens.
begin().base()};
172 return std::make_unique<T>(span<Token>{entry.base(),
tokens.
begin().base()}, std::forward<Args>(args)...);
176 return std::make_unique<T>(
static_cast<span<Token>
>(range), std::forward<Args>(args)...);
180 return T(span<Token>{entry.base(),
tokens.
begin().base()}, std::forward<Args>(args)...);
196 const static array OPERATORS = {
206 const static vector UNARY_OPERATORS = {
211 return UNARY_OPERATORS;
255 template <
typename T, std::convertible_to<T> U>
262 vec.emplace_back((this->*action)());
269 template <
typename T, std::convertible_to<T> U>
278 vec.emplace_back((this->*action)());
294 static auto is_uword(string_view word) ->
bool {
return isupper(word.front()) != 0; }
351 if constexpr (N == ops.size()) {
354 auto left = parse_operator<N + 1>();
356 auto found_operator =
false;
357 for (
const auto& op : ops[N]) {
359 auto right = parse_operator<N + 1>();
360 auto args = vector<AnyExpr>{};
361 args.emplace_back(move(left));
362 args.emplace_back(move(right));
363 left = ast_ptr<CallExpr>(entry,
string(std::get<Atom>(op)), std::nullopt, move(args));
364 found_operator =
true;
Atoms represent strings in a string pool.
Expressions have an associated value and type.
Statements make up most things in source code.
An iterator-like holding Tokens, used when parsing.
auto operator->() const -> Token *
auto end() const -> VectorTokenIterator
auto operator++() -> TokenIterator &
auto operator*() const -> Token
TokenIterator(const VectorTokenIterator &iterator, const VectorTokenIterator &end)
auto operator+(int i) const noexcept -> TokenIterator
auto begin() const -> VectorTokenIterator
Returns the underlying iterator. This shouldn't really be needed but I'm too lazy to properly model a...
auto operator++(int) -> TokenIterator
auto operator-(int i) const noexcept -> TokenIterator
auto at_end() const noexcept -> bool
Check if the iterator is at the end and no more Tokens could possibly be read.
A type annotation. This (ast::Type) is distinct from the actual type of a value (ty::Type).
constexpr TokenRange(auto &&begin, int end)
constexpr TokenRange(auto &&begin, auto &&end)
static const TokenAtom KWD_TYPE
static const TokenAtom KWD_DEF
static const TokenAtom SYM_RBRACKET
static const TokenAtom SYM_DOLLAR
static const TokenAtom KWD_SELF_ITEM
static const TokenAtom KWD_IF
static const TokenAtom SYM_COMMA
static const TokenAtom SYM_PLUS
static const TokenAtom SYM_SLASH_SLASH
static const TokenAtom SYM_COLON
static const TokenAtom KWD_INTERFACE
static const TokenAtom SYM_PERCENT
static const TokenAtom KWD_LET
static const TokenAtom KWD_STRUCT
static const TokenAtom SYM_STAR
static const TokenAtom KWD_VARARGS
static const TokenAtom SYM_LBRACE
static const TokenAtom SYM_GT
static const TokenAtom KWD_PRIMITIVE
static const TokenAtom SYM_AT
static constexpr auto Word
static const TokenAtom SYM_NEQ
static const TokenAtom KWD_THEN
static const TokenAtom SYM_RPAREN
static const TokenAtom KWD_CONST
static const TokenAtom SYM_DOT
static const TokenAtom SYM_LPAREN
static const TokenAtom SYM_EQ_EQ
static const TokenAtom SYM_LT
static const TokenAtom KWD_PTR
static const TokenAtom KWD_NEW
static const TokenAtom SYM_COLON_COLON
static const TokenAtom SYM_EQ
static const TokenAtom SYM_MINUS
static const TokenAtom KWD_SELF_TYPE
static const TokenAtom KWD_WHILE
static const TokenAtom KWD_TRUE
static const TokenAtom SYM_BANG
static const TokenAtom SYM_ARROW
static const TokenAtom KWD_ABSTRACT
static const TokenAtom KWD_END
static const TokenAtom SYM_AND
static const TokenAtom KWD_IS
static const TokenAtom KWD_EXTERN
static const TokenAtom SYM_AND_AND
static const TokenAtom KWD_ELSE
static const TokenAtom KWD_RETURN
static const TokenAtom KWD_MUT
static const TokenAtom SYM_RBRACE
static const TokenAtom KWD_REF
static const TokenAtom KWD_FALSE
static const TokenAtom SYM_LBRACKET
std::pair< Token::Type, Atom > TokenAtom
static const TokenAtom SYM_OR_OR
static constexpr auto Symbol
vector< Token >::iterator VectorTokenIterator
A categorized token in source code, created by the tokenizer. These tokens are consumed by the lexer.
@ Symbol
Special characters, such as those representing operators.
@ Separator
A newline or a semicolon ;
@ Word
Any form of keyword or identifier, essentially the "default" token type.
@ Number
A number literal.
A declaration of a constant (const).
A declaration of a custom constructor (def :new).
A declaration of a function (def).
A function type i.e. ->(Foo,Bar)Baz.
A generic, compile-time argument to a struct or function definition, comparable to C++ template param...
An if statement (if), with one or more IfClauses, and optionally an else clause.
A local definition of an anonymous function.
Return from a function body.
A declaration of a struct (struct) or an interface (interface).
A pair of a Type and an identifier, i.e. a parameter name.
A declaration of a local variable (let).
unique_ptr< TypeName > type_name
auto ast_ptr(const VectorTokenIterator &entry, Args &&... args)
auto parse_generic_type_params() -> vector< GenericParam >
static auto is_uword(string_view word) -> bool
Check if the string begins with a capital letter. Used for types, as all types must be capitalized.
auto parse_string_expr() -> unique_ptr< StringExpr >
void expect(Token::Type token_type, source_location location=source_location::current()) const
If the next token doesn't have the type, token_type, throw a runtime exception.
auto consume_word(source_location location=source_location::current()) -> string
Return the payload of the next token. Throws if the next token isn't a Word.
auto parse_number_expr() -> unique_ptr< NumberExpr >
void consume(TokenAtom token_atom, source_location location=source_location::current())
Consume a token of the given type and payload. Throws if it wasn't encountered.
auto make_guard(const string &message) const -> ParserStackTrace
auto parse_logical_and() -> unique_ptr< Expr >
auto parse_receiver() -> unique_ptr< Expr >
auto try_parse_function_type() -> optional< unique_ptr< FunctionType > >
static auto unary_operators()
auto emit_fatal_and_terminate(int offset=0) const noexcept(false) -> diagnostic::Note
auto parse_fn_or_ctor_decl() -> unique_ptr< Stmt >
auto try_parse_type() -> optional< unique_ptr< Type > >
static auto to_string(Token token) -> string
auto parse_unary() -> unique_ptr< Expr >
auto try_consume(TokenAtom token_atom, source_location location=source_location::current()) -> bool
Attempt to consume a token of the given type and payload. Returns false if it wasn't encountered.
auto parse_if_stmt() -> unique_ptr< IfStmt >
auto parse_struct_decl() -> unique_ptr< StructDecl >
auto next(source_location location=source_location::current()) -> Token
Return the next token and increment the iterator.
auto parse_while_stmt() -> unique_ptr< WhileStmt >
auto emit_note(int offset=0, diagnostic::Severity severity=diagnostic::Severity::Note) const -> diagnostic::Note
static constexpr auto Separator
auto ast_ptr(TokenRange &&range, Args &&... args)
auto ts(const VectorTokenIterator &entry) const -> span< Token >
auto parse_var_decl() -> unique_ptr< VarDecl >
auto assert_payload_next(source_location location=source_location::current()) -> Atom
Returns the payload of the next token and increment the iterator.
void consume_with_commas_until(TokenAtom token_atom, std::invocable auto action, const source_location location=source_location::current())
Consume tokens until a token of the given type and payload is encountered. action (a no-arg function)...
auto parse_operator() -> unique_ptr< Expr >
auto parse_fn_arg() -> FnArg
static constexpr auto Number
auto collect_with_commas_until(TokenAtom token_atom, U(Parser::*action)(), const source_location location=source_location::current()) -> vector< T >
Consume tokens until a token of the given type and payload is encountered. action (a no-arg member fu...
auto parse_type_name() -> unique_ptr< TypeName >
auto try_peek(int ahead, TokenAtom token_atom, source_location location=source_location::current()) const -> bool
Check if the token ahead by ahead is of the given type and payload.
diagnostic::NotesHolder & notes
auto parse_stmt(bool require_sep=true) -> unique_ptr< Stmt >
auto parse_fn_name() -> string
void require_separator(source_location location=source_location::current())
Consume all subsequent Separator tokens. Throws if none were found.
auto clamped_iterator(const TokenIterator &iter) const -> TokenIterator
auto parse_const_decl() -> unique_ptr< ConstDecl >
auto parse_lambda() -> unique_ptr< LambdaExpr >
void collect_with_commas_until(TokenAtom token_atom, U(Parser::*action)(), vector< T > &vec, const source_location location=source_location::current())
Consume tokens until a token of the given type and payload is encountered. action (a no-arg member fu...
auto ignore_separator(source_location location=source_location::current()) -> bool
Ignore any Separator tokens if any are present.
auto parse_expr() -> unique_ptr< Expr >
auto make_ast(const VectorTokenIterator &entry, Args &&... args)
auto parse_type(bool implicit_self=false) -> unique_ptr< Type >
auto parse_ctor_decl() -> unique_ptr< CtorDecl >
static auto ts(T &&begin, U &&end) -> span< Token >
static constexpr auto Word
auto parse_fn_decl() -> unique_ptr< FnDecl >
auto parse_logical_or() -> unique_ptr< Expr >
auto parse_primary() -> unique_ptr< Expr >
auto parse_return_stmt() -> unique_ptr< ReturnStmt >
auto try_peek_uword(int ahead, source_location location=source_location::current()) const -> bool
Check if the ahead by ahead is a capitalized word.
static constexpr auto Symbol
auto parse_char_expr() -> unique_ptr< CharExpr >
auto emit(Loc location, Severity severity=Severity::Note) -> Note
static constexpr auto current()