76 case Tag::D_angle_l: \
77 case Tag::D_brckt_l: \
78 case Tag::D_paren_l: \
83 case Tag::T_backtick: \
84 case Tag::D_brace_l: \
85 case Tag::D_brckt_l: \
89using namespace std::string_literals;
100 auto track = tracker();
103 if (ahead().isa(Tag::K_import) || ahead().isa(Tag::K_plugin)) {
104 if (
auto import = parse_import_or_plugin()) imports.emplace_back(std::move(
import));
109 auto decls = parse_decls();
110 bool where = ahead().isa(Tag::K_where);
111 expect(Tag::EoF,
"module");
112 auto mod = ptr<Module>(track, std::move(imports), std::move(decls));
113 if (where)
ast().
note(mod->loc().anew_finis(),
"did you accidentally end your declaration expression with a ';'?");
118 auto name = dbg.sym();
119 auto filename = fs::path(name.view());
120 driver().VLOG(
"import: {}", name);
122 if (!filename.has_extension()) filename.replace_extension(
"mim");
125 for (
const auto& path :
driver().search_paths()) {
126 std::error_code ignore;
127 rel_path = path / filename;
128 if (
bool reg_file = fs::is_regular_file(rel_path, ignore); reg_file && !ignore)
break;
129 rel_path = path / name.view() / filename;
130 if (
bool reg_file = fs::is_regular_file(rel_path, ignore); reg_file && !ignore)
break;
133 if (
auto path =
driver().add_import(std::move(rel_path), name)) {
134 auto ifs = std::ifstream(*path);
135 return import(ifs, dbg.loc(), path, md);
141 driver().VLOG(
"reading: {}", path ? path->string() :
"<unknown file>"s);
143 ast().
error(loc,
"cannot read file {}", *path);
147 auto state = std::tuple(prev_, ahead_, lexer_);
148 auto lexer =
Lexer(
ast(), is, path, md);
151 auto mod = parse_module();
152 std::tie(prev_, ahead_, lexer_) = state;
166 auto track = tracker();
167 auto tag = lex().tag();
168 auto name = expect(Tag::M_id,
"{} name", tag == Tag::K_import ?
"import" :
"plugin");
169 auto dbg = name.dbg();
170 expect(Tag::T_semicolon,
"end of {}", tag == Tag::K_import ?
"import" :
"plugin");
171 if (
auto module = tag == Tag::K_import ?
import(dbg) :
plugin(dbg))
172 return ptr<Import>(track, tag, name.dbg(), std::move(module));
176Dbg Parser::parse_id(std::string_view ctxt) {
177 if (
auto id = accept(Tag::M_id))
return id.dbg();
178 syntax_err(
"identifier", ctxt);
179 return {prev_,
driver().sym(
"<error>")};
182Dbg Parser::parse_name(std::string_view ctxt) {
183 if (
auto tok = accept(Tag::M_anx))
return tok.dbg();
184 if (
auto tok = accept(Tag::M_id))
return tok.dbg();
185 syntax_err(
"identifier or annex name", ctxt);
186 return Dbg(prev_,
ast().sym(
"<error>"));
189Ptr<Expr> Parser::parse_type_ascr(std::string_view ctxt) {
190 if (accept(Tag::T_colon))
return parse_expr(ctxt);
191 if (ctxt.empty())
return nullptr;
192 syntax_err(
"':'", ctxt);
193 return ptr<ErrorExpr>(prev_);
200Ptr<Expr> Parser::parse_expr(std::string_view ctxt,
Prec curr_prec) {
201 auto track = tracker();
202 auto lhs = parse_primary_expr(ctxt);
203 return parse_infix_expr(track, std::move(lhs), curr_prec);
209 switch (ahead().tag()) {
210 case Tag::T_extract: {
213 if (
auto tok = accept(Tag::M_id))
214 lhs = ptr<ExtractExpr>(track.loc(), std::move(lhs), tok.dbg());
216 auto rhs = parse_expr(
"right-hand side of an extract",
Prec::Extract);
217 lhs = ptr<ExtractExpr>(track.loc(), std::move(lhs), std::move(rhs));
224 auto rhs = parse_expr(
"right-hand side of a function type",
Prec::Arrow);
225 lhs = ptr<ArrowExpr>(track.loc(), std::move(lhs), std::move(rhs));
231 auto rhs = parse_expr(
"explicit argument to an application",
Prec::App);
232 lhs = ptr<AppExpr>(track.loc(),
true, std::move(lhs), std::move(rhs));
237 switch (ahead().tag()) {
239 ast().
warn(ahead().loc(),
"you are passing a declaration expression as argument");
240 ast().
note(lhs->loc(),
"to this expression");
242 "if this was your intention, consider to parenthesize the declaration expression");
243 ast().
note(lhs->loc().anew_finis(),
"otherwise, you are probably missing a ';'");
246 auto rhs = parse_expr(
"argument to an application",
Prec::App);
247 lhs = ptr<AppExpr>(track.loc(),
false, std::move(lhs), std::move(rhs));
253 auto decls = parse_decls();
254 lhs = ptr<DeclExpr>(track, std::move(decls), std::move(lhs),
true);
256 bool where = ahead().tag() == Tag::K_where;
257 expect(Tag::K_end,
"end of a where declaration block");
259 ast().
note(lhs->loc().anew_finis(),
260 "did you accidentally end your declaration expression with a ';'?");
270 auto track = tracker();
271 expect(Tag::D_paren_l,
"opening paren for insert arguments");
272 auto tuple = parse_expr(
"the tuple to insert into");
273 expect(Tag::T_comma,
"comma after tuple to insert into");
274 auto index = parse_expr(
"insert index");
275 expect(Tag::T_comma,
"comma after insert index");
276 auto value = parse_expr(
"insert value");
277 expect(Tag::D_paren_r,
"closing paren for insert arguments");
278 return ptr<InsertExpr>(track.loc(), std::move(tuple), std::move(index), std::move(value));
281Ptr<Expr> Parser::parse_primary_expr(std::string_view ctxt) {
283 switch (ahead().tag()) {
284 case Tag::C_PRIMARY:
return ptr<PrimaryExpr>(lex());
285 case Tag::C_ID:
return ptr<IdExpr>(lex().dbg());
286 case Tag::C_LIT:
return parse_lit_expr();
287 case Tag::C_DECL:
return parse_decl_expr();
288 case Tag::C_PI:
return parse_pi_expr();
289 case Tag::C_LM:
return parse_lam_expr();
290 case Tag::K_ins:
return parse_insert_expr();
291 case Tag::K_ret:
return parse_ret_expr();
292 case Tag::D_quote_l:
return parse_arr_or_pack_expr<true>();
293 case Tag::D_angle_l:
return parse_arr_or_pack_expr<false>();
294 case Tag::D_brckt_l:
return parse_sigma_expr();
295 case Tag::D_paren_l:
return parse_tuple_expr();
296 case Tag::K_Type:
return parse_type_expr();
298 if (ctxt.empty())
return nullptr;
299 syntax_err(
"primary expression", ctxt);
302 return ptr<ErrorExpr>(prev_);
305template<
bool arr>
Ptr<Expr> Parser::parse_arr_or_pack_expr() {
306 auto track = tracker();
307 eat(arr ? Tag::D_quote_l : Tag::D_angle_l);
310 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::T_colon)) {
311 dbg = eat(Tag::M_id).dbg();
315 auto shape = parse_expr(arr ?
"shape of an array" :
"shape of a pack");
317 expect(Tag::T_semicolon, arr ?
"array" :
"pack");
318 auto body = parse_expr(arr ?
"body of an array" :
"body of a pack");
319 expect(arr ? Tag::D_quote_r : Tag::D_angle_r,
320 arr ?
"closing delimiter of an array" :
"closing delimiter of a pack");
322 return ptr<ArrOrPackExpr<arr>>(track, std::move(ptrn), std::move(body));
326 auto track = tracker();
327 auto decls = parse_decls();
328 auto expr = parse_expr(
"final expression of a declaration expression");
329 return ptr<DeclExpr>(track, std::move(decls), std::move(expr),
false);
333 auto track = tracker();
335 auto type = accept(Tag::T_colon) ? parse_expr(
"literal",
Prec::Lit) : nullptr;
336 return ptr<LitExpr>(track, tok, std::move(type));
340 auto ptrn = parse_tuple_ptrn();
341 if (ahead().isa(Tag::D_brace_l) || ahead().isa(Tag::D_brckt_l) || ahead().isa(Tag::T_arrow))
342 return parse_pi_expr(std::move(ptrn));
343 return ptr<SigmaExpr>(std::move(ptrn));
347 auto track = tracker();
349 parse_list(
"tuple", Tag::D_paren_l, [&]() { elems.emplace_back(parse_expr(
"tuple element")); });
350 return ptr<TupleExpr>(track, std::move(elems));
354 auto track = tracker();
356 auto level = parse_expr(
"type level",
Prec::App);
357 return ptr<TypeExpr>(track, std::move(level));
361 auto track = tracker();
362 auto tag = ahead().tag();
363 auto entity =
"dependent function type"s;
364 bool has_first = ptrn.get();
366 if (accept(Tag::K_Cn))
367 entity =
"continuation type";
368 else if (accept(Tag::K_Fn))
369 entity =
"returning continuation type";
372 if (has_first) doms.emplace_back(ptr<PiExpr::Dom>(ptrn->loc(),
false, std::move(ptrn)));
374 if (!has_first || !ahead().isa(Tag::T_arrow)) {
376 auto track = tracker();
377 auto implicit =
false;
379 if (ahead().isa(Tok::Tag::D_brace_l)) {
381 ptrn = parse_tuple_ptrn();
384 ptrn = parse_ptrn(Tag::D_brckt_l,
"domain of a "s + entity, prec);
387 doms.emplace_back(ptr<PiExpr::Dom>(track, implicit, std::move(ptrn)));
389 switch (ahead().tag()) {
390 case Tag::C_PTRN:
continue;
397 auto codom = tag != Tag::K_Cn ? (expect(Tag::T_arrow, entity), parse_expr(
"codomain of a "s + entity,
Prec::Arrow))
400 if (tag == Tag::K_Fn) doms.back()->add_ret(
ast(), codom ? std::move(codom) : ptr<InferExpr>(prev_));
403 auto loc = ptrn ? ptrn->loc() + track.loc() : track.loc();
404 return ptr<PiExpr>(loc, tag, std::move(doms), std::move(codom));
407Ptr<Expr> Parser::parse_lam_expr() {
return ptr<LamExpr>(parse_lam_decl()); }
410 auto track = tracker();
412 auto ptrn = parse_ptrn(Tag::D_paren_l,
"binding pattern of a ret expression");
413 expect(Tag::T_assign,
"ret expression");
414 auto callee = parse_expr(
"continuation expression of a ret expression");
415 expect(Tag::T_dollar,
"separator of a ret expression");
416 auto arg = parse_expr(
"argument of ret expression");
417 expect(Tag::T_semicolon,
"ret expression");
418 auto body = parse_expr(
"body of a ret expression");
419 return ptr<RetExpr>(track, std::move(ptrn), std::move(callee), std::move(arg), std::move(body));
426Ptr<Ptrn> Parser::parse_ptrn(Tag delim_l, std::string_view ctxt,
Prec prec,
bool allow_annex) {
427 auto track = tracker();
428 bool p = delim_l == Tag::D_paren_l;
429 bool b = delim_l == Tag::D_brckt_l;
430 assert((p ^ b) &&
"left delimiter must either be '(' or '['");
436 if (
auto anx = accept(Tok::Tag::M_anx)) {
437 auto type = parse_type_ascr();
438 return ptr<IdPtrn>(track,
false, anx.dbg(), std::move(type));
443 if (accept(Tok::Tag::T_backtick)) {
444 auto dbg = expect(Tok::Tag::M_id,
"identifier pattern").
dbg();
445 auto type = accept(Tok::Tag::T_colon) ? parse_expr(
"identifier pattern", prec) : nullptr;
446 return ptr<IdPtrn>(track,
true, dbg, std::move(type));
451 if ((p && ahead().isa(Tag::D_paren_l)) || ahead().isa(Tag::D_brckt_l))
return parse_tuple_ptrn();
453 if (ahead(0).isa(Tag::M_id)) {
454 if (ahead(1).isa(Tag::T_colon)) {
456 auto dbg = eat(Tag::M_id).dbg();
458 auto type = parse_expr(ctxt, prec);
459 return ptr<IdPtrn>(track,
false, dbg, std::move(type));
463 auto dbg = eat(Tag::M_id).dbg();
464 return ptr<IdPtrn>(track,
false, dbg,
nullptr);
467 auto type = parse_expr(ctxt, prec);
468 return ptr<IdPtrn>(track,
false, type->loc().anew_begin(), std::move(type));
472 auto type = parse_expr(ctxt, prec);
473 auto loc = type->loc().anew_begin();
474 return ptr<IdPtrn>(track,
false, Dbg(loc), std::move(type));
475 }
else if (!ctxt.empty()) {
477 syntax_err(
"pattern", ctxt);
478 return ptr<ErrorPtrn>(prev_);
485 auto track = tracker();
486 auto delim_l = ahead().tag();
489 parse_list(
"tuple pattern", delim_l, [&]() {
490 auto track = tracker();
493 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::M_id)) {
495 while (
auto tok = accept(Tag::M_id)) dbgs.emplace_back(tok.dbg());
497 if (accept(Tag::T_colon)) {
498 auto dbg = dbgs.back();
499 auto type = parse_expr(
"type of an identifier group within a tuple pattern");
500 auto id = ptr<IdPtrn>(
dbg.loc() + type->loc().finis,
false, dbg, std::move(type));
502 for (
auto dbg : dbgs | std::views::take(dbgs.size() - 1))
503 ptrns.emplace_back(ptr<GrpPtrn>(dbg,
id.
get()));
504 ptrns.emplace_back(std::move(
id));
509 Ptr<Expr> lhs = ptr<IdExpr>(dbgs.front());
510 for (
auto dbg : dbgs | std::views::drop(1)) {
511 auto rhs = ptr<IdExpr>(dbg);
512 lhs = ptr<AppExpr>(track,
false, std::move(lhs), std::move(rhs));
514 auto expr = parse_infix_expr(track, std::move(lhs),
Prec::App);
517 auto dl = delim_l == Tag::D_brace_l ? Tag::D_brckt_l : delim_l;
518 ptrn = parse_ptrn(dl,
"element of a tuple pattern");
520 if (dl == Tag::D_brckt_l) {
522 if (ahead().isa(Tag::T_arrow)) {
523 auto loc = ptrn->loc();
524 auto expr = parse_pi_expr(std::move(ptrn));
525 ptrn = ptr<IdPtrn>(loc,
false, Dbg(loc.anew_begin(), Sym()), std::move(expr));
528 auto addr = expr.get();
529 expr = parse_infix_expr(track, std::move(expr));
530 if (expr.get() != addr) {
531 auto loc = expr->loc();
532 ptrn = ptr<IdPtrn>(loc,
false, Dbg(loc.anew_begin(), Sym()), std::move(expr));
540 ptrns.emplace_back(std::move(ptrn));
545 if (accept(Tag::T_colon_colon)) {
546 rebind = (bool)accept(Tag::T_backtick);
547 dbg = eat(Tag::M_id).dbg();
549 return ptr<TuplePtrn>(track, delim_l, std::move(ptrns), rebind, dbg);
560 switch (ahead().tag()) {
561 case Tag::T_semicolon: lex();
break;
562 case Tag::K_ax: decls.emplace_back(parse_axiom_decl());
break;
564 case Tag::K_cfun: decls.emplace_back(parse_c_decl());
break;
565 case Tag::K_let: decls.emplace_back(parse_let_decl());
break;
566 case Tag::K_rec: decls.emplace_back(parse_rec_decl(
true));
break;
569 case Tag::K_lam: decls.emplace_back(parse_lam_decl());
break;
570 default:
return decls;
577 auto track = tracker();
581 if (
auto name = expect(Tag::M_anx,
"annex name of an axiom"))
584 dbg = Dbg(prev_,
ast().sym(
"<error annex name>"));
586 std::deque<Ptrs<AxiomDecl::Alias>> subs;
587 if (ahead().isa(Tag::D_paren_l)) {
588 parse_list(
"tag list of an axiom", Tag::D_paren_l, [&]() {
589 auto& aliases = subs.emplace_back();
590 aliases.emplace_back(ptr<AxiomDecl::Alias>(parse_id(
"tag of an axiom")));
591 while (accept(Tag::T_assign))
592 aliases.emplace_back(ptr<AxiomDecl::Alias>(parse_id(
"alias of an axiom tag")));
596 auto type = parse_type_ascr(
"type ascription of an axiom");
598 if (ahead(0).isa(Tag::T_comma) && ahead(1).isa(Tag::M_id)) {
600 normalizer = lex().dbg();
602 if (accept(Tag::T_comma)) {
603 if (
auto c = expect(Tag::L_u,
"curry counter for axiom")) curry =
c;
604 if (accept(Tag::T_comma)) {
605 if (
auto t = expect(Tag::L_u,
"trip count for axiom")) trip =
t;
609 return ptr<AxiomDecl>(track, dbg, std::move(subs), std::move(type), normalizer, curry, trip);
613 auto track = tracker();
615 auto ptrn = parse_ptrn(Tag::D_paren_l,
"binding pattern of a let declaration",
Prec::Bot,
true);
616 expect(Tag::T_assign,
"let");
617 auto type = parse_type_ascr();
618 auto value = parse_expr(
"value of a let declaration");
619 return ptr<LetDecl>(track, std::move(ptrn), std::move(value));
623 auto track = tracker();
624 auto tag = lex().tag();
625 auto id = expect(Tag::M_id,
"C function declaration");
626 auto dom = parse_ptrn(Tag::D_brckt_l,
"domain of a C function"s,
Prec::App);
628 if (tag == Tag::K_cfun) {
629 expect(Tag::T_colon,
"codomain of a C function");
630 codom = parse_expr(
"codomain of a C function");
632 return ptr<CDecl>(track, tag,
id.
dbg(), std::move(dom), std::move(codom));
636 auto track = tracker();
637 eat(first ? Tag::K_rec : Tag::K_and);
638 auto dbg = parse_name(
"recursive declaration");
639 auto type = accept(Tag::T_colon) ? parse_expr(
"type of a recursive declaration") : ptr<InferExpr>(prev_);
640 expect(Tag::T_assign,
"recursive declaration");
641 auto body = parse_expr(
"body of a recursive declaration");
642 auto next = ahead().isa(Tag::K_and) ? parse_and_decl() : nullptr;
643 return ptr<RecDecl>(track, dbg, std::move(type), std::move(body), std::move(next));
647 auto track = tracker();
648 auto tag = lex().tag();
650 bool external = (bool)accept(Tag::K_extern);
656 case Tag::T_lm: decl =
false; entity =
"function expression";
break;
657 case Tag::K_cn: decl =
false; entity =
"continuation expression";
break;
658 case Tag::K_fn: decl =
false; entity =
"returning continuation expression";
break;
659 case Tag::K_lam: decl = true ; entity =
"function declaration";
break;
660 case Tag::K_con: decl = true ; entity =
"continuation declaration";
break;
661 case Tag::K_fun: decl = true ; entity =
"returning continuation declaration";
break;
662 default: fe::unreachable();
666 auto dbg = decl ? parse_name(entity) : Dbg();
669 auto track = tracker();
670 bool implicit =
false;
672 if (ahead().isa(Tok::Tag::D_brace_l)) {
674 ptrn = parse_tuple_ptrn();
676 ptrn = parse_ptrn(Tag::D_paren_l,
"domain pattern of a "s + entity, prec);
678 auto filter = accept(Tag::T_at) ? parse_expr(
"filter") : nullptr;
680 doms.emplace_back(ptr<LamDecl::Dom>(track, implicit, std::move(ptrn), std::move(filter)));
681 switch (ahead().tag()) {
682 case Tag::C_PTRN:
continue;
688 auto codom = accept(Tag::T_colon) ? parse_expr(
"codomain of a "s + entity,
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>(prev_));
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 > mk_id(AST &ast, Dbg dbg, Ptr< Expr > &&type)
static Ptr< IdPtrn > mk_type(AST &ast, 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)