From 2b0228cec24e49369634cb8239a1939f0fad7e2e Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Tue, 9 Jul 2024 23:04:47 +0200 Subject: Disallow keywords as identifier names --- README | 8 ++++++-- make.c | 27 ++++++++++++++++++++++++++- src/keywords.gperf | 40 ++++++++++++++++++++++++++++++++++++++++ src/parser.c | 6 ++++++ 4 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 src/keywords.gperf diff --git a/README b/README index f30fdb1..624df36 100644 --- a/README +++ b/README @@ -19,11 +19,15 @@ Building the Oryx compiler is rather trivial. The steps are as follows: the version of LLVM being utilized is 17.0.6. The compiler may work with other versions, but it isn’t guaranteed. -2. Clone the compiler repository. +2. Install Gperf. It should be available in your systems package + manager, and if not then you can easily find instructions online to + build from source. + +3. Clone the compiler repository. $ git clone https://github.com/Mango0x45/oryx.git -3. Bootstrap and run the build script. +4. Bootstrap and run the build script. $ cc -o make make.c $ ./make # See below for more details diff --git a/make.c b/make.c index 5d9212b..4692189 100644 --- a/make.c +++ b/make.c @@ -61,7 +61,7 @@ static void mkgmp(int); static bool tagvalid(const char *); static void chk_cpu_flags(void); static int globerr(const char *, int); -static tjob cc, cc_test; +static tjob cc, cc_test, gperf; static void usage(void) @@ -158,7 +158,14 @@ main(int argc, char **argv) glob_t g; + /* GNU Perf files */ + assert(glob("src/*.gperf", 0, globerr, &g) == 0); + for (size_t i = 0; i < g.gl_pathc; i++) + tpenq(&tp, gperf, g.gl_pathv[i], NULL); + tpwait(&tp); + /* C files */ + globfree(&g); assert(glob("src/*.c", 0, globerr, &g) == 0); for (size_t i = 0; i < g.gl_pathc; i++) tpenq(&tp, cc, g.gl_pathv[i], NULL); @@ -260,6 +267,24 @@ out: free(dst); } +void +gperf(void *arg) +{ + struct strs cmd = {0}; + char *dst = swpext(arg, "gen.c"), *src = arg; + + if (!fflag && fmdnewer(dst, src)) + goto out; + + strspushl(&cmd, "gperf", src, "--output-file", dst); + + cmdput(cmd); + cmdexec(cmd); + strsfree(&cmd); +out: + free(dst); +} + void ld(void) { diff --git a/src/keywords.gperf b/src/keywords.gperf new file mode 100644 index 0000000..7d81705 --- /dev/null +++ b/src/keywords.gperf @@ -0,0 +1,40 @@ +%compare-lengths +%compare-strncmp +%includes +%readonly-tables + +%{ +#include + +#include "strview.h" + +static const char *in_word_set(const char *, size_t); +%} + +%% +pub +static +bool +i8 +i16 +i32 +i64 +i128 +int +u8 +u16 +u32 +u64 +u128 +uint +f16 +f32 +f64 +f128 +rune +%% +bool +iskeyword(strview_t sv) +{ + return in_word_set(sv.p, sv.len) != NULL; +} diff --git a/src/parser.c b/src/parser.c index defe47d..9e748b5 100644 --- a/src/parser.c +++ b/src/parser.c @@ -47,6 +47,9 @@ static idx_t astalloc(ast_t *ast) static void astresz(ast_t *ast) __attribute__((nonnull)); +/* Generated by Gperf */ +bool iskeyword(strview_t); + /* TODO: Make thread-local? */ static size_t toksidx; @@ -177,6 +180,9 @@ parsedecl(ast_t *ast, aux_t *aux, lexemes_t toks, bool toplvl) ast->lexemes[i] = toksidx; } + if (iskeyword(toks.strs[toksidx])) + err("parser: Cannot use reserved word as identifier"); + if (toks.kinds[toksidx++] != LEXIDENT) err("parser: Expected identifier"); if (toks.kinds[toksidx++] != LEXCOLON) -- cgit v1.2.3