aboutsummaryrefslogtreecommitdiff
path: root/src/sema
diff options
context:
space:
mode:
Diffstat (limited to 'src/sema')
-rw-r--r--src/sema/sema.c73
-rw-r--r--src/sema/sema.h7
2 files changed, 80 insertions, 0 deletions
diff --git a/src/sema/sema.c b/src/sema/sema.c
new file mode 100644
index 0000000..99ec4f1
--- /dev/null
+++ b/src/sema/sema.c
@@ -0,0 +1,73 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sema/sema.h"
+
+static bool names_equal(struct Token a, struct Token b)
+{
+ return a.length == b.length && memcmp(a.start, b.start, a.length) == 0;
+}
+
+static bool check_duplicate_names(struct Program* program)
+{
+ size_t count = program->const_count + program->data_count + program->proc_count;
+ if (count == 0)
+ return true;
+
+ struct Token* names = malloc(count * sizeof(struct Token));
+ size_t n = 0;
+ for (size_t i = 0; i < program->const_count; i += 1)
+ {
+ names[n] = program->consts[i].name;
+ n += 1;
+ }
+ for (size_t i = 0; i < program->data_count; i += 1)
+ {
+ names[n] = program->data_decls[i].name;
+ n += 1;
+ }
+ for (size_t i = 0; i < program->proc_count; i += 1)
+ {
+ names[n] = program->procs[i].name;
+ n += 1;
+ }
+
+ bool ok = true;
+ for (size_t i = 0; i < count; i += 1)
+ for (size_t j = 0; j < i; j += 1)
+ if (names_equal(names[i], names[j]))
+ {
+ fprintf(stderr, "error: line %u: '%.*s' is already defined\n",
+ names[i].line, (int)names[i].length, names[i].start);
+ ok = false;
+ }
+
+ free(names);
+ return ok;
+}
+
+static bool check_entry_point(struct Program* program)
+{
+ for (size_t i = 0; i < program->proc_count; i += 1)
+ {
+ struct Token name = program->procs[i].name;
+ if (name.length == 4 && memcmp(name.start, "main", 4) == 0)
+ return true;
+ }
+
+ fprintf(stderr, "error: no 'main' procedure defined\n");
+ return false;
+}
+
+bool analyze_program(struct Program* program)
+{
+ bool ok = true;
+
+ if (!check_duplicate_names(program))
+ ok = false;
+ if (!check_entry_point(program))
+ ok = false;
+
+ return ok;
+}
diff --git a/src/sema/sema.h b/src/sema/sema.h
new file mode 100644
index 0000000..e015f41
--- /dev/null
+++ b/src/sema/sema.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include <stdbool.h>
+
+#include "parser/ast.h"
+
+bool analyze_program(struct Program* program);