77 case Tag::D_angle_l: \
78 case Tag::D_brckt_l: \
79 case Tag::D_curly_l: \
80 case Tag::D_paren_l: \
85 case Tag::D_brckt_l: \
90 case Tag::D_brckt_l: \
94using namespace std::string_literals;
105 auto track = tracker();
108 if (ahead().isa(Tag::K_import) || ahead().isa(Tag::K_plugin)) {
109 if (
auto import = parse_import_or_plugin()) imports.emplace_back(std::move(
import));
114 auto decls = parse_decls();
115 bool where = ahead().isa(Tag::K_where);
116 expect(Tag::EoF,
"module");
117 auto mod = ptr<Module>(track, std::move(imports), std::move(decls));
118 if (where)
ast().
note(mod->loc().anew_finis(),
"did you accidentally end your declaration expression with a ';'?");
123 auto name = dbg.sym();
124 auto filename = fs::path(name.view());
125 driver().VLOG(
"import: {}", name);
127 if (!filename.has_extension()) filename.replace_extension(
"mim");
130 for (
const auto& path :
driver().search_paths()) {
131 std::error_code ignore;
132 rel_path = path / filename;
133 if (
bool reg_file = fs::is_regular_file(rel_path, ignore); reg_file && !ignore)
break;
134 rel_path = path / name.view() / filename;
135 if (
bool reg_file = fs::is_regular_file(rel_path, ignore); reg_file && !ignore)
break;
138 if (
auto path =
driver().add_import(std::move(rel_path), name)) {
139 auto ifs = std::ifstream(*path);
140 return import(ifs, dbg.loc(), path, md);
146 driver().VLOG(
"reading: {}", path ? path->string() :
"<unknown file>"s);
148 ast().
error(loc,
"cannot read file {}", *path);
152 auto state = std::tuple(curr_, ahead_, lexer_);
153 auto lexer =
Lexer(
ast(), is, path, md);
156 auto mod = parse_module();
157 std::tie(curr_, ahead_, lexer_) = state;
171 auto track = tracker();
172 auto tag = lex().tag();
173 auto name = expect(Tag::M_id,
"{} name", tag == Tag::K_import ?
"import" :
"plugin");
174 auto dbg = name.dbg();
175 expect(Tag::T_semicolon,
"end of {}", tag == Tag::K_import ?
"import" :
"plugin");
176 if (
auto module = tag == Tag::K_import ?
import(dbg) :
plugin(dbg))
177 return ptr<Import>(track, tag, name.dbg(), std::move(module));
181Dbg Parser::parse_id(std::string_view ctxt) {
182 if (
auto id = accept(Tag::M_id))
return id.dbg();
183 syntax_err(
"identifier", ctxt);
184 return {curr_,
driver().sym(
"<error>")};
187Dbg Parser::parse_name(std::string_view ctxt) {
188 if (
auto tok = accept(Tag::M_anx))
return tok.dbg();
189 if (
auto tok = accept(Tag::M_id))
return tok.dbg();
190 syntax_err(
"identifier or annex name", ctxt);
191 return Dbg(curr_,
ast().sym(
"<error>"));
194Ptr<Expr> Parser::parse_type_ascr(std::string_view ctxt) {
195 if (accept(Tag::T_colon))
return parse_expr(ctxt);
196 if (ctxt.empty())
return nullptr;
197 syntax_err(
"':'", ctxt);
198 return ptr<ErrorExpr>(curr_);
206 auto track = tracker();
207 auto lhs = parse_primary_expr(ctxt);
208 return parse_infix_expr(track, std::move(lhs), curr_prec);
214 switch (ahead().tag()) {
215 case Tag::T_extract: {
218 if (
auto tok = accept(Tag::M_id))
219 lhs = ptr<ExtractExpr>(track, std::move(lhs), tok.dbg());
222 lhs = ptr<ExtractExpr>(track, std::move(lhs), std::move(rhs));
230 lhs = ptr<ArrowExpr>(track, std::move(lhs), std::move(rhs));
236 auto rhs = parse_expr(
"explicit argument to an application",
Expr::Prec::App);
237 lhs = ptr<AppExpr>(track,
true, std::move(lhs), std::move(rhs));
242 switch (ahead().tag()) {
244 ast().
warn(ahead().loc(),
"you are passing a declaration expression as argument");
245 ast().
note(lhs->loc(),
"to this expression");
247 "if this was your intention, consider to parenthesize the declaration expression");
248 ast().
note(lhs->loc().anew_finis(),
"otherwise, you are probably missing a ';'");
252 lhs = ptr<AppExpr>(track,
false, std::move(lhs), std::move(rhs));
258 auto decls = parse_decls();
259 lhs = ptr<DeclExpr>(track, std::move(decls), std::move(lhs),
true);
261 bool where = ahead().tag() == Tag::K_where;
262 expect(Tag::K_end,
"end of a where declaration block");
264 ast().
note(lhs->loc().anew_finis(),
265 "did you accidentally end your declaration expression with a ';'?");
275 auto track = tracker();
276 expect(Tag::D_paren_l,
"opening paren for insert arguments");
277 auto tuple = parse_expr(
"the tuple to insert into");
278 expect(Tag::T_comma,
"comma after tuple to insert into");
279 auto index = parse_expr(
"insert index");
280 expect(Tag::T_comma,
"comma after insert index");
281 auto value = parse_expr(
"insert value");
282 expect(Tag::D_paren_r,
"closing paren for insert arguments");
283 return ptr<InsertExpr>(track, std::move(tuple), std::move(index), std::move(value));
287 auto track = tracker();
288 expect(Tag::D_curly_l,
"opening curly bracket for singleton type");
289 auto inhabitant = parse_expr(
"singleton type");
290 expect(Tag::D_curly_r,
"closing curly bracket for singleton type");
291 return ptr<UniqExpr>(track, std::move(inhabitant));
294Ptr<Expr> Parser::parse_primary_expr(std::string_view ctxt) {
296 switch (ahead().tag()) {
297 case Tag::C_PRIMARY:
return ptr<PrimaryExpr>(lex());
298 case Tag::C_ID:
return ptr<IdExpr>(lex().dbg());
299 case Tag::C_LIT:
return parse_lit_expr();
300 case Tag::C_DECL:
return parse_decl_expr();
301 case Tag::C_PI:
return parse_pi_expr();
302 case Tag::C_LM:
return parse_lam_expr();
303 case Tag::K_ins:
return parse_insert_expr();
304 case Tag::K_ret:
return parse_ret_expr();
305 case Tag::D_curly_l:
return parse_uniq_expr();
306 case Tag::D_quote_l:
return parse_arr_or_pack_expr<true>();
307 case Tag::D_angle_l:
return parse_arr_or_pack_expr<false>();
308 case Tag::D_brckt_l:
return parse_sigma_expr();
309 case Tag::D_paren_l:
return parse_tuple_expr();
310 case Tag::K_Type:
return parse_type_expr();
312 if (ctxt.empty())
return nullptr;
313 syntax_err(
"primary expression", ctxt);
316 return ptr<ErrorExpr>(curr_);
319template<
bool arr>
Ptr<Expr> Parser::parse_arr_or_pack_expr() {
320 auto track = tracker();
321 eat(arr ? Tag::D_quote_l : Tag::D_angle_l);
323 std::deque<std::pair<Ptr<IdPtrn>,
Ptr<Expr>>> shapes;
327 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::T_colon)) {
328 dbg = eat(Tag::M_id).dbg();
332 auto expr = parse_expr(arr ?
"shape of an array" :
"shape of a pack");
334 shapes.emplace_back(std::move(ptrn), std::move(expr));
335 }
while (accept(Tag::T_comma));
337 expect(Tag::T_semicolon, arr ?
"array" :
"pack");
338 auto body = parse_expr(arr ?
"body of an array" :
"body of a pack");
339 expect(arr ? Tag::D_quote_r : Tag::D_angle_r,
340 arr ?
"closing delimiter of an array" :
"closing delimiter of a pack");
342 for (
auto& [ptrn, expr] : shapes | std::ranges::views::reverse)
343 body = ptr<ArrOrPackExpr<arr>>(track, std::move(ptrn), std::move(body));
349 auto track = tracker();
350 auto decls = parse_decls();
351 auto expr = parse_expr(
"final expression of a declaration expression");
352 return ptr<DeclExpr>(track, std::move(decls), std::move(expr),
false);
356 auto track = tracker();
358 auto type = accept(Tag::T_colon) ? parse_expr(
"literal",
Expr::Prec::Lit) : nullptr;
359 return ptr<LitExpr>(track, tok, std::move(type));
363 auto track = tracker();
364 auto ptrn = parse_tuple_ptrn(Brckt_Style);
365 switch (ahead().tag()) {
368 auto alias = ptr<AliasPtrn>(track, std::move(ptrn), parse_name(
"alias pattern"));
369 return parse_pi_expr(std::move(alias));
371 case Tag::C_CURRIED_B:
372 case Tag::T_arrow:
return parse_pi_expr(std::move(ptrn));
373 default:
return ptr<SigmaExpr>(std::move(ptrn));
378 auto track = tracker();
380 parse_list(
"tuple", Tag::D_paren_l, [&]() { elems.emplace_back(parse_expr(
"tuple element")); });
381 return ptr<TupleExpr>(track, std::move(elems));
385 auto track = tracker();
388 return ptr<TypeExpr>(track, std::move(level));
392 auto track = tracker();
393 auto tag = ahead().tag();
394 auto entity =
"dependent function type"s;
396 if (accept(Tag::K_Cn))
397 entity =
"continuation type";
398 else if (accept(Tag::K_Fn))
399 entity =
"returning continuation type";
401 auto domt = tracker();
403 auto ptrn = parse_ptrn(Brckt_Style | Implicit,
"domain of a "s + entity, prec);
404 auto dom = ptr<PiExpr::Dom>(domt, std::move(ptrn));
406 auto codom = tag != Tag::K_Cn
407 ? (expect(Tag::T_arrow, entity), parse_expr(
"codomain of a "s + entity,
Expr::Prec::Arrow))
410 if (tag == Tag::K_Fn) dom->add_ret(
ast(), codom ? std::move(codom) : ptr<InferExpr>(curr_));
411 return ptr<PiExpr>(track, tag, std::move(dom), std::move(codom));
415 auto track = tracker(ptrn->loc());
416 auto entity =
"dependent function type"s;
417 auto dom = ptr<PiExpr::Dom>(ptrn->loc(), std::move(ptrn));
418 expect(Tag::T_arrow, entity);
420 return ptr<PiExpr>(track, Tag::Nil, std::move(dom), std::move(codom));
423Ptr<Expr> Parser::parse_lam_expr() {
return ptr<LamExpr>(parse_lam_decl()); }
426 auto track = tracker();
428 auto ptrn = parse_ptrn(Paren_Style,
"binding pattern of a ret expression");
429 expect(Tag::T_assign,
"ret expression");
430 auto callee = parse_expr(
"continuation expression of a ret expression");
431 expect(Tag::T_dollar,
"separator of a ret expression");
432 auto arg = parse_expr(
"argument of ret expression");
433 expect(Tag::T_semicolon,
"ret expression");
434 auto body = parse_expr(
"body of a ret expression");
435 return ptr<RetExpr>(track, std::move(ptrn), std::move(callee), std::move(arg), std::move(body));
443 auto track = tracker();
444 auto ptrn = parse_ptrn_(style, ctxt, prec);
445 if (accept(Tag::K_as))
return ptr<AliasPtrn>(track, std::move(ptrn), parse_name(
"alias pattern"));
450 auto track = tracker();
455 if (is_paren_style(style) && ahead().isa(Tag::D_paren_l))
return parse_tuple_ptrn(style);
456 if (is_implicit(style) && ahead().isa(Tag::D_brace_l))
return parse_tuple_ptrn(style);
457 if (ahead().isa(Tag::D_brckt_l))
return parse_tuple_ptrn(Brckt_Style);
459 if (ahead(0).isa(Tag::M_id)) {
460 if (ahead(1).isa(Tag::T_colon)) {
462 auto dbg = eat(Tag::M_id).dbg();
464 auto type = parse_expr(ctxt, prec);
465 return ptr<IdPtrn>(track, dbg, std::move(type));
466 }
else if (is_paren_style(style)) {
469 auto dbg = eat(Tag::M_id).dbg();
470 return ptr<IdPtrn>(track, dbg,
nullptr);
473 auto type = parse_expr(ctxt, prec);
474 return ptr<IdPtrn>(track, type->loc().anew_begin(), std::move(type));
476 }
else if (is_brket_style(style)) {
478 auto type = parse_expr(ctxt, prec);
479 auto loc = type->loc().anew_begin();
480 return ptr<IdPtrn>(track, Dbg(loc), std::move(type));
481 }
else if (!ctxt.empty()) {
483 syntax_err(
"pattern", ctxt);
484 return ptr<ErrorPtrn>(curr_);
491 auto track = tracker();
492 auto delim_l = ahead().tag();
495 parse_list(
"tuple pattern", delim_l, [&]() {
496 auto track = tracker();
499 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::M_id)) {
501 while (
auto tok = accept(Tag::M_id)) dbgs.emplace_back(tok.dbg());
503 if (accept(Tag::T_colon)) {
504 auto dbg = dbgs.back();
505 auto type = parse_expr(
"type of an identifier group within a tuple pattern");
506 auto id = ptr<IdPtrn>(
dbg.loc() + type->loc().finis, dbg, std::move(type));
508 for (
auto dbg : dbgs | std::views::take(dbgs.size() - 1))
509 ptrns.emplace_back(ptr<GrpPtrn>(dbg,
id.
get()));
510 ptrns.emplace_back(std::move(
id));
515 Ptr<Expr> lhs = ptr<IdExpr>(dbgs.front());
516 for (
auto dbg : dbgs | std::views::drop(1)) {
517 auto rhs = ptr<IdExpr>(dbg);
518 lhs = ptr<AppExpr>(track,
false, std::move(lhs), std::move(rhs));
523 ptrn = parse_ptrn(style & Style_Bit,
"element of a tuple pattern");
525 if (is_brket_style(style)) {
527 if (ahead().isa(Tag::T_arrow)) {
528 auto loc = ptrn->loc();
529 auto expr = parse_pi_expr(std::move(ptrn));
530 ptrn = ptr<IdPtrn>(loc, Dbg(loc.anew_begin(), Sym()), std::move(expr));
533 auto addr = expr.get();
534 expr = parse_infix_expr(track, std::move(expr));
535 if (expr.get() != addr) {
536 auto loc = expr->loc();
537 ptrn = ptr<IdPtrn>(loc, Dbg(loc.anew_begin(), Sym()), std::move(expr));
545 ptrns.emplace_back(std::move(ptrn));
548 return ptr<TuplePtrn>(track, delim_l, std::move(ptrns));
559 switch (ahead().tag()) {
560 case Tag::T_semicolon: lex();
break;
561 case Tag::K_axm: decls.emplace_back(parse_axiom_decl());
break;
563 case Tag::K_cfun: decls.emplace_back(parse_c_decl());
break;
564 case Tag::K_let: decls.emplace_back(parse_let_decl());
break;
565 case Tag::K_rec: decls.emplace_back(parse_rec_decl(
true));
break;
568 case Tag::K_lam: decls.emplace_back(parse_lam_decl());
break;
569 default:
return decls;
576 auto track = tracker();
580 if (
auto name = expect(Tag::M_anx,
"annex name of an axiom"))
583 dbg = Dbg(curr_,
ast().sym(
"<error annex name>"));
585 std::deque<Ptrs<AxiomDecl::Alias>> subs;
586 if (ahead().isa(Tag::D_paren_l)) {
587 parse_list(
"tag list of an axiom", Tag::D_paren_l, [&]() {
588 auto& aliases = subs.emplace_back();
589 aliases.emplace_back(ptr<AxiomDecl::Alias>(parse_id(
"tag of an axiom")));
590 while (accept(Tag::T_assign))
591 aliases.emplace_back(ptr<AxiomDecl::Alias>(parse_id(
"alias of an axiom tag")));
595 auto type = parse_type_ascr(
"type ascription of an axiom");
597 if (ahead(0).isa(Tag::T_comma) && ahead(1).isa(Tag::M_id)) {
599 normalizer = lex().dbg();
601 if (accept(Tag::T_comma)) {
602 if (
auto c = expect(Tag::L_u,
"curry counter for axiom")) curry =
c;
603 if (accept(Tag::T_comma)) {
604 if (
auto t = expect(Tag::L_u,
"trip count for axiom")) trip =
t;
608 return ptr<AxiomDecl>(track, dbg, std::move(subs), std::move(type), normalizer, curry, trip);
612 auto track = tracker();
616 if (
auto anx = accept(Tok::Tag::M_anx)) {
617 auto type = parse_type_ascr();
618 ptrn = ptr<IdPtrn>(track, anx.dbg(), std::move(type));
620 ptrn = parse_ptrn(Paren_Style,
"binding pattern of a let declaration",
Expr::Prec::Bot);
623 expect(Tag::T_assign,
"let");
624 auto type = parse_type_ascr();
625 auto value = parse_expr(
"value of a let declaration");
626 return ptr<LetDecl>(track, std::move(ptrn), std::move(value));
630 auto track = tracker();
631 auto tag = lex().tag();
632 auto id = expect(Tag::M_id,
"C function declaration");
633 auto dom = parse_ptrn(Brckt_Style,
"domain of a C function"s,
Expr::Prec::App);
635 if (tag == Tag::K_cfun) {
636 expect(Tag::T_colon,
"codomain of a C function");
637 codom = parse_expr(
"codomain of a C function");
639 return ptr<CDecl>(track, tag,
id.
dbg(), std::move(dom), std::move(codom));
643 auto track = tracker();
644 eat(first ? Tag::K_rec : Tag::K_and);
645 auto dbg = parse_name(
"recursive declaration");
646 auto type = accept(Tag::T_colon) ? parse_expr(
"type of a recursive declaration") : ptr<InferExpr>(curr_);
647 expect(Tag::T_assign,
"recursive declaration");
648 auto body = parse_expr(
"body of a recursive declaration");
649 auto next = ahead().isa(Tag::K_and) ? parse_and_decl() : nullptr;
650 return ptr<RecDecl>(track, dbg, std::move(type), std::move(body), std::move(next));
654 auto track = tracker();
655 auto tag = lex().tag();
657 bool external = (bool)accept(Tag::K_extern);
663 case Tag::T_lm: decl =
false; entity =
"function expression";
break;
664 case Tag::K_cn: decl =
false; entity =
"continuation expression";
break;
665 case Tag::K_fn: decl =
false; entity =
"returning continuation expression";
break;
666 case Tag::K_lam: decl = true ; entity =
"function declaration";
break;
667 case Tag::K_con: decl = true ; entity =
"continuation declaration";
break;
668 case Tag::K_fun: decl = true ; entity =
"returning continuation declaration";
break;
669 default: fe::unreachable();
673 auto dbg = decl ? parse_name(entity) : Dbg();
676 auto track = tracker();
677 auto ptrn = parse_ptrn(Paren_Style | Implicit,
"domain pattern of a "s + entity, prec);
678 auto filter = accept(Tag::T_at) ? parse_expr(
"filter") : nullptr;
679 doms.emplace_back(ptr<LamDecl::Dom>(track, std::move(ptrn), std::move(filter)));
681 switch (ahead().tag()) {
682 case Tag::C_CURRIED_P:
continue;
688 auto codom = accept(Tag::T_colon) ? parse_expr(
"codomain of a "s + entity,
Expr::Prec::Arrow) : nullptr;
689 if (tag == Tag::K_fn || tag == Tag::K_fun)
690 doms.back()->add_ret(
ast(), codom ? std::move(codom) : ptr<InferExpr>(curr_));
692 expect(Tag::T_assign,
"body of a "s + entity);
693 auto body = parse_expr(
"body of a "s + entity);
694 auto next = ahead().isa(Tag::K_and) ? parse_and_decl() : nullptr;
696 return ptr<LamDecl>(track, tag, external, dbg, std::move(doms), std::move(codom), std::move(body), std::move(next));
700 switch (ahead(1).tag()) {
701 case Tag::C_LAM:
return lex(), parse_lam_decl();
702 default:
return parse_rec_decl(
false);
Error & note(Loc loc, const char *fmt, Args &&... args) const
Error & warn(Loc loc, const char *fmt, Args &&... args) const
static Ptr< IdPtrn > make_type(AST &ast, Ptr< Expr > &&type)
static Ptr< IdPtrn > make_id(AST &ast, Dbg dbg, Ptr< Expr > &&type)
Ptr< Module > import(std::string_view sv)
Ptr< Module > plugin(Dbg)
static Ptr< Ptrn > to_ptrn(Ptr< Expr > &&)
static Ptr< Expr > to_expr(AST &, Ptr< Ptrn > &&)
fe::Arena::Ptr< const T > Ptr
std::deque< Ptr< T > > Ptrs
void * get(void *handle, const char *symbol_name)