MimIR 0.1
MimIR is my 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 "mim/ast/ast.h"
6#include "mim/ast/lexer.h"
7
8namespace mim::ast {
9
10constexpr size_t Look_Ahead = 2;
11
12/// Parses Mim code as AST.
13///
14/// The logic behind the various parse methods is as follows:
15/// 1. The `parse_*` method does **not** have a `std::string_view ctxt` parameter:
16///
17/// It's the **caller's responsibility** to first make appropriate
18/// [FIRST/FOLLOW](https://www.cs.uaf.edu/~cs331/notes/FirstFollow.pdf) checks.
19/// Otherwise, an assertion will be triggered in the case of a syntax error.
20///
21/// 2. The `parse_*` method does have a `std::string_view ctxt` parameter:
22///
23/// The **called method** checks this and spits out an appropriate error message using `ctxt` in the case of a
24/// syntax error.
25///
26/// 3. The `parse_*` method does have a `std::string_view ctxt = {}` parameter **with default argument**:
27///
28/// * If default argument is **elided** we have the same behavior as in 1.
29/// * If default argument is **provided** we have the same behavior as in 2.
30class Parser : public fe::Parser<Tok, Tok::Tag, Look_Ahead, Parser> {
31 using Super = fe::Parser<Tok, Tok::Tag, Look_Ahead, Parser>;
32
33public:
35 : ast_(ast) {}
36
37 AST& ast() { return ast_; }
38 Driver& driver() { return ast().driver(); }
39 Ptr<Module> import(std::string_view sv) { return import({Loc(), driver().sym(sv)}); }
40 Ptr<Module> import(Dbg, std::ostream* md = nullptr);
41 Ptr<Module> import(std::istream&, Loc = {}, const fs::path* = nullptr, std::ostream* md = nullptr);
43 Ptr<Module> plugin(const std::string& s) { return plugin({Loc(), driver().sym(s)}); }
44 Ptr<Module> plugin(const char* name) { return plugin({Loc(), driver().sym(name)}); }
45
46private:
47 template<class T, class... Args> auto ptr(Args&&... args) {
48 return ast_.ptr<const T>(std::forward<Args&&>(args)...);
49 }
50
51 Dbg anon() const { return {ahead().loc().anew_begin(), ast_.sym_anon()}; }
52 Dbg dbg(const Tracker& tracker, Sym sym) const { return {tracker.loc(), sym}; }
53 Lexer& lexer() { return *lexer_; }
54
55 /// @name parse misc
56 ///@{
57 Ptr<Module> parse_module();
58 Dbg parse_id(std::string_view ctxt = {});
59 std::pair<Annex&, bool> parse_annex(std::string_view ctxt = {});
60 Dbg parse_name(std::string_view ctxt = {});
61 Ptr<Import> parse_import_or_plugin();
62 Ptr<Import> parse_plugin();
63 Ptr<Expr> parse_type_ascr(std::string_view ctxt = {});
64
65 template<class F> void parse_list(std::string ctxt, Tok::Tag delim_l, F f, Tok::Tag sep = Tok::Tag::T_comma) {
66 expect(delim_l, ctxt);
67 auto delim_r = Tok::delim_l2r(delim_l);
68 if (!ahead().isa(delim_r)) {
69 do { f(); } while (accept(sep) && !ahead().isa(delim_r));
70 }
71 expect(delim_r, std::string("closing delimiter of a ") + ctxt);
72 }
73 ///@}
74
75 /// @name parse exprs
76 ///@{
77 Ptr<Expr> parse_expr(std::string_view ctxt, Expr::Prec = Expr::Prec::Bot);
78 Ptr<Expr> parse_primary_expr(std::string_view ctxt);
79 Ptr<Expr> parse_infix_expr(Tracker, Ptr<Expr>&& lhs, Expr::Prec = Expr::Prec::Bot);
80 ///@}
81
82 /// @name parse primary exprs
83 ///@{
84 template<bool> Ptr<Expr> parse_arr_or_pack_expr();
85 Ptr<Expr> parse_decl_expr();
86 Ptr<Expr> parse_lit_expr();
87 Ptr<Expr> parse_extremum_expr();
88 Ptr<Expr> parse_type_expr();
89 Ptr<Expr> parse_ret_expr();
90 Ptr<Expr> parse_pi_expr(Ptr<Ptrn>&& = nullptr);
91 Ptr<Expr> parse_lam_expr();
92 Ptr<Expr> parse_sigma_expr();
93 Ptr<Expr> parse_tuple_expr();
94 Ptr<Expr> parse_insert_expr();
95 ///@}
96
97 enum PtrnStyle {
98 Style_Bit = 0b001,
99 Brckt_Style = 0b001,
100 Paren_Style = 0b000,
101 Implicit = 0b010,
102 };
103
104 /// @name parse ptrns
105 ///@{
106 /// Depending on @p style, this parses a `()`-style (Tok::Tag::D_paren_l) or `[]`-style (Tok::Tag::D_brckt_l) Ptrn.
107 Ptr<Ptrn> parse_ptrn(int style, std::string_view ctxt, Expr::Prec = Expr::Prec::Bot);
108 Ptr<Ptrn> parse_ptrn_(int style, std::string_view ctxt, Expr::Prec = Expr::Prec::Bot);
109 Ptr<TuplePtrn> parse_tuple_ptrn(int style);
110 ///@}
111
112 /// @name parse decls
113 ///@{
114 /// If @p ctxt ...
115 /// * ... empty: **Only** decls are parsed. @returns `nullptr`
116 /// * ... **non**-empty: Decls are parsed, then an expression. @returns expression.
117 Ptrs<ValDecl> parse_decls();
118 Ptr<ValDecl> parse_axiom_decl();
119 Ptr<ValDecl> parse_let_decl();
120 Ptr<ValDecl> parse_c_decl();
121 Ptr<LamDecl> parse_lam_decl();
122 Ptr<RecDecl> parse_rec_decl(bool first);
123 Ptr<RecDecl> parse_and_decl();
124 ///@}
125
126 /// @name error messages
127 ///@{
128 /// Issue an error message of the form:
129 /// "expected <what>, got '<tok>\' while parsing <ctxt>"
130 void syntax_err(std::string_view what, const Tok& tok, std::string_view ctxt) {
131 ast().error(tok.loc(), "expected {}, got '{}' while parsing {}", what, tok, ctxt);
132 }
133
134 /// Same above but uses @p ahead() as @p tok.
135 void syntax_err(std::string_view what, std::string_view ctxt) { syntax_err(what, ahead(), ctxt); }
136
137 void syntax_err(Tok::Tag tag, std::string_view ctxt) {
138 std::string msg("'");
139 msg.append(Tok::tag2str(tag)).append("'");
140 syntax_err(msg, ctxt);
141 }
142
143 using Super::expect;
144 template<class... Args> Tok expect(Tok::Tag tag, const char* f, Args&&... args) {
145 std::ostringstream oss;
146 print(oss, f, std::forward<Args&&>(args)...);
147 return Super::expect(tag, oss.str());
148 }
149 ///@}
150
151 AST& ast_;
152 Lexer* lexer_ = nullptr;
153
154 friend Super;
155};
156
157} // namespace mim::ast
Some "global" variables needed all over the place.
Definition driver.h:17
Driver & driver()
Definition ast.h:62
auto ptr(Args &&... args)
Definition ast.h:77
Sym sym_anon()
"_".
Definition ast.h:72
Error & error()
Definition ast.h:63
Parses Mim code as AST.
Definition parser.h:30
Parser(AST &ast)
Definition parser.h:34
AST & ast()
Definition parser.h:37
Ptr< Module > plugin(const std::string &s)
Definition parser.h:43
Ptr< Module > plugin(const char *name)
Definition parser.h:44
Driver & driver()
Definition parser.h:38
Ptr< Module > plugin(Dbg)
Definition parser.cpp:164
static constexpr Tok::Tag delim_l2r(Tag tag)
Definition tok.h:115
static const char * tag2str(Tok::Tag)
Definition tok.cpp:10
Definition ast.h:14
fe::Arena::Ptr< const T > Ptr
Definition ast.h:21
constexpr size_t Look_Ahead
Definition parser.h:10
std::deque< Ptr< T > > Ptrs
Definition ast.h:22
std::ostream & print(std::ostream &os, const char *s)
Base case.
Definition print.cpp:5