diff options
author | Thomas Voss <mail@thomasvoss.com> | 2024-07-09 23:04:47 +0200 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2024-07-09 23:04:54 +0200 |
commit | 2b0228cec24e49369634cb8239a1939f0fad7e2e (patch) | |
tree | 18d6f926ae47da1485e651896bfc0a3c06d7a4c0 | |
parent | 2b06086473b466fe989ce8629f941b9539ba1095 (diff) |
Disallow keywords as identifier names
-rw-r--r-- | README | 8 | ||||
-rw-r--r-- | make.c | 27 | ||||
-rw-r--r-- | src/keywords.gperf | 40 | ||||
-rw-r--r-- | src/parser.c | 6 |
4 files changed, 78 insertions, 3 deletions
@@ -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 @@ -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); @@ -261,6 +268,24 @@ out: } 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) { glob_t g; 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 <stdbool.h> + +#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) |