diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.c | 8 | ||||
| -rw-r--r-- | src/sema/sema.c | 73 | ||||
| -rw-r--r-- | src/sema/sema.h | 7 |
3 files changed, 88 insertions, 0 deletions
@@ -2,6 +2,7 @@ #include "io/file.h" #include "cli/args.h" +#include "sema/sema.h" #include "lexer/lexer.h" #include "codegen/nasm.h" #include "parser/parser.h" @@ -36,6 +37,13 @@ int main(int argc, char** argv) return 1; } + if (!analyze_program(&program)) + { + free_program(&program); + free_file(&source); + return 1; + } + FILE* out = stdout; if (args.output_path != NULL) { 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); |
