MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
tok.h
Go to the documentation of this file.
1#pragma once
2
3#include <fe/assert.h>
4#include <fe/format.h>
5
6#include "mim/util/dbg.h"
7
8namespace mim {
9
10class Def;
11class Lit;
12
13namespace ast {
14
15/// @name Precedence Table
16/// X-macro listing all expression precedences from lowest to highest.
17/// Each entry is `m(name, assoc)` where @p assoc is `L`, `R`, or `N`.
18///@{
19// clang-format off
20#define MIM_PREC(m) \
21 m(Err, N) \
22 m(Bot, N) \
23 m(Where, L) \
24 m(Arrow, R) \
25 m(Pi, N) \
26 m(Inj, R) \
27 m(App, L) \
28 m(Union, L) \
29 m(Extract, L) \
30 m(Lit, N)
31// clang-format on
32///@}
33
34/// Associativity of an infix expression.
35enum class Assoc { N, L, R };
36
37/// Expression precedences used by the parser and the dumper; ordered low to high.
38enum class Prec {
39#define CODE(name, ...) name,
41#undef CODE
42};
43
44/// Associativity of precedence level @p p.
45constexpr Assoc prec_assoc(Prec p) {
46 switch (p) {
47#define CODE(name, assoc) \
48 case Prec::name: return Assoc::assoc;
50#undef CODE
51 }
52 fe::unreachable();
53}
54
55constexpr bool is_rassoc(Prec p) { return prec_assoc(p) == Assoc::R; }
56constexpr bool is_lassoc(Prec p) { return prec_assoc(p) == Assoc::L; }
57
58/// Should a Pratt parser reduce when the current binding power is @p curr
59/// and the infix operator has precedence @p op?
60constexpr bool should_reduce(Prec curr, Prec op) { return is_rassoc(op) ? curr > op : curr >= op; }
61
62// clang-format off
63#define MIM_KEY(m) \
64 m(K_Bool, "Bool" ) \
65 m(K_Cn, "Cn" ) \
66 m(K_Fn, "Fn" ) \
67 m(K_I1, "I1" ) \
68 m(K_I16, "I16" ) \
69 m(K_I32, "I32" ) \
70 m(K_I64, "I64" ) \
71 m(K_I8, "I8" ) \
72 m(K_Idx, "Idx" ) \
73 m(K_Nat, "Nat" ) \
74 m(K_Type, "Type" ) \
75 m(K_Univ, "Univ" ) \
76 m(K_and, "and" ) \
77 m(K_as, "as" ) \
78 m(K_axm, "axm" ) \
79 m(K_ccon, "ccon" ) \
80 m(K_cfun, "cfun" ) \
81 m(K_cn, "cn" ) \
82 m(K_con, "con" ) \
83 m(K_end, "end" ) \
84 m(K_extern, "extern") \
85 m(K_ff, "ff" ) \
86 m(K_fn, "fn" ) \
87 m(K_fun, "fun" ) \
88 m(K_i1, "i1" ) \
89 m(K_i16, "i16" ) \
90 m(K_i32, "i32" ) \
91 m(K_i64, "i64" ) \
92 m(K_i8, "i8" ) \
93 m(K_import, "import") \
94 m(K_inj, "inj" ) \
95 m(K_ins, "ins" ) \
96 m(K_lam, "lam" ) \
97 m(K_let, "let" ) \
98 m(K_match, "match" ) \
99 m(K_module, "module") \
100 m(K_norm, "norm" ) \
101 m(K_plugin, "plugin") \
102 m(K_rec, "rec" ) \
103 m(K_ret, "ret" ) \
104 m(K_rule, "rule" ) \
105 m(K_Rule, "Rule" ) \
106 m(K_tt, "tt" ) \
107 m(K_when, "when" ) \
108 m(K_where, "where" ) \
109 m(K_with, "with" ) \
110
111#define CODE(t, str) + size_t(1)
112constexpr auto Num_Keys = size_t(0) MIM_KEY(CODE);
113#undef CODE
114
115#define MIM_TOK(m) \
116 m(EoF, "<end of file>" ) \
117 /* literals */ \
118 m(L_s, "<signed integer literal>") \
119 m(L_u, "<integer literal>" ) \
120 m(L_i, "<index literal>" ) \
121 m(L_f, "<floating-point literal>") \
122 m(L_c, "<char literal>" ) \
123 m(L_str, "<string literal>" ) \
124 /* misc */ \
125 m(M_id, "<identifier>" ) \
126 m(M_anx, "<annex name>" ) \
127 /* delimiters */ \
128 m(D_angle_l, "‹") \
129 m(D_angle_r, "›") \
130 m(D_brace_l, "{") \
131 m(D_brace_r, "}") \
132 m(D_brckt_l, "[") \
133 m(D_brckt_r, "]") \
134 m(D_curly_l, "⦃") \
135 m(D_curly_r, "⦄") \
136 m(D_paren_l, "(") \
137 m(D_paren_r, ")") \
138 m(D_quote_l, "«") \
139 m(D_quote_r, "»") \
140 /* further tokens */ \
141 m(T_arrow, "→") \
142 m(T_fat_arrow, "=>") \
143 m(T_assign, "=") \
144 m(T_at, "@") \
145 m(T_bot, "⊥") \
146 m(T_top, "⊤") \
147 m(T_box, "□") \
148 m(T_colon, ":") \
149 m(T_comma, ",") \
150 m(T_dollar, "$") \
151 m(T_dot, ".") \
152 m(T_extract, "#") \
153 m(T_lm, "λ") \
154 m(T_semicolon, ";") \
155 m(T_star, "*") \
156 m(T_union, "∪") \
157 m(T_pipe, "|") \
158
159#define MIM_SUBST(m) \
160 m("lm", T_lm ) \
161 m("bot", T_bot ) \
162 m("top", T_top ) \
163 m("insert", K_ins ) \
164
165class Tok {
166public:
167 /// @name Tag
168 ///@{
169 enum class Tag {
171#define CODE(t, str) t,
173#undef CODE
174 };
175
176 static const char* tag2str(Tok::Tag);
177 static constexpr Tok::Tag delim_l2r(Tag tag) { return Tok::Tag(int(tag) + 1); }
178 ///@}
179
180 // clang-format on
181
182 Tok() {}
184 : loc_(loc)
185 , tag_(tag) {}
186 Tok(Loc loc, char8_t c)
187 : loc_(loc)
188 , tag_(Tag::L_c)
189 , c_(c) {}
190 Tok(Loc loc, uint64_t u)
191 : loc_(loc)
192 , tag_(Tag::L_u)
193 , u_(u) {}
194 Tok(Loc loc, int64_t s)
195 : loc_(loc)
196 , tag_(Tag::L_s)
197 , u_(std::bit_cast<uint64_t>(s)) {}
198 Tok(Loc loc, double d)
199 : loc_(loc)
200 , tag_(Tag::L_f)
201 , u_(std::bit_cast<uint64_t>(d)) {}
202 Tok(Loc loc, const Lit* i)
203 : loc_(loc)
204 , tag_(Tag::L_i)
205 , i_(i) {}
206 Tok(Loc loc, Tag tag, Sym sym)
207 : loc_(loc)
208 , tag_(tag)
209 , sym_(sym) {
210 assert(tag == Tag::M_id || tag == Tag::M_anx || tag == Tag::L_str);
211 }
212
213 bool isa(Tag tag) const { return tag == tag_; }
214 Tag tag() const { return tag_; }
215 Dbg dbg() const { return {loc(), sym()}; }
216 Loc loc() const { return loc_; }
217 explicit operator bool() const { return tag_ != Tag::Nil; }
218 // clang-format off
219 const Lit* lit_i() const { assert(isa(Tag::L_i)); return i_; }
220 char8_t lit_c() const { assert(isa(Tag::L_c)); return c_; }
221 uint64_t lit_u() const { assert(isa(Tag::L_u ) || isa(Tag::L_s ) || isa(Tag::L_f )); return u_; }
222 Sym sym() const { assert(isa(Tag::M_anx) || isa(Tag::M_id) || isa(Tag::L_str)); return sym_; }
223 // clang-format on
224 std::string str() const;
225
226 friend std::ostream& operator<<(std::ostream&, Tok);
227 friend std::ostream& operator<<(std::ostream& os, Tok::Tag tag) { return os << tag2str(tag); }
228
229private:
230 Loc loc_;
231 Tag tag_ = Tag::Nil;
232 union {
233 Sym sym_;
234 uint64_t u_;
235 char8_t c_;
236 const Lit* i_;
237 };
238};
239
240} // namespace ast
241} // namespace mim
242
243#ifndef DOXYGEN // clang-format off
244template<> struct std::formatter<mim::ast::Tok > : fe::ostream_formatter {};
245template<> struct std::formatter<mim::ast::Tok::Tag> : fe::ostream_formatter {};
246#endif // clang-format on
Base class for all Defs.
Definition def.h:246
Tok(Loc loc, uint64_t u)
Definition tok.h:190
friend std::ostream & operator<<(std::ostream &, Tok)
Definition tok.cpp:30
const Lit * lit_i() const
Definition tok.h:219
Sym sym() const
Definition tok.h:222
Tok(Loc loc, Tag tag)
Definition tok.h:183
Tok(Loc loc, Tag tag, Sym sym)
Definition tok.h:206
Tok(Loc loc, const Lit *i)
Definition tok.h:202
Dbg dbg() const
Definition tok.h:215
Loc loc() const
Definition tok.h:216
uint64_t lit_u() const
Definition tok.h:221
bool isa(Tag tag) const
Definition tok.h:213
static constexpr Tok::Tag delim_l2r(Tag tag)
Definition tok.h:177
Tok(Loc loc, int64_t s)
Definition tok.h:194
Tok(Loc loc, char8_t c)
Definition tok.h:186
friend std::ostream & operator<<(std::ostream &os, Tok::Tag tag)
Definition tok.h:227
static const char * tag2str(Tok::Tag)
Definition tok.cpp:10
std::string str() const
Definition tok.cpp:22
Tok(Loc loc, double d)
Definition tok.h:198
Tag tag() const
Definition tok.h:214
char8_t lit_c() const
Definition tok.h:220
Definition ast.h:14
constexpr bool is_lassoc(Prec p)
Definition tok.h:56
Assoc
Associativity of an infix expression.
Definition tok.h:35
constexpr bool is_rassoc(Prec p)
Definition tok.h:55
constexpr bool should_reduce(Prec curr, Prec op)
Should a Pratt parser reduce when the current binding power is curr and the infix operator has preced...
Definition tok.h:60
constexpr auto Num_Keys
Definition tok.h:112
Tok::Tag Tag
Definition bind.cpp:7
constexpr Assoc prec_assoc(Prec p)
Associativity of precedence level p.
Definition tok.h:45
Prec
Expression precedences used by the parser and the dumper; ordered low to high.
Definition tok.h:38
Definition ast.h:14
Definition span.h:122
#define MIM_PREC(m)
Definition tok.h:20
#define CODE(name,...)
Definition tok.h:39
#define MIM_TOK(m)
Definition tok.h:115
#define MIM_KEY(m)
Definition tok.h:63