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, Tok::Tag tag = Tok::Tag::K_import) {
40 return import({Loc(), driver().sym(sv)}, nullptr, tag);
41 }
42 Ptr<Module> import(Dbg, std::ostream* md = nullptr, Tok::Tag tag = Tok::Tag::K_import);
43 Ptr<Module> import(std::istream&, Loc = {}, const fs::path* = nullptr, std::ostream* md = nullptr);
45 Ptr<Module> plugin(const std::string& s) { return plugin({Loc(), driver().sym(s)}); }
46 Ptr<Module> plugin(const char* name) { return plugin({Loc(), driver().sym(name)}); }
47
48private:
49 template<class T, class... Args>
50 auto ptr(Args&&... args) {
51 return ast_.ptr<const T>(std::forward<Args>(args)...);
52 }
53
54 Dbg anon() const { return {ahead().loc().anew_begin(), ast_.sym_anon()}; }
55 Dbg dbg(const Tracker& tracker, Sym sym) const { return {tracker.loc(), sym}; }
56 Lexer& lexer() { return *lexer_; }
57
58 /// @name parse misc
59 ///@{
60 Ptr<Module> parse_module();
61 Dbg parse_id(std::string_view ctxt = {});
62 std::pair<Annex&, bool> parse_annex(std::string_view ctxt = {});
63 Dbg parse_name(std::string_view ctxt = {});
64 Ptr<Import> parse_import_or_plugin();
65 Ptr<Import> parse_plugin();
66 Ptr<Expr> parse_type_ascr(std::string_view ctxt = {});
67
68 template<class F>
69 void parse_list(std::string ctxt, Tok::Tag delim_l, F f, Tok::Tag sep = Tok::Tag::T_comma) {
70 expect(delim_l, ctxt);
71 auto delim_r = Tok::delim_l2r(delim_l);
72 if (!ahead().isa(delim_r)) {
73 do {
74 f();
75 } while (accept(sep) && !ahead().isa(delim_r));
76 }
77 expect(delim_r, std::string("closing delimiter of a ") + ctxt);
78 }
79 ///@}
80
81 /// @name parse exprs
82 ///@{
83 Ptr<Expr> parse_expr(std::string_view ctxt, Prec = Prec::Bot);
84 Ptr<Expr> parse_primary_expr(std::string_view ctxt);
85 Ptr<Expr> parse_infix_expr(Tracker, Ptr<Expr>&& lhs, Prec = Prec::Bot);
86 ///@}
87
88 /// @name parse primary exprs
89 ///@{
90 Ptr<Expr> parse_decl_expr();
91 Ptr<Expr> parse_lit_expr();
92 Ptr<Expr> parse_extremum_expr();
93 Ptr<Expr> parse_type_expr();
94 Ptr<Expr> parse_rule_expr();
95 Ptr<Expr> parse_ret_expr();
96 Ptr<Expr> parse_pi_expr();
97 Ptr<Expr> parse_pi_expr(Ptr<Ptrn>&&);
98 Ptr<Expr> parse_lam_expr();
99 Ptr<Expr> parse_seq_expr();
100 Ptr<Expr> parse_sigma_expr();
101 Ptr<Expr> parse_tuple_expr();
102 Ptr<Expr> parse_insert_expr();
103 Ptr<Expr> parse_uniq_expr();
104 Ptr<Expr> parse_match_expr();
105 ///@}
106
107 enum PtrnStyle {
108 Style_Bit = 0b001,
109 Brckt_Style = 0b001,
110 Paren_Style = 0b000,
111 Implicit = 0b010,
112 };
113
114 /// @name parse ptrns
115 ///@{
116 static bool is_paren_style(int style) { return (style & Style_Bit) == Paren_Style; }
117 static bool is_brket_style(int style) { return (style & Style_Bit) == Brckt_Style; }
118 static bool is_implicit(int style) { return (style & Implicit); }
119 Ptr<Ptrn> parse_ptrn(int style, std::string_view ctxt, Prec = Prec::Bot);
120 Ptr<Ptrn> parse_ptrn_(int style, std::string_view ctxt, Prec = Prec::Bot);
121 Ptr<TuplePtrn> parse_tuple_ptrn(int style);
122 ///@}
123
124 /// @name parse decls
125 ///@{
126 /// If @p ctxt ...
127 /// * ... empty: **Only** decls are parsed. @returns `nullptr`
128 /// * ... **non**-empty: Decls are parsed, then an expression. @returns expression.
129 Ptrs<ValDecl> parse_decls();
130 Ptr<ValDecl> parse_axm_decl();
131 Ptr<ValDecl> parse_let_decl();
132 Ptr<ValDecl> parse_c_decl();
133 Ptr<ValDecl> parse_rule_decl();
134 Ptr<LamDecl> parse_lam_decl();
135 Ptr<RecDecl> parse_rec_decl(bool first);
136 Ptr<RecDecl> parse_and_decl();
137 ///@}
138
139 /// @name error messages
140 ///@{
141 /// Issue an error message of the form:
142 /// "expected <what>, got '<tok>\' while parsing <ctxt>"
143 void syntax_err(std::string_view what, const Tok& tok, std::string_view ctxt) {
144 ast().error(tok.loc(), "expected {}, got '{}' while parsing {}", what, tok, ctxt);
145 }
146
147 /// Same above but uses @p ahead() as @p tok.
148 void syntax_err(std::string_view what, std::string_view ctxt) { syntax_err(what, ahead(), ctxt); }
149
150 void syntax_err(Tok::Tag tag, std::string_view ctxt) {
151 std::string msg("'");
152 msg.append(Tok::tag2str(tag)).append("'");
153 syntax_err(msg, ctxt);
154 }
155
156 using Super::expect;
157 template<class... Args>
158 Tok expect(Tok::Tag tag, const char* f, Args&&... args) {
159 std::ostringstream oss;
160 print(oss, f, std::forward<Args>(args)...);
161 return Super::expect(tag, oss.str());
162 }
163 ///@}
164
165 AST& ast_;
166 Lexer* lexer_ = nullptr;
167
168 friend Super;
169};
170
171} // namespace mim::ast
Some "global" variables needed all over the place.
Definition driver.h:19
Driver & driver()
Definition ast.h:62
auto ptr(Args &&... args)
Definition ast.h:78
Sym sym_anon()
"_".
Definition ast.h:72
Error & error()
Definition ast.h:63
Parser(AST &ast)
Definition parser.h:34
AST & ast()
Definition parser.h:37
Ptr< Module > plugin(const std::string &s)
Definition parser.h:45
Ptr< Module > plugin(const char *name)
Definition parser.h:46
Driver & driver()
Definition parser.h:38
Ptr< Module > plugin(Dbg)
Definition parser.cpp:162
static constexpr Tok::Tag delim_l2r(Tag tag)
Definition tok.h:175
static const char * tag2str(Tok::Tag)
Definition tok.cpp:10
Definition ast.h:14
fe::Arena::Ptr< const T > Ptr
Definition ast.h:22
constexpr size_t Look_Ahead
Definition parser.h:10
std::deque< Ptr< T > > Ptrs
Definition ast.h:24
Prec
Expression precedences used by the parser and the dumper; ordered low to high.
Definition tok.h:37
std::ostream & print(std::ostream &os, const char *s)
Base case.
Definition print.cpp:5