Thorin 1.9.0
The Higher ORder INtermediate representation
Loading...
Searching...
No Matches
parser.h
Go to the documentation of this file.
1#pragma once
2
3#include <fe/parser.h>
4
5#include "thorin/driver.h"
6
7#include "thorin/fe/ast.h"
8#include "thorin/fe/lexer.h"
9#include "thorin/fe/scopes.h"
10
11namespace thorin {
12
13constexpr size_t Look_Ahead = 2;
14
15/// Parses Thorin code into the provided World.
16///
17/// The logic behind the various parse methods is as follows:
18/// 1. The `parse_*` method does **not** have a `std::string_view ctxt` parameter:
19///
20/// It's the **caller's responsibility** to first make appropriate
21/// [FIRST/FOLLOW](https://www.cs.uaf.edu/~cs331/notes/FirstFollow.pdf) checks.
22/// Otherwise, an assertion will be triggered in the case of a syntax error.
23///
24/// 2. The `parse_*` method does have a `std::string_view ctxt` parameter:
25///
26/// The **called method** checks this and spits out an appropriate error message using `ctxt` in the case of a
27/// syntax error.
28///
29/// 3. The `parse_*` method does have a `std::string_view ctxt = {}` parameter **with default argument**:
30///
31/// * If default argument is **elided** we have the same behavior as in 1.
32/// * If default argument is **provided** we have the same behavior as in 2.
33class Parser : public fe::Parser<Tok, Tok::Tag, Look_Ahead, Parser> {
34public:
36 : world_(world)
37 , anonymous_(world.sym("_"))
38 , return_(world.sym("return")) {}
39
40 World& world() { return world_; }
41 Driver& driver() { return world().driver(); }
42 void import(std::string_view sv) { return import(driver().sym(sv)); }
43 void import(Sym, std::ostream* md = nullptr);
44 void import(std::istream&, const fs::path* = nullptr, std::ostream* md = nullptr);
45 void plugin(Sym);
46 void plugin(const char* name) { return plugin(driver().sym(name)); }
47 const Scopes& scopes() const { return scopes_; }
48
49private:
50 Dbg dbg(const Tracker& tracker, Sym sym) const { return {tracker.loc(), sym}; }
51 Lexer& lexer() { return *lexer_; }
52
53 /// @name parse misc
54 ///@{
55 void parse_module();
56 Dbg parse_id(std::string_view ctxt = {});
57 std::pair<Annex&, bool> parse_annex(std::string_view ctxt = {});
58 std::pair<Dbg, bool> parse_name(std::string_view ctxt = {});
59 void parse_import();
60 void parse_plugin();
61 Ref parse_type_ascr(std::string_view ctxt = {});
62 void register_annex(Dbg, Ref);
63
64 template<class F> void parse_list(std::string ctxt, Tok::Tag delim_l, F f, Tok::Tag sep = Tok::Tag::T_comma) {
65 expect(delim_l, ctxt);
66 auto delim_r = Tok::delim_l2r(delim_l);
67 if (!ahead().isa(delim_r)) {
68 do { f(); } while (accept(sep) && !ahead().isa(delim_r));
69 }
70 expect(delim_r, std::string("closing delimiter of a ") + ctxt);
71 }
72 ///@}
73
74 /// @name parse exprs
75 ///@{
76 Ref parse_expr(std::string_view ctxt, Tok::Prec = Tok::Prec::Bot);
77 Ref parse_primary_expr(std::string_view ctxt);
78 Ref parse_infix_expr(Tracker, const Def* lhs, Tok::Prec = Tok::Prec::Bot);
79 Ref parse_extract_expr(Tracker, const Def*, Tok::Prec);
80 ///@}
81
82 /// @name parse primary exprs
83 ///@{
84 Ref parse_arr_expr();
85 Ref parse_pack_expr();
86 Ref parse_block_expr();
87 Ref parse_sigma_expr();
88 Ref parse_tuple_expr();
89 Ref parse_type_expr();
90 Pi* parse_pi_expr(Pi* = nullptr);
91 Ref parse_lit_expr();
92 Ref parse_insert_expr();
93 Ref parse_ret_expr();
94 Lam* parse_lam(bool decl = false);
95 ///@}
96
97 /// @name parse ptrns
98 ///@{
99
100 /// Depending on @p tag, this parses a `()`-style (Tok::Tag::D_paren_l) or `[]`-style (Tok::Tag::D_brckt_l) Ptrn.
101 std::unique_ptr<Ptrn> parse_ptrn(Tok::Tag tag, std::string_view ctxt, Tok::Prec = Tok::Prec::Bot);
102 std::unique_ptr<TuplePtrn> parse_tuple_ptrn(Tracker, bool rebind, Sym, Def* = nullptr);
103 ///@}
104
105 /// @name parse decls
106 ///@{
107
108 /// If @p ctxt ...
109 /// * ... empty: **Only** decls are parsed. @returns `nullptr`
110 /// * ... **non**-empty: Decls are parsed, then an expression. @returns expression.
111 Ref parse_decls(std::string_view ctxt);
112 void parse_ax_decl();
113 void parse_let_decl();
114 void parse_sigma_decl();
115 void parse_pi_decl();
116 ///@}
117
118 /// @name error messages
119 ///@{
120 /// Issue an error message of the form:
121 /// "expected <what>, got '<tok>\' while parsing <ctxt>"
122 [[noreturn]] void syntax_err(std::string_view what, const Tok& tok, std::string_view ctxt) {
123 error(tok.loc(), "expected {}, got '{}' while parsing {}", what, tok, ctxt);
124 }
125
126 /// Same above but uses @p ahead() as @p tok.
127 [[noreturn]] void syntax_err(std::string_view what, std::string_view ctxt) { syntax_err(what, ahead(), ctxt); }
128
129 [[noreturn]] void syntax_err(Tok::Tag tag, std::string_view ctxt) {
130 std::string msg("'");
131 msg.append(Tok::tag2str(tag)).append("'");
132 syntax_err(msg, ctxt);
133 }
134 ///@}
135
136 World& world_;
137 Lexer* lexer_ = nullptr;
138 Scopes scopes_;
139 Def2Fields def2fields_;
140 Sym anonymous_;
141 Sym return_;
142
143 friend class fe::Parser<Tok, Tok::Tag, Look_Ahead, Parser>;
144};
145
146} // namespace thorin
Some "global" variables needed all over the place.
Definition driver.h:17
Parses Thorin code into the provided World.
Definition parser.h:33
const Scopes & scopes() const
Definition parser.h:47
void plugin(Sym)
Definition parser.cpp:72
Parser(World &world)
Definition parser.h:35
Driver & driver()
Definition parser.h:41
void plugin(const char *name)
Definition parser.h:46
World & world()
Definition parser.h:40
static std::string_view tag2str(Tok::Tag)
Definition tok.cpp:10
static constexpr Tok::Tag delim_l2r(Tag tag)
Definition tok.h:147
The World represents the whole program and manages creation of Thorin nodes (Defs).
Definition world.h:35
const Driver & driver() const
Definition world.h:83
Definition cfg.h:11
void error(const Def *def, const char *fmt, Args &&... args)
Definition def.h:622
Loc loc
Definition dbg.h:32
DefMap< Vector< Sym > > Def2Fields
Definition ast.h:17
constexpr size_t Look_Ahead
Definition parser.h:13