aboutsummaryrefslogtreecommitdiff
path: root/parse.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-04-12 13:09:31 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-04-12 13:09:31 -0400
commit6c01eef851439549018267fdc439e4884af0c624 (patch)
tree0599dd071b8a5effb67e6a87ed1c34777eb8d8c7 /parse.c
parent17cb6ffd88c4464c513b045f4b06c4e6e46e8f22 (diff)
Introducing the main() function
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c43
1 files changed, 39 insertions, 4 deletions
diff --git a/parse.c b/parse.c
index 8b2e9840..4d283918 100644
--- a/parse.c
+++ b/parse.c
@@ -96,6 +96,7 @@ static PARSER(parse_doctest);
static PARSER(parse_use);
static PARSER(parse_linker);
static PARSER(parse_namespace);
+static PARSER(parse_file_body);
static type_ast_t *parse_type(parse_ctx_t *ctx, const char *pos);
@@ -509,7 +510,7 @@ type_ast_t *parse_pointer_type(parse_ctx_t *ctx, const char *pos) {
bool is_readonly = match(&pos, "%");
spaces(&pos);
type_ast_t *type = expect(ctx, start, &pos, parse_type,
- "I couldn't parse a pointer type after this point");
+ "I couldn't parse a pointer type after this point");
return NewTypeAST(ctx->file, start, pos, PointerTypeAST, .pointed=type, .is_optional=optional, .is_stack=is_stack, .is_readonly=is_readonly);
}
@@ -1548,7 +1549,8 @@ PARSER(parse_namespace) {
||(stmt=optional(ctx, &pos, parse_func_def))
||(stmt=optional(ctx, &pos, parse_use))
||(stmt=optional(ctx, &pos, parse_linker))
- ||(stmt=optional(ctx, &pos, parse_statement)))
+ ||(stmt=optional(ctx, &pos, parse_extern))
+ ||(stmt=optional(ctx, &pos, parse_declaration)))
{
statements = new(ast_list_t, .ast=stmt, .next=statements);
pos = stmt->end;
@@ -1559,7 +1561,7 @@ PARSER(parse_namespace) {
// }
} else {
if (get_indent(ctx->file, next) > indent && next < strchrnul(next, '\n'))
- parser_err(ctx, next, strchrnul(next, '\n'), "I couldn't parse this namespace statement");
+ parser_err(ctx, next, strchrnul(next, '\n'), "I couldn't parse this namespace declaration");
break;
}
}
@@ -1567,6 +1569,39 @@ PARSER(parse_namespace) {
return NewAST(ctx->file, start, pos, Block, .statements=statements);
}
+PARSER(parse_file_body) {
+ const char *start = pos;
+ whitespace(&pos);
+ ast_list_t *statements = NULL;
+ for (;;) {
+ const char *next = pos;
+ whitespace(&next);
+ if (get_indent(ctx->file, next) != 0) break;
+ ast_t *stmt;
+ if ((stmt=optional(ctx, &pos, parse_struct_def))
+ ||(stmt=optional(ctx, &pos, parse_enum_def))
+ ||(stmt=optional(ctx, &pos, parse_lang_def))
+ ||(stmt=optional(ctx, &pos, parse_func_def))
+ ||(stmt=optional(ctx, &pos, parse_use))
+ ||(stmt=optional(ctx, &pos, parse_linker))
+ ||(stmt=optional(ctx, &pos, parse_extern))
+ ||(stmt=optional(ctx, &pos, parse_declaration)))
+ {
+ statements = new(ast_list_t, .ast=stmt, .next=statements);
+ pos = stmt->end;
+ whitespace(&pos); // TODO: check for newline
+ } else {
+ break;
+ }
+ }
+ whitespace(&pos);
+ if (pos < ctx->file->text + ctx->file->len && *pos != '\0') {
+ parser_err(ctx, pos, strchrnul(pos, '\n'), "I expect all top-level statements to be declarations of some kind");
+ }
+ REVERSE_LIST(statements);
+ return NewAST(ctx->file, start, pos, Block, .statements=statements);
+}
+
PARSER(parse_struct_def) {
// struct Foo(...) \n body
const char *start = pos;
@@ -1902,7 +1937,7 @@ ast_t *parse_file(file_t *file, jmp_buf *on_err) {
some_not(&pos, "\r\n");
whitespace(&pos);
- ast_t *ast = parse_namespace(&ctx, pos);
+ ast_t *ast = parse_file_body(&ctx, pos);
pos = ast->end;
whitespace(&pos);
if (pos < file->text + file->len && *pos != '\0') {