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();
91 Ptr<Expr> parse_pi_expr(Ptr<Ptrn>&&);
92 Ptr<Expr> parse_lam_expr();
93 Ptr<Expr> parse_sigma_expr();
94 Ptr<Expr> parse_tuple_expr();
95 Ptr<Expr> parse_insert_expr();
96 Ptr<Expr> parse_uniq_expr();
97 ///@}
98
99 enum PtrnStyle {
100 Style_Bit = 0b001,
101 Brckt_Style = 0b001,
102 Paren_Style = 0b000,
103 Implicit = 0b010,
104 };
105
106 /// @name parse ptrns
107 ///@{
108 static bool is_paren_style(int style) { return (style & Style_Bit) == Paren_Style; }
109 static bool is_brket_style(int style) { return (style & Style_Bit) == Brckt_Style; }
110 static bool is_implicit(int style) { return (style & Implicit); }
111 Ptr<Ptrn> parse_ptrn(int style, std::string_view ctxt, Expr::Prec = Expr::Prec::Bot);
112 Ptr<Ptrn> parse_ptrn_(int style, std::string_view ctxt, Expr::Prec = Expr::Prec::Bot);
113 Ptr<TuplePtrn> parse_tuple_ptrn(int style);
114 ///@}
115
116 /// @name parse decls
117 ///@{
118 /// If @p ctxt ...
119 /// * ... empty: **Only** decls are parsed. @returns `nullptr`
120 /// * ... **non**-empty: Decls are parsed, then an expression. @returns expression.
121 Ptrs<ValDecl> parse_decls();
122 Ptr<ValDecl> parse_axiom_decl();
123 Ptr<ValDecl> parse_let_decl();
124 Ptr<ValDecl> parse_c_decl();
125 Ptr<LamDecl> parse_lam_decl();
126 Ptr<RecDecl> parse_rec_decl(bool first);
127 Ptr<RecDecl> parse_and_decl();
128 ///@}
129
130 /// @name error messages
131 ///@{
132 /// Issue an error message of the form:
133 /// "expected <what>, got '<tok>\' while parsing <ctxt>"
134 void syntax_err(std::string_view what, const Tok& tok, std::string_view ctxt) {
135 ast().error(tok.loc(), "expected {}, got '{}' while parsing {}", what, tok, ctxt);
136 }
137
138 /// Same above but uses @p ahead() as @p tok.
139 void syntax_err(std::string_view what, std::string_view ctxt) { syntax_err(what, ahead(), ctxt); }
140
141 void syntax_err(Tok::Tag tag, std::string_view ctxt) {
142 std::string msg("'");
143 msg.append(Tok::tag2str(tag)).append("'");
144 syntax_err(msg, ctxt);
145 }
146
147 using Super::expect;
148 template<class... Args> Tok expect(Tok::Tag tag, const char* f, Args&&... args) {
149 std::ostringstream oss;
150 print(oss, f, std::forward<Args&&>(args)...);
151 return Super::expect(tag, oss.str());
152 }
153 ///@}
154
155 AST& ast_;
156 Lexer* lexer_ = nullptr;
157
158 friend Super;
159};
160
161} // 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:161
static constexpr Tok::Tag delim_l2r(Tag tag)
Definition tok.h:117
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