76 case Tag::D_angle_l: \
77 case Tag::D_brckt_l: \
78 case Tag::D_paren_l: \
83 case Tag::D_brckt_l: \
88 case Tag::D_brckt_l: \
93 case Tag::D_brckt_l: \
97using namespace std::string_literals;
108 auto track = tracker();
111 if (ahead().isa(Tag::K_import) || ahead().isa(Tag::K_plugin)) {
112 if (
auto import = parse_import_or_plugin()) imports.emplace_back(std::move(
import));
117 auto decls = parse_decls();
118 bool where = ahead().isa(Tag::K_where);
119 expect(Tag::EoF,
"module");
120 auto mod = ptr<Module>(track, std::move(imports), std::move(decls));
121 if (where)
ast().
note(mod->loc().anew_finis(),
"did you accidentally end your declaration expression with a ';'?");
126 auto name = dbg.sym();
127 auto filename = fs::path(name.view());
128 driver().VLOG(
"import: {}", name);
130 if (!filename.has_extension()) filename.replace_extension(
"mim");
133 for (
const auto& path :
driver().search_paths()) {
134 std::error_code ignore;
135 rel_path = path / filename;
136 if (
bool reg_file = fs::is_regular_file(rel_path, ignore); reg_file && !ignore)
break;
137 rel_path = path / name.view() / filename;
138 if (
bool reg_file = fs::is_regular_file(rel_path, ignore); reg_file && !ignore)
break;
141 if (
auto path =
driver().add_import(std::move(rel_path), name)) {
142 auto ifs = std::ifstream(*path);
143 return import(ifs, dbg.loc(), path, md);
149 driver().VLOG(
"reading: {}", path ? path->string() :
"<unknown file>"s);
151 ast().
error(loc,
"cannot read file {}", *path);
155 auto state = std::tuple(prev_, ahead_, lexer_);
156 auto lexer =
Lexer(
ast(), is, path, md);
159 auto mod = parse_module();
160 std::tie(prev_, ahead_, lexer_) = state;
174 auto track = tracker();
175 auto tag = lex().tag();
176 auto name = expect(Tag::M_id,
"{} name", tag == Tag::K_import ?
"import" :
"plugin");
177 auto dbg = name.dbg();
178 expect(Tag::T_semicolon,
"end of {}", tag == Tag::K_import ?
"import" :
"plugin");
179 if (
auto module = tag == Tag::K_import ?
import(dbg) :
plugin(dbg))
180 return ptr<Import>(track, tag, name.dbg(), std::move(module));
184Dbg Parser::parse_id(std::string_view ctxt) {
185 if (
auto id = accept(Tag::M_id))
return id.dbg();
186 syntax_err(
"identifier", ctxt);
187 return {prev_,
driver().sym(
"<error>")};
190Dbg Parser::parse_name(std::string_view ctxt) {
191 if (
auto tok = accept(Tag::M_anx))
return tok.dbg();
192 if (
auto tok = accept(Tag::M_id))
return tok.dbg();
193 syntax_err(
"identifier or annex name", ctxt);
194 return Dbg(prev_,
ast().sym(
"<error>"));
197Ptr<Expr> Parser::parse_type_ascr(std::string_view ctxt) {
198 if (accept(Tag::T_colon))
return parse_expr(ctxt);
199 if (ctxt.empty())
return nullptr;
200 syntax_err(
"':'", ctxt);
201 return ptr<ErrorExpr>(prev_);
209 auto track = tracker();
210 auto lhs = parse_primary_expr(ctxt);
211 return parse_infix_expr(track, std::move(lhs), curr_prec);
217 switch (ahead().tag()) {
218 case Tag::T_extract: {
221 if (
auto tok = accept(Tag::M_id))
222 lhs = ptr<ExtractExpr>(track.loc(), std::move(lhs), tok.dbg());
225 lhs = ptr<ExtractExpr>(track.loc(), std::move(lhs), std::move(rhs));
233 lhs = ptr<ArrowExpr>(track.loc(), std::move(lhs), std::move(rhs));
239 auto rhs = parse_expr(
"explicit argument to an application",
Expr::Prec::App);
240 lhs = ptr<AppExpr>(track.loc(),
true, std::move(lhs), std::move(rhs));
245 switch (ahead().tag()) {
247 ast().
warn(ahead().loc(),
"you are passing a declaration expression as argument");
248 ast().
note(lhs->loc(),
"to this expression");
250 "if this was your intention, consider to parenthesize the declaration expression");
251 ast().
note(lhs->loc().anew_finis(),
"otherwise, you are probably missing a ';'");
255 lhs = ptr<AppExpr>(track.loc(),
false, std::move(lhs), std::move(rhs));
261 auto decls = parse_decls();
262 lhs = ptr<DeclExpr>(track, std::move(decls), std::move(lhs),
true);
264 bool where = ahead().tag() == Tag::K_where;
265 expect(Tag::K_end,
"end of a where declaration block");
267 ast().
note(lhs->loc().anew_finis(),
268 "did you accidentally end your declaration expression with a ';'?");
278 auto track = tracker();
279 expect(Tag::D_paren_l,
"opening paren for insert arguments");
280 auto tuple = parse_expr(
"the tuple to insert into");
281 expect(Tag::T_comma,
"comma after tuple to insert into");
282 auto index = parse_expr(
"insert index");
283 expect(Tag::T_comma,
"comma after insert index");
284 auto value = parse_expr(
"insert value");
285 expect(Tag::D_paren_r,
"closing paren for insert arguments");
286 return ptr<InsertExpr>(track.loc(), std::move(tuple), std::move(index), std::move(value));
289Ptr<Expr> Parser::parse_primary_expr(std::string_view ctxt) {
291 switch (ahead().tag()) {
292 case Tag::C_PRIMARY:
return ptr<PrimaryExpr>(lex());
293 case Tag::C_ID:
return ptr<IdExpr>(lex().dbg());
294 case Tag::C_LIT:
return parse_lit_expr();
295 case Tag::C_DECL:
return parse_decl_expr();
296 case Tag::C_PI:
return parse_pi_expr();
297 case Tag::C_LM:
return parse_lam_expr();
298 case Tag::K_ins:
return parse_insert_expr();
299 case Tag::K_ret:
return parse_ret_expr();
300 case Tag::D_quote_l:
return parse_arr_or_pack_expr<true>();
301 case Tag::D_angle_l:
return parse_arr_or_pack_expr<false>();
302 case Tag::D_brckt_l:
return parse_sigma_expr();
303 case Tag::D_paren_l:
return parse_tuple_expr();
304 case Tag::K_Type:
return parse_type_expr();
306 if (ctxt.empty())
return nullptr;
307 syntax_err(
"primary expression", ctxt);
310 return ptr<ErrorExpr>(prev_);
313template<
bool arr>
Ptr<Expr> Parser::parse_arr_or_pack_expr() {
314 auto track = tracker();
315 eat(arr ? Tag::D_quote_l : Tag::D_angle_l);
318 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::T_colon)) {
319 dbg = eat(Tag::M_id).dbg();
323 auto shape = parse_expr(arr ?
"shape of an array" :
"shape of a pack");
325 expect(Tag::T_semicolon, arr ?
"array" :
"pack");
326 auto body = parse_expr(arr ?
"body of an array" :
"body of a pack");
327 expect(arr ? Tag::D_quote_r : Tag::D_angle_r,
328 arr ?
"closing delimiter of an array" :
"closing delimiter of a pack");
330 return ptr<ArrOrPackExpr<arr>>(track, std::move(ptrn), std::move(body));
334 auto track = tracker();
335 auto decls = parse_decls();
336 auto expr = parse_expr(
"final expression of a declaration expression");
337 return ptr<DeclExpr>(track, std::move(decls), std::move(expr),
false);
341 auto track = tracker();
343 auto type = accept(Tag::T_colon) ? parse_expr(
"literal",
Expr::Prec::Lit) : nullptr;
344 return ptr<LitExpr>(track, tok, std::move(type));
348 auto track = tracker();
349 auto ptrn = parse_tuple_ptrn(Brckt_Style);
350 switch (ahead().tag()) {
353 auto alias = ptr<AliasPtrn>(track, std::move(ptrn), parse_name(
"alias pattern"));
354 return parse_pi_expr(std::move(alias));
356 case Tag::C_CURRIED_B:
357 case Tag::T_arrow:
return parse_pi_expr(std::move(ptrn));
358 default:
return ptr<SigmaExpr>(std::move(ptrn));
363 auto track = tracker();
365 parse_list(
"tuple", Tag::D_paren_l, [&]() { elems.emplace_back(parse_expr(
"tuple element")); });
366 return ptr<TupleExpr>(track, std::move(elems));
370 auto track = tracker();
373 return ptr<TypeExpr>(track, std::move(level));
377 auto track = tracker();
378 auto tag = ahead().tag();
379 auto entity =
"dependent function type"s;
380 bool has_first = ptrn.get();
382 if (accept(Tag::K_Cn))
383 entity =
"continuation type";
384 else if (accept(Tag::K_Fn))
385 entity =
"returning continuation type";
388 if (has_first) doms.emplace_back(ptr<PiExpr::Dom>(ptrn->loc(), std::move(ptrn)));
390 if (!has_first || !ahead().isa(Tag::T_arrow)) {
392 auto track = tracker();
394 auto ptrn = parse_ptrn(Brckt_Style | Implicit,
"domain of a "s + entity, prec);
395 doms.emplace_back(ptr<PiExpr::Dom>(track, std::move(ptrn)));
397 switch (ahead().tag()) {
398 case Tag::C_CURRIED_B:
continue;
405 auto codom = tag != Tag::K_Cn
406 ? (expect(Tag::T_arrow, entity), parse_expr(
"codomain of a "s + entity,
Expr::Prec::Arrow))
409 if (tag == Tag::K_Fn) doms.back()->add_ret(
ast(), codom ? std::move(codom) : ptr<InferExpr>(prev_));
412 auto loc = ptrn ? ptrn->loc() + track.loc() : track.loc();
413 return ptr<PiExpr>(loc, tag, std::move(doms), std::move(codom));
416Ptr<Expr> Parser::parse_lam_expr() {
return ptr<LamExpr>(parse_lam_decl()); }
419 auto track = tracker();
421 auto ptrn = parse_ptrn(Paren_Style,
"binding pattern of a ret expression");
422 expect(Tag::T_assign,
"ret expression");
423 auto callee = parse_expr(
"continuation expression of a ret expression");
424 expect(Tag::T_dollar,
"separator of a ret expression");
425 auto arg = parse_expr(
"argument of ret expression");
426 expect(Tag::T_semicolon,
"ret expression");
427 auto body = parse_expr(
"body of a ret expression");
428 return ptr<RetExpr>(track, std::move(ptrn), std::move(callee), std::move(arg), std::move(body));
436 auto track = tracker();
437 auto ptrn = parse_ptrn_(style, ctxt, prec);
438 if (accept(Tag::K_as))
return ptr<AliasPtrn>(track, std::move(ptrn), parse_name(
"alias pattern"));
443 auto track = tracker();
448 if ((style & Style_Bit) == Paren_Style && ahead().isa(Tag::D_paren_l))
return parse_tuple_ptrn(style);
449 if (style & Implicit && ahead().isa(Tag::D_brace_l))
return parse_tuple_ptrn(style);
450 if (ahead().isa(Tag::D_brckt_l))
return parse_tuple_ptrn(Brckt_Style);
452 if (ahead(0).isa(Tag::M_id)) {
453 if (ahead(1).isa(Tag::T_colon)) {
455 auto dbg = eat(Tag::M_id).dbg();
457 auto type = parse_expr(ctxt, prec);
458 return ptr<IdPtrn>(track, dbg, std::move(type));
459 }
else if ((style & Style_Bit) == Paren_Style) {
462 auto dbg = eat(Tag::M_id).dbg();
463 return ptr<IdPtrn>(track, dbg,
nullptr);
466 auto type = parse_expr(ctxt, prec);
467 return ptr<IdPtrn>(track, type->loc().anew_begin(), std::move(type));
469 }
else if ((style & Style_Bit) == Brckt_Style) {
471 auto type = parse_expr(ctxt, prec);
472 auto loc = type->loc().anew_begin();
473 return ptr<IdPtrn>(track, Dbg(loc), std::move(type));
474 }
else if (!ctxt.empty()) {
476 syntax_err(
"pattern", ctxt);
477 return ptr<ErrorPtrn>(prev_);
484 auto track = tracker();
485 auto delim_l = ahead().tag();
488 parse_list(
"tuple pattern", delim_l, [&]() {
489 auto track = tracker();
492 if (ahead(0).isa(Tag::M_id) && ahead(1).isa(Tag::M_id)) {
494 while (
auto tok = accept(Tag::M_id)) dbgs.emplace_back(tok.dbg());
496 if (accept(Tag::T_colon)) {
497 auto dbg = dbgs.back();
498 auto type = parse_expr(
"type of an identifier group within a tuple pattern");
499 auto id = ptr<IdPtrn>(
dbg.loc() + type->loc().finis, dbg, std::move(type));
501 for (
auto dbg : dbgs | std::views::take(dbgs.size() - 1))
502 ptrns.emplace_back(ptr<GrpPtrn>(dbg,
id.
get()));
503 ptrns.emplace_back(std::move(
id));
508 Ptr<Expr> lhs = ptr<IdExpr>(dbgs.front());
509 for (
auto dbg : dbgs | std::views::drop(1)) {
510 auto rhs = ptr<IdExpr>(dbg);
511 lhs = ptr<AppExpr>(track,
false, std::move(lhs), std::move(rhs));
516 ptrn = parse_ptrn(style & Style_Bit,
"element of a tuple pattern");
518 if ((style & Style_Bit) == Brckt_Style) {
520 if (ahead().isa(Tag::T_arrow)) {
521 auto loc = ptrn->loc();
522 auto expr = parse_pi_expr(std::move(ptrn));
523 ptrn = ptr<IdPtrn>(loc, Dbg(loc.anew_begin(), Sym()), std::move(expr));
526 auto addr = expr.get();
527 expr = parse_infix_expr(track, std::move(expr));
528 if (expr.get() != addr) {
529 auto loc = expr->loc();
530 ptrn = ptr<IdPtrn>(loc, Dbg(loc.anew_begin(), Sym()), std::move(expr));
538 ptrns.emplace_back(std::move(ptrn));
541 return ptr<TuplePtrn>(track, delim_l, std::move(ptrns));
552 switch (ahead().tag()) {
553 case Tag::T_semicolon: lex();
break;
554 case Tag::K_axm: decls.emplace_back(parse_axiom_decl());
break;
556 case Tag::K_cfun: decls.emplace_back(parse_c_decl());
break;
557 case Tag::K_let: decls.emplace_back(parse_let_decl());
break;
558 case Tag::K_rec: decls.emplace_back(parse_rec_decl(
true));
break;
561 case Tag::K_lam: decls.emplace_back(parse_lam_decl());
break;
562 default:
return decls;
569 auto track = tracker();
573 if (
auto name = expect(Tag::M_anx,
"annex name of an axiom"))
576 dbg = Dbg(prev_,
ast().sym(
"<error annex name>"));
578 std::deque<Ptrs<AxiomDecl::Alias>> subs;
579 if (ahead().isa(Tag::D_paren_l)) {
580 parse_list(
"tag list of an axiom", Tag::D_paren_l, [&]() {
581 auto& aliases = subs.emplace_back();
582 aliases.emplace_back(ptr<AxiomDecl::Alias>(parse_id(
"tag of an axiom")));
583 while (accept(Tag::T_assign))
584 aliases.emplace_back(ptr<AxiomDecl::Alias>(parse_id(
"alias of an axiom tag")));
588 auto type = parse_type_ascr(
"type ascription of an axiom");
590 if (ahead(0).isa(Tag::T_comma) && ahead(1).isa(Tag::M_id)) {
592 normalizer = lex().dbg();
594 if (accept(Tag::T_comma)) {
595 if (
auto c = expect(Tag::L_u,
"curry counter for axiom")) curry =
c;
596 if (accept(Tag::T_comma)) {
597 if (
auto t = expect(Tag::L_u,
"trip count for axiom")) trip =
t;
601 return ptr<AxiomDecl>(track, dbg, std::move(subs), std::move(type), normalizer, curry, trip);
605 auto track = tracker();
609 if (
auto anx = accept(Tok::Tag::M_anx)) {
610 auto type = parse_type_ascr();
611 ptrn = ptr<IdPtrn>(track, anx.dbg(), std::move(type));
613 ptrn = parse_ptrn(Paren_Style,
"binding pattern of a let declaration",
Expr::Prec::Bot);
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(Brckt_Style,
"domain of a C function"s,
Expr::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 auto ptrn = parse_ptrn(Paren_Style | Implicit,
"domain pattern of a "s + entity, prec);
671 auto filter = accept(Tag::T_at) ? parse_expr(
"filter") : nullptr;
672 doms.emplace_back(ptr<LamDecl::Dom>(track, std::move(ptrn), std::move(filter)));
674 switch (ahead().tag()) {
675 case Tag::C_CURRIED_P:
continue;
681 auto codom = accept(Tag::T_colon) ? parse_expr(
"codomain of a "s + entity,
Expr::Prec::Arrow) : nullptr;
682 if (tag == Tag::K_fn || tag == Tag::K_fun)
683 doms.back()->add_ret(
ast(), codom ? std::move(codom) : ptr<InferExpr>(prev_));
685 expect(Tag::T_assign,
"body of a "s + entity);
686 auto body = parse_expr(
"body of a "s + entity);
687 auto next = ahead().isa(Tag::K_and) ? parse_and_decl() : nullptr;
689 return ptr<LamDecl>(track, tag, external, dbg, std::move(doms), std::move(codom), std::move(body), std::move(next));
693 switch (ahead(1).tag()) {
694 case Tag::C_LAM:
return lex(), parse_lam_decl();
695 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)