summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuinn Stephens <quinn@osmora.org>2024-11-07 16:59:19 -0500
committerQuinn Stephens <quinn@osmora.org>2024-11-07 16:59:19 -0500
commit6ab9c3732793b6fd40e6388cf1b08756194c0ea6 (patch)
treee7ae86e1bad944192f0b6fd130cb7d84afa4f180
parent063c40584ae78a396b558a5e2a08e3d871450c0b (diff)
[compiler] Parse return statementsmain
Laid groundwork for statements and AST trees. Currently return values are not supported, expression parsing must be implemented first. Also stopped dumping parsed type definitions. Signed-off-by: Quinn Stephens <quinn@osmora.org>
-rw-r--r--Makefile2
-rw-r--r--compiler/lexer/keywords.c1
-rw-r--r--compiler/main.c97
-rw-r--r--compiler/parser/proc.c22
-rw-r--r--compiler/parser/stmt.c62
-rw-r--r--include/lexer/token.h1
-rw-r--r--include/list.h7
-rw-r--r--include/parser/ast.h38
-rw-r--r--include/parser/proc.h3
-rw-r--r--include/parser/stmt.h16
-rw-r--r--test.q5
11 files changed, 168 insertions, 86 deletions
diff --git a/Makefile b/Makefile
index 5dfb0a2..9363239 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ CC = clang
LD = ld.ldd
EXENAME = quarkc
-OFILES = $(addprefix compiler/,debug.o hash.o hashmap.o lexer/char_info.o lexer/keywords.o lexer/lexer.o parser/type.o parser/proc.o parser/parser.o main.o)
+OFILES = $(addprefix compiler/,debug.o hash.o hashmap.o lexer/char_info.o lexer/keywords.o lexer/lexer.o parser/type.o parser/stmt.o parser/proc.o parser/parser.o main.o)
CFLAGS = -Wall -Wextra -Iinclude
LDFLAGS =
diff --git a/compiler/lexer/keywords.c b/compiler/lexer/keywords.c
index 88c2e67..dbae881 100644
--- a/compiler/lexer/keywords.c
+++ b/compiler/lexer/keywords.c
@@ -69,6 +69,7 @@ keywords_init(void)
add_keyword("type", TK_TYPE);
add_keyword("enum", TK_ENUM);
add_keyword("struct", TK_STRUCT);
+ add_keyword("ret", TK_RET);
initialized = true;
}
diff --git a/compiler/main.c b/compiler/main.c
index e614be6..aa3bcdc 100644
--- a/compiler/main.c
+++ b/compiler/main.c
@@ -183,69 +183,31 @@ print_ptrs(int n_ptrs)
}
static void
-print_alias(struct type *typ)
+print_ret(struct ast_node *node)
{
- printf("alias (%lu bytes, %d pointer(s));\n", typ->size, typ->n_ptrs);
-}
-
-static void
-print_enum(struct type *typ)
-{
- struct enum_member *mem;
+ (void)node;
- printf("enum {\n");
-
- for (size_t r = 0; r < typ->members.n_rows; r++) {
- mem = (struct enum_member*)typ->members.rows[r].head;
- while (mem != (struct enum_member*)&typ->members.rows[r]) {
- printf(" %.*s,\n", (int)mem->name_len, mem->name);
-
- mem = (struct enum_member*)mem->hashmap_entry.list_entry.next;
- }
- }
-
- printf("}\n");
+ /* TODO: Print return value */
+ printf(" ret;\n");
}
static void
-print_struct(struct type *typ)
+print_stmt_block(struct ast_node *parent)
{
- struct struct_member *mem;
-
- printf("struct (%lu bytes) {\n", typ->size);
-
- for (size_t r = 0; r < typ->members.n_rows; r++) {
- mem = (struct struct_member*)typ->members.rows[r].head;
- while (mem != (struct struct_member*)&typ->members.rows[r]) {
- printf(" %.*s ", (int)mem->typ->name_len, mem->typ->name);
- print_ptrs(mem->n_ptrs);
- printf("%.*s;\n", (int)mem->name_len, mem->name);
-
- mem = (struct struct_member*)mem->hashmap_entry.list_entry.next;
+ struct ast_node *node;
+
+ node = (struct ast_node*)parent->children.head;
+ while (node != (struct ast_node*)&parent->children) {
+ switch (node->kind) {
+ case NK_RETURN:
+ print_ret(node);
+ break;
+ default:
+ printf(" /* Unknown */\n");
+ break;
}
- }
-
- printf("}\n");
-}
-static void
-print_type(struct type *typ)
-{
- printf("type %.*s: ", (int)typ->name_len, typ->name);
-
- switch (typ->kind) {
- case TYK_ALIAS:
- print_alias(typ);
- break;
- case TYK_ENUM:
- print_enum(typ);
- break;
- case TYK_STRUCT:
- print_struct(typ);
- break;
- default:
- printf("unknown;\n");
- break;
+ node = (struct ast_node*)node->list_entry.next;
}
}
@@ -281,26 +243,14 @@ print_proc(struct procedure *proc)
print_ptrs(proc->ret_n_ptrs);
}
- printf(";\n");
-}
-
-static void
-dump_types(struct hashmap *map)
-{
- struct type *typ, *next;
-
- for (size_t r = 0; r < map->n_rows; r++) {
- typ = (struct type*)map->rows[r].head;
- while (typ != (struct type*)&map->rows[r]) {
- print_type(typ);
-
- next = (struct type*)typ->hashmap_entry.list_entry.next;
- free(typ);
- typ = next;
- }
+ if (list_is_empty(&proc->node->children)) {
+ printf(";\n");
+ return;
}
- free(map->rows);
+ printf(" {\n");
+ print_stmt_block(proc->node);
+ printf("}\n");
}
static void
@@ -362,7 +312,6 @@ main(int argc, char **argv)
parser_init(&parser, input);
parser_parse(&parser);
- dump_types(parser.types);
dump_procs(parser.procs);
free(input);
diff --git a/compiler/parser/proc.c b/compiler/parser/proc.c
index bbbdad1..b32f5e9 100644
--- a/compiler/parser/proc.c
+++ b/compiler/parser/proc.c
@@ -7,6 +7,7 @@
#include <stdbool.h>
#include "debug.h"
#include "parser/proc.h"
+#include "parser/stmt.h"
#include "parser/type.h"
#include "parser.h"
@@ -119,26 +120,29 @@ parse_proc(struct parser *ctx)
}
}
- /* Add procedure to parser's registry */
- hashmap_add(ctx->procs, &proc->hashmap_entry);
-
/* We are finished now if this is just a declaration */
if (ctx->tok.kind == TK_SEMICOLON) {
+ proc->node = NULL;
+
+ /* Add procedure to parser's registry */
+ hashmap_add(ctx->procs, &proc->hashmap_entry);
+
next_token(ctx);
return;
}
if (ctx->tok.kind != TK_LBRACE) {
+ proc->node = NULL;
tok_error(&ctx->tok, "Expected \";\" or \"{\"\n");
return;
}
- /* TODO: Parse body/code */
+ /* Allocate AST root node for body */
+ proc->node = ast_new_node(NK_PROCEDURE);
- if (next_token(ctx)->kind != TK_RBRACE) {
- tok_error(&ctx->tok, "Expected \"}\" after procedure body\n");
- return;
- }
+ /* Parse procedure body (code) */
+ parse_stmt_block(ctx, proc->node, proc);
- next_token(ctx);
+ /* Add procedure to parser's registry */
+ hashmap_add(ctx->procs, &proc->hashmap_entry);
}
diff --git a/compiler/parser/stmt.c b/compiler/parser/stmt.c
new file mode 100644
index 0000000..6fe3d6d
--- /dev/null
+++ b/compiler/parser/stmt.c
@@ -0,0 +1,62 @@
+/*
+ * Statement parser.
+ * Copyright (c) 2023-2024, Quinn Stephens and the OSMORA team.
+ * Provided under the BSD 3-Clause license.
+ */
+
+#include <stdbool.h>
+#include "debug.h"
+#include "parser/ast.h"
+#include "parser/stmt.h"
+#include "parser/proc.h"
+#include "parser.h"
+
+static bool
+parse_ret(struct parser *ctx, struct ast_node *parent, struct procedure *proc)
+{
+ struct ast_node *node;
+
+ (void)proc;
+
+ debug("Parsing return statement...\n");
+
+ /* TODO: Parse return value */
+ next_token(ctx);
+
+ if (ctx->tok.kind != TK_SEMICOLON) {
+ tok_error(&ctx->tok, "Expected \";\"\n");
+ return false;
+ }
+ next_token(ctx);
+
+ node = ast_new_node(NK_RETURN);
+ ast_append_child(parent, node);
+
+ return true;
+}
+
+void
+parse_stmt_block(struct parser *ctx, struct ast_node *parent, struct procedure *proc)
+{
+ bool success;
+
+ debug("Parsing statement block...\n");
+
+ next_token(ctx);
+ while (ctx->tok.kind != TK_RBRACE) {
+ switch (ctx->tok.kind) {
+ case TK_RET:
+ success = parse_ret(ctx, parent, proc);
+ break;
+ default:
+ tok_error(&ctx->tok, "Expected statement\n");
+ success = false;
+ break;
+ }
+
+ if (!success) {
+ return;
+ }
+ }
+ next_token(ctx);
+}
diff --git a/include/lexer/token.h b/include/lexer/token.h
index 2ba5408..cc04c95 100644
--- a/include/lexer/token.h
+++ b/include/lexer/token.h
@@ -25,6 +25,7 @@ typedef enum {
TK_TYPE,
TK_ENUM,
TK_STRUCT,
+ TK_RET,
/*
* Operators.
diff --git a/include/list.h b/include/list.h
index 0364f7c..69d0c33 100644
--- a/include/list.h
+++ b/include/list.h
@@ -7,6 +7,7 @@
#ifndef _LIST_H
#define _LIST_H
+#include <stdbool.h>
#include <stddef.h>
struct list_entry {
@@ -20,6 +21,12 @@ struct list {
size_t length;
};
+static inline bool
+list_is_empty(struct list *list)
+{
+ return list->head == (struct list_entry*)list;
+}
+
static inline void
list_remove(struct list_entry *entry)
{
diff --git a/include/parser/ast.h b/include/parser/ast.h
index 03be1bd..9463511 100644
--- a/include/parser/ast.h
+++ b/include/parser/ast.h
@@ -7,14 +7,50 @@
#ifndef _PARSER_AST_H
#define _PARSER_AST_H
+#include <stdlib.h>
+#include "list.h"
+
enum ast_node_kind {
NK_UNKNOWN,
- NK_
+ NK_PROCEDURE,
+ NK_RETURN
};
struct ast_node {
+ struct list_entry list_entry;
+
enum ast_node_kind kind;
+
+ struct ast_node *parent;
+ struct list children;
};
+static inline void
+ast_append_child(struct ast_node *parent, struct ast_node *child)
+{
+ child->parent = parent;
+ list_append(&parent->children, &child->list_entry);
+}
+
+static inline void
+ast_remove_child(struct ast_node *child)
+{
+ list_remove(&child->list_entry);
+ child->parent->children.length--;
+}
+
+static inline struct ast_node *
+ast_new_node(enum ast_node_kind kind)
+{
+ struct ast_node *node;
+
+ node = malloc(sizeof(struct ast_node));
+ node->kind = kind;
+ node->parent = NULL;
+ list_init(&node->children);
+
+ return node;
+}
+
#endif /* !_PARSER_AST_H */
diff --git a/include/parser/proc.h b/include/parser/proc.h
index 0cc8471..f74fee6 100644
--- a/include/parser/proc.h
+++ b/include/parser/proc.h
@@ -9,6 +9,7 @@
#include "list.h"
#include "hashmap.h"
+#include "parser/ast.h"
#include "parser/var.h"
struct parameter {
@@ -27,6 +28,8 @@ struct procedure {
struct type *ret_typ;
int ret_n_ptrs;
+
+ struct ast_node *node;
};
void parse_proc(struct parser *ctx);
diff --git a/include/parser/stmt.h b/include/parser/stmt.h
new file mode 100644
index 0000000..caf022c
--- /dev/null
+++ b/include/parser/stmt.h
@@ -0,0 +1,16 @@
+/*
+ * Statement parser.
+ * Copyright (c) 2023-2024, Quinn Stephens and the OSMORA team.
+ * Provided under the BSD 3-Clause license.
+ */
+
+#ifndef _PARSER_STMT_H
+#define _PARSER_STMT_H
+
+#include "parser/ast.h"
+#include "parser/proc.h"
+#include "parser.h"
+
+void parse_stmt_block(struct parser *ctx, struct ast_node *parent, struct procedure *proc);
+
+#endif /* !_PARSER_STMT_H */
diff --git a/test.q b/test.q
index 0769752..4b9a944 100644
--- a/test.q
+++ b/test.q
@@ -48,4 +48,7 @@ type EfiSystemTable: struct {
EfiConfigurationTable *configurationTable;
}
-proc efiEntry(EfiHandle imageHandle, EfiSystemTable *systemTable) -> EfiStatus;
+proc efiEntry(EfiHandle imgHandle, EfiSystemTable *sysTable) -> EfiStatus
+{
+ ret;
+}