Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
Compiler_Parser.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
46#ifndef COMPILER_PARSER_H
47#define COMPILER_PARSER_H
48
49#include <string>
50
51#include <Compiler_AST.H>
53
54namespace Aleph {
55
65
76{
82 std::string source_name;
83
86 {
87 return tokens.peek();
88 }
89
92 {
93 return tokens.next();
94 }
95
99 bool match(const Compiler_Token_Kind kind)
100 {
101 return tokens.match(kind);
102 }
103
105 void emit_error(const Source_Span &span,
106 const std::string &message,
107 const std::string &code,
108 const std::string &note = "",
109 const std::string &help = "") const
110 {
111 if (diagnostics == nullptr)
112 return;
113
114 auto builder = diagnostics->error(span, message).code(code);
115 if (not note.empty())
116 builder.note(note);
117 if (not help.empty())
118 builder.help(help);
119 builder.emit();
120 }
121
124 {
125 return ast->make<Compiler_Invalid_Expr>(span);
126 }
127
130 {
131 return ast->make<Compiler_Invalid_Stmt>(span);
132 }
133
136 {
137 return ast->make<Compiler_Invalid_Type_Expr>(span);
138 }
139
145
148 {
149 return ast->make<Compiler_Invalid_Type_Decl>(span);
150 }
151
156 const std::string &message,
157 const std::string &code)
158 {
159 return tokens.expect(kind, message, code);
160 }
161
163 Compiler_Token expect_identifier(const std::string &context, const std::string &code = "PAR002")
164 {
165 return tokens.expect_identifier(context, code);
166 }
167
173
176 {
177 const auto tok = peek();
179 return next().span;
180
181 emit_error(tok.span.is_valid() ? tok.span : anchor, "expected ';' after statement", "PAR005");
182
183 if (tok.is_eof() or tok.kind == Compiler_Token_Kind::RBrace
185 return {};
186
188 return {};
189 }
190
193 {
194 const auto lparen = next();
195 auto *inner = parse_expression();
196 const auto rparen
197 = expect(Compiler_Token_Kind::RParen, "expected ')' to close grouped expression", "PAR003");
198 return ast->make<Compiler_Grouping_Expr>(inner, lparen.span, rparen.span);
199 }
200
203 {
204 const auto tok = peek();
205 switch (tok.kind)
206 {
208 {
209 const auto name = next();
210 return ast->make<Compiler_Identifier_Expr>(name.lexeme, name.span);
211 }
213 {
214 const auto lit = next();
216 lit.lexeme,
217 lit.span);
218 }
220 {
221 const auto lit = next();
223 lit.lexeme,
224 lit.span);
225 }
227 {
228 const auto lit = next();
230 lit.lexeme,
231 lit.span);
232 }
234 {
235 const auto lit = next();
237 lit.lexeme,
238 lit.span,
239 true);
240 }
242 {
243 const auto lit = next();
245 lit.lexeme,
246 lit.span,
247 false);
248 }
250 return parse_grouping_expr();
251 default:
252 emit_error(tok.span, "expected expression", "PAR001");
253 if (not tok.is_eof())
254 (void) next();
255 return invalid_expr(tok.span);
256 }
257 }
258
261 {
262 const auto lparen
263 = expect(Compiler_Token_Kind::LParen, "expected '(' to start argument list", "PAR003");
264 auto *call = ast->make<Compiler_Call_Expr>(callee, lparen.span, Source_Span());
265
268 [&]()
269 {
270 call->arguments.append(parse_expression());
271 return true;
272 });
273
274 const auto rparen
275 = expect(Compiler_Token_Kind::RParen, "expected ')' after argument list", "PAR003");
276 call->rparen_span = rparen.span;
277 call->span = compiler_merge_spans(call->span, rparen.span);
278 return call;
279 }
280
283 {
284 auto *expr = parse_primary();
285 while (peek().kind == Compiler_Token_Kind::LParen)
286 expr = parse_call_suffix(expr);
287 return expr;
288 }
289
292 {
293 const auto tok = peek();
296 {
297 const auto op = next();
298 auto *operand = parse_unary();
299 return ast->make<Compiler_Unary_Expr>(op.kind, op.span, operand);
300 }
301
302 return parse_postfix();
303 }
304
307 {
308 auto *lhs = parse_unary();
309
310 while (true)
311 {
312 const auto op = peek();
313 const int precedence = compiler_binary_precedence(op.kind);
315 break;
316
317 (void) next();
319 ? precedence
320 : precedence + 1;
321 auto *rhs = parse_expression(rhs_min);
322 lhs = ast->make<Compiler_Binary_Expr>(lhs, op.kind, op.span, rhs);
323 }
324
325 return lhs;
326 }
327
330 {
331 const auto tok = peek();
333 {
334 emit_error(tok.span, "expected type name", "PAR007");
335 if (not tok.is_eof())
336 (void) next();
337 return invalid_type_expr(tok.span);
338 }
339
340 const auto name = next();
341 return ast->make<Compiler_Named_Type_Expr>(name.lexeme, name.span);
342 }
343
350 {
351 const auto lparen = expect(Compiler_Token_Kind::LParen, "expected '(' to start type", "PAR003");
352
353 auto *first = parse_type_expression();
354 if (peek().kind != Compiler_Token_Kind::Comma)
355 {
356 const auto rparen = expect(Compiler_Token_Kind::RParen, "expected ')' after type", "PAR003");
357 if (first != nullptr and rparen.span.is_valid())
358 first->span = compiler_merge_spans(lparen.span, rparen.span);
359 return first;
360 }
361
363 tuple->members.append(first);
364 (void) expect(Compiler_Token_Kind::Comma, "expected ',' in tuple type", "PAR003");
365 tuple->members.append(parse_type_expression());
368 [&]()
369 {
370 tuple->members.append(parse_type_expression());
371 return true;
372 });
373
374 const auto rparen
375 = expect(Compiler_Token_Kind::RParen, "expected ')' after tuple type", "PAR003");
376 tuple->rparen_span = rparen.span;
377 tuple->span = compiler_merge_spans(lparen.span, rparen.span);
378 return tuple;
379 }
380
383 {
384 const auto kw
385 = expect(Compiler_Token_Kind::Kw_Fn, "expected 'fn' to start function type", "PAR003");
386 const auto lparen
387 = expect(Compiler_Token_Kind::LParen, "expected '(' after 'fn' in type", "PAR003");
388
390 kw.span, lparen.span, Source_Span(), Source_Span(), nullptr);
391
394 [&]()
395 {
396 fn_type->parameters.append(parse_type_expression());
397 return true;
398 });
399
400 const auto rparen
401 = expect(Compiler_Token_Kind::RParen, "expected ')' after function type parameters", "PAR003");
402 fn_type->rparen_span = rparen.span;
403 const auto arrow
404 = expect(Compiler_Token_Kind::Arrow, "expected '->' after function type parameters", "PAR003");
405 fn_type->arrow_span = arrow.span;
406 fn_type->result = parse_type_expression();
407 fn_type->span
409 fn_type->result != nullptr ? fn_type->result->span : arrow.span);
410 return fn_type;
411 }
412
415 {
416 switch (const auto tok = peek(); tok.kind)
417 {
419 return parse_named_type();
423 return parse_function_type();
424 default:
425 emit_error(tok.span, "expected type expression", "PAR007");
426 if (not tok.is_eof())
427 (void) next();
428 return invalid_type_expr(tok.span);
429 }
430 }
431
437
440 {
441 const auto kw = next();
442 const auto path_tok = peek();
444 "expected string literal after 'import'",
445 "PAR003");
446 const auto semi = parse_statement_terminator(path.span.is_valid() ? path.span : kw.span);
448 return invalid_import_decl(
449 compiler_merge_spans(kw.span, semi.is_valid() ? semi : path_tok.span));
452 path.span,
453 semi);
454 }
455
458 {
459 const auto kw = next();
460 const auto name = expect_identifier("after 'type'");
461 const auto equal
462 = expect(Compiler_Token_Kind::Assign, "expected '=' in type alias declaration", "PAR003");
463 auto *target = parse_type_expression();
464 const auto semi = parse_statement_terminator(name.span);
465 return ast->make<Compiler_Type_Alias_Decl>(kw.span, name.lexeme, name.span, equal.span, target, semi);
466 }
467
470 {
471 const auto kw = next();
472 const auto name = expect_identifier("after 'struct'");
473 const auto lbrace
474 = expect(Compiler_Token_Kind::LBrace, "expected '{' after struct name", "PAR003");
475
476 auto *decl
477 = ast->make<Compiler_Struct_Decl>(kw.span, name.lexeme, name.span, lbrace.span, Source_Span());
478
479 while (true)
480 {
481 const auto tok = peek();
482 if (tok.is_eof() or tok.kind == Compiler_Token_Kind::RBrace)
483 break;
484
485 const auto field = expect_identifier("in struct field list");
486 const auto colon
487 = expect(Compiler_Token_Kind::Colon, "expected ':' after struct field name", "PAR003");
488 auto *annotation = parse_type_expression();
489 const auto semi = expect(Compiler_Token_Kind::Semicolon,
490 "expected ';' after struct field declaration",
491 "PAR003");
492 decl->fields.append({field.lexeme, field.span, colon.span, annotation, semi.span});
493 }
494
495 const auto rbrace
496 = expect(Compiler_Token_Kind::RBrace, "expected '}' after struct declaration", "PAR003");
497 decl->rbrace_span = rbrace.span;
498 decl->span = compiler_merge_spans(kw.span, rbrace.span);
499 return decl;
500 }
501
504 {
505 const auto kw = next();
506 const auto name = expect_identifier("after 'enum'");
507 const auto lbrace
508 = expect(Compiler_Token_Kind::LBrace, "expected '{' after enum name", "PAR003");
509
510 auto *decl
511 = ast->make<Compiler_Enum_Decl>(kw.span, name.lexeme, name.span, lbrace.span, Source_Span());
512
515 [&]()
516 {
517 const auto variant = expect_identifier("in enum variant list");
518 decl->variants.append({variant.lexeme, variant.span});
519 return true;
520 },
521 true);
522
523 const auto rbrace
524 = expect(Compiler_Token_Kind::RBrace, "expected '}' after enum declaration", "PAR003");
525 decl->rbrace_span = rbrace.span;
526 decl->span = compiler_merge_spans(kw.span, rbrace.span);
527 return decl;
528 }
529
532 {
533 const auto lbrace = expect(Compiler_Token_Kind::LBrace, "expected '{' to start block", "PAR003");
534 auto *block = ast->make<Compiler_Block_Stmt>(lbrace.span, Source_Span());
535
536 while (true)
537 {
538 const auto tok = peek();
539 if (tok.is_eof() or tok.kind == Compiler_Token_Kind::RBrace)
540 break;
541 block->statements.append(parse_statement());
542 }
543
544 const auto rbrace = expect(Compiler_Token_Kind::RBrace, "expected '}' to close block", "PAR003");
545 block->rbrace_span = rbrace.span;
546 block->span = compiler_merge_spans(block->lbrace_span, rbrace.span);
547 return block;
548 }
549
552 {
553 const auto kw = next();
554 const auto name = expect_identifier("after 'let'");
556 Compiler_Type_Expr *annotation = nullptr;
557
558 if (peek().kind == Compiler_Token_Kind::Colon)
559 {
560 colon = next().span;
561 annotation = parse_type_expression();
562 }
563
564 Compiler_Expr *init = nullptr;
567
568 const auto semi = parse_statement_terminator(name.span);
569 return ast->make<Compiler_Let_Stmt>(kw.span, name.lexeme, name.span, colon, annotation, init, semi);
570 }
571
574 {
575 const auto kw = next();
576 Compiler_Expr *value = nullptr;
578 and not peek().is_eof())
580
581 const auto semi = parse_statement_terminator(kw.span);
582 return ast->make<Compiler_Return_Stmt>(kw.span, value, semi);
583 }
584
587 {
588 const auto kw = next();
589 const auto semi = parse_statement_terminator(kw.span);
590 return ast->make<Compiler_Break_Stmt>(kw.span, semi);
591 }
592
595 {
596 const auto kw = next();
597 const auto semi = parse_statement_terminator(kw.span);
598 return ast->make<Compiler_Continue_Stmt>(kw.span, semi);
599 }
600
603 {
604 const auto if_kw = next();
605 auto *condition = parse_expression();
606 auto *then_branch = parse_statement();
607
609 Compiler_Stmt *else_branch = nullptr;
611 {
612 else_kw = next().span;
613 else_branch = parse_statement();
614 }
615
616 return ast->make<Compiler_If_Stmt>(if_kw.span, condition, then_branch, else_kw, else_branch);
617 }
618
621 {
622 const auto kw = next();
623 auto *condition = parse_expression();
624 auto *body = parse_statement();
625 return ast->make<Compiler_While_Stmt>(kw.span, condition, body);
626 }
627
630 {
631 auto *expr = parse_expression();
632 const auto semi = parse_statement_terminator(expr != nullptr ? expr->span : Source_Span());
633 return ast->make<Compiler_Expr_Stmt>(expr, semi);
634 }
635
636public:
648 const Source_Manager &sm,
649 const Source_File_Id file_id,
650 Diagnostic_Engine *dx = nullptr,
651 const Compiler_Parser_Options &opts = {})
652 : ast(&ctx), diagnostics(dx), lexer(sm, file_id, dx), tokens(lexer, dx), options(opts),
653 source_name(sm.file_name(file_id))
654 {}
655
667 {
668 auto *module = ast->make<Compiler_Module>();
669 module->source_name = source_name;
672
673 while (true)
674 {
675 const auto tok = peek();
676 if (tok.is_eof())
677 {
678 if (not first_span.is_valid())
679 module->span = tok.span;
680 else
681 module->span = compiler_merge_spans(first_span, last_span);
682 return module;
683 }
684
685 if (not first_span.is_valid())
686 first_span = tok.span;
687
689 {
690 auto *fn = parse_function();
691 module->functions.append(fn);
692 last_span = fn->span;
693 continue;
694 }
695
697 {
699 module->imports.append(decl);
700 last_span = decl != nullptr ? decl->span : tok.span;
701 continue;
702 }
703
705 {
707 module->type_declarations.append(decl);
708 last_span = decl != nullptr ? decl->span : tok.span;
709 continue;
710 }
711
713 {
715 module->type_declarations.append(decl);
716 last_span = decl != nullptr ? decl->span : tok.span;
717 continue;
718 }
719
721 {
723 module->type_declarations.append(decl);
724 last_span = decl != nullptr ? decl->span : tok.span;
725 continue;
726 }
727
729 emit_error(tok.span, "top-level statement is not allowed in this parser mode", "PAR004");
730
731 auto *stmt = parse_statement();
732 module->statements.append(stmt);
733 last_span = stmt->span;
734 }
735 }
736
746 {
747 const auto kw
748 = expect(Compiler_Token_Kind::Kw_Fn, "expected 'fn' to start function declaration", "PAR003");
749 const auto name = expect_identifier("after 'fn'");
750
751 (void) expect(Compiler_Token_Kind::LParen, "expected '(' after function name", "PAR003");
752
754 kw.span, name.lexeme, name.span, Source_Span(), nullptr, nullptr);
755
758 [&]()
759 {
760 const auto param = expect_identifier("in parameter list");
762 Compiler_Type_Expr *annotation = nullptr;
763 if (peek().kind == Compiler_Token_Kind::Colon)
764 {
765 colon = next().span;
766 annotation = parse_type_expression();
767 }
768 fn->parameters.append({param.lexeme, param.span, colon, annotation});
769 return true;
770 });
771
772 (void) expect(Compiler_Token_Kind::RParen, "expected ')' after parameter list", "PAR003");
773
775 {
776 fn->arrow_span = next().span;
777 fn->return_annotation = parse_type_expression();
778 }
779
780 fn->body = parse_block_statement();
781 fn->span = compiler_merge_spans(kw.span, fn->body != nullptr ? fn->body->span : name.span);
782 return fn;
783 }
784
794 {
795 const auto tok = peek();
796 switch (tok.kind)
797 {
799 return parse_block_statement();
801 return parse_let_statement();
803 return parse_return_statement();
805 return parse_if_statement();
807 return parse_while_statement();
809 return parse_break_statement();
812 default:
815
816 emit_error(tok.span, "expected statement", "PAR006");
817 if (not tok.is_eof())
818 (void) next();
820 return invalid_stmt(tok.span);
821 }
822 }
823};
824
825} // namespace Aleph
826
827#endif // COMPILER_PARSER_H
Arena-backed AST node model for the compiler-support MVP.
Reusable token-stream helpers for recursive-descent frontends.
size_t size_t int32_t value
Definition ca-c-api.h:116
Arena-backed ownership context for AST nodes.
T * make(Args &&...args)
Allocates and constructs an AST node of type T.
Token generator for a single source file.
Lightweight token stream facade for recursive-descent parsers.
bool parse_separated_list(const Compiler_Token_Kind separator, const Compiler_Token_Kind terminator, Parse_Item &&parse_item, const bool allow_trailing_separator=false)
Parses one separated list until a terminator token is reached.
bool match(const Compiler_Token_Kind kind)
Consumes the next token if it matches kind.
void synchronize_statement()
Skips tokens until a statement boundary suitable for recovery.
Compiler_Token peek()
Returns the next token without consuming it.
Compiler_Token expect(const Compiler_Token_Kind kind, const std::string &message, const std::string &code, const std::string &note="", const std::string &help="")
Consumes a token of kind kind or emits one diagnostic error.
Compiler_Token expect_identifier(const std::string_view context, const std::string &code="PAR002")
Consumes one identifier token or emits one diagnostic error.
Compiler_Token next()
Consumes and returns the next token.
Recursive-descent parser that produces an AST in Compiler_Ast_Context.
Compiler_Expr * parse_expression(const int min_precedence=1)
Parses binary expressions using precedence-climbing.
Compiler_Grouping_Expr * parse_grouping_expr()
Parses a parenthesized expression: ( expression ).
Compiler_Parser_Options options
Parser behavior configuration.
Compiler_Ast_Context * ast
AST owner.
Compiler_Module * parse_module()
Parses a full module until EOF.
Compiler_Invalid_Expr * invalid_expr(const Source_Span &span={}) const
Creates an invalid expression node in the current arena.
Compiler_Invalid_Type_Decl * invalid_type_decl(const Source_Span &span={}) const
Creates an invalid type-declaration node in the current arena.
Compiler_Import_Decl * parse_import_declaration()
Parses one top-level import declaration: import string ;.
Compiler_Type_Decl * parse_type_alias_declaration()
Parses one top-level type alias: type ident = type ;.
Compiler_Type_Expr * parse_type_primary()
Parses one primary type-expression form.
Compiler_Invalid_Import_Decl * invalid_import_decl(const Source_Span &span={}) const
Creates an invalid import-declaration node in the current arena.
Compiler_Token peek()
Peeks at the next token without consuming it.
void emit_error(const Source_Span &span, const std::string &message, const std::string &code, const std::string &note="", const std::string &help="") const
Internal helper to report a diagnostic error.
Compiler_Type_Expr * parse_function_type()
Parses a function type such as fn(Int) -> Bool.
Compiler_Lexer lexer
Token source.
bool match(const Compiler_Token_Kind kind)
Consumes the next token if it matches kind.
Compiler_Expr * parse_primary()
Parses primary expressions: literals, identifiers, and groupings.
Compiler_Stmt * parse_continue_statement()
Parses a continue statement: continue;.
Compiler_Expr * parse_call_suffix(Compiler_Expr *callee)
Parses function call argument list suffix: ( args? ).
Compiler_Stmt * parse_let_statement()
Parses a variable declaration: let ident (: type)? (= expr)? ;.
Compiler_Token expect(const Compiler_Token_Kind kind, const std::string &message, const std::string &code)
Consumes a token of kind kind or emits an error.
Compiler_Type_Expr * parse_named_type()
Parses a named type such as Int or T.
Compiler_Type_Expr * parse_type_expression()
Parses a type expression used by explicit annotations.
Compiler_Expr * parse_unary()
Parses prefix unary expressions: !, -, +, ~.
Compiler_Token expect_identifier(const std::string &context, const std::string &code="PAR002")
Consumes an identifier token or emits an error.
Compiler_Stmt * parse_if_statement()
Parses an if statement: if expr stmt (else stmt)?.
Compiler_Function_Decl * parse_function()
Parses a top-level function declaration.
Compiler_Stmt * parse_while_statement()
Parses a while loop: while expr stmt.
Compiler_Stmt * parse_return_statement()
Parses a return statement: return expr? ;.
Compiler_Stmt * parse_statement()
Parses a single statement.
Diagnostic_Engine * diagnostics
diagnostic sink.
Compiler_Type_Expr * parse_parenthesized_type()
Parses parenthesized tuple-type syntax.
Compiler_Type_Decl * parse_struct_declaration()
Parses one top-level struct declaration.
Compiler_Stmt * parse_expression_statement()
Parses an expression statement: expr ;.
Compiler_Stmt * parse_break_statement()
Parses a break statement: break;.
Compiler_Parser_Stream tokens
Reusable parser-oriented token facade.
Source_Span parse_statement_terminator(const Source_Span &anchor)
Ensures a statement is terminated by a semicolon or reports an error.
Compiler_Parser(Compiler_Ast_Context &ctx, const Source_Manager &sm, const Source_File_Id file_id, Diagnostic_Engine *dx=nullptr, const Compiler_Parser_Options &opts={})
Constructs a parser for one registered source file.
Compiler_Expr * parse_postfix()
Parses postfix expressions such as calls.
Compiler_Block_Stmt * parse_block_statement()
Parses a block statement: { statements* }.
void synchronize_statement()
Error recovery helper: skips tokens until a statement boundary.
std::string source_name
User-facing source name being parsed.
Compiler_Type_Decl * parse_enum_declaration()
Parses one top-level unit-variant enum declaration.
Compiler_Invalid_Stmt * invalid_stmt(const Source_Span &span={}) const
Creates an invalid statement node in the current arena.
Compiler_Token next()
Consumes and returns the next token.
Compiler_Invalid_Type_Expr * invalid_type_expr(const Source_Span &span={}) const
Creates an invalid type-expression node in the current arena.
Diagnostic_Builder & code(const std::string &value)
Sets the stable diagnostic code.
size_t emit() const noexcept
Finalizes the builder and returns the diagnostic index.
Diagnostic_Builder & help(const std::string &msg)
Appends a help line.
Diagnostic_Builder & note(const std::string &msg)
Appends a note line.
Diagnostic accumulator and renderer.
Diagnostic_Builder error(const Source_Span &span, const std::string &msg)
Starts an error diagnostic.
Stores source files and resolves offsets into human-readable data.
Definition ah-source.H:184
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
bool compiler_is_expression_start(const Compiler_Token_Kind kind) noexcept
Returns whether a token kind can start an expression in the MVP grammar.
@ Integer_Literal
Numeric integer constant.
@ Char_Literal
Character constant.
@ String_Literal
String constant.
@ Bool_Literal
Boolean constant (true/false).
Source_Span compiler_merge_spans(const Source_Span &lhs, const Source_Span &rhs) noexcept
Merges two spans from the same source file.
void message(const char *file, int line, const char *format,...)
Print an informational message with file and line info.
Definition ahDefs.C:95
int compiler_binary_precedence(Compiler_Token_Kind kind) noexcept
Returns binary precedence for an operator.
and
Check uniqueness with explicit hash + equality functors.
std::string code(Node *root)
Compute a string with the Lukasiewicz`s word of a tree.
@ Right
Right-associative: a = (b = c).
bool equal(Itor1 beg, const Itor1 &end, Itor2 cmpBeg, BinaryPredicate op=BinaryPredicate())
Test if two ranges are equal.
Definition ahAlgo.H:482
Compiler_Token_Kind
Token kinds supported by the compiler MVP.
@ Identifier
Named identifier (e.g., variable or function name).
@ Integer_Literal
Integer constant.
@ Char_Literal
Single character constant.
@ String_Literal
String constant (with escape sequences).
bool compiler_is_statement_start(const Compiler_Token_Kind kind) noexcept
Returns whether a token kind can start a statement in the MVP grammar.
std::string compiler_unquote_string_token(const Compiler_Token &token)
Removes surrounding double quotes from one string-literal token.
size_t Source_File_Id
Definition ah-source.H:61
static std::atomic< bool > init
Definition hash-fct.C:54
Compiler_Associativity compiler_binary_associativity(Compiler_Token_Kind kind) noexcept
Returns binary associativity for an operator.
Source_Span span
Source region covered by this node.
Node representing an infix binary operation.
Node representing a braced sequence of statements.
Node representing a loop break.
Node representing a function or method call.
Node representing a loop continuation.
Nominal top-level enum declaration with unit variants.
Node representing an expression evaluated as a statement.
Abstract base class for expression nodes.
Node representing a top-level function declaration.
Function type syntax such as fn(Int, T) -> Bool.
Node representing an expression explicitly wrapped in parentheses.
Node representing a named identifier reference.
Node representing a conditional branch.
Abstract base class for top-level import declarations.
Placeholder node for expressions that failed to parse.
Placeholder node for malformed import declarations.
Placeholder node for statements that failed to parse.
Placeholder node for malformed type declarations.
Placeholder node for type syntax that failed to parse.
Node representing a local variable binding.
Node representing a literal value.
Node representing a complete translation unit or module.
Named type syntax such as Int, Bool, or T.
Parser configuration knobs for the MVP grammar.
bool allow_top_level_statements
If false, only top-level declarations are accepted.
Node representing a return from the current function.
Source_Span span
Aggregate source span.
Definition SSA.H:166
Top-level import declaration naming one other source unit.
Abstract base class for statement nodes.
Nominal top-level struct declaration.
Lexical token representation with its value and location.
Source_Span span
Precise location in the source code.
Compiler_Token_Kind kind
Logical category (e.g., Kw_If).
Tuple type syntax such as (Int, Bool).
DynArray< Compiler_Type_Expr * > members
Tuple element types in source order.
Transparent top-level type alias declaration.
Abstract base class for top-level type declarations.
Abstract base class for parsed type-annotation syntax.
Node representing a prefix unary operation.
Node representing a while-loop.
Half-open byte range inside a source file.
Definition ah-source.H:100