aboutsummaryrefslogtreecommitdiff
path: root/bootstrap
diff options
context:
space:
mode:
Diffstat (limited to 'bootstrap')
-rw-r--r--bootstrap/Makefile13
-rw-r--r--bootstrap/token.c120
2 files changed, 73 insertions, 60 deletions
diff --git a/bootstrap/Makefile b/bootstrap/Makefile
index 2e8bb8e..6c9a77c 100644
--- a/bootstrap/Makefile
+++ b/bootstrap/Makefile
@@ -150,7 +150,8 @@ $(builddir)/stage2: $(STAGE2_OBJECTS) $(RTL_C_HEADERS)
longlines outdirs
# TODO add a proper test once the stage2 compiler is done
check: $(builddir)/stage2
-check-all: check check-valgrind check-boundschecked clang-analyze longlines
+check-all: check check-valgrind check-boundschecked clang-analyze \
+ check-tokens longlines
check-valgrind: $(builddir)/stage1
valgrind --leak-check=yes -q $(builddir)/stage1 $(STAGE1_ARGS)
check-boundschecked: $(builddir)/stage1-boundschecked
@@ -165,6 +166,16 @@ longlines:
else \
true ;\
fi
+check-tokens:
+ grep -E '^ +CMP_KW' $(srcdir)/token.c | \
+ sed -E -e 's/^.*, "([^"]+)", T_KW_([a-zA-Z0-9_]+)\)/\1 \2/' | \
+ while read kwstr kwconst; do \
+ if [ "x$$kwstr" != "x$$kwconst" ]; then \
+ printf "Keyword str \"%s\" and enum \"%s\" mismatch\n" \
+ "$$kwstr" "$$kwconst" >&2; \
+ exit 1; \
+ fi; \
+ done
# Gives a lot of warnings (possibly false positives) and output gets mixed
# up (unless a single file is processed). So not included in check-all.
gcc-analyzer:
diff --git a/bootstrap/token.c b/bootstrap/token.c
index 322a3cc..99e4480 100644
--- a/bootstrap/token.c
+++ b/bootstrap/token.c
@@ -150,91 +150,93 @@ static enum Token tok_symbol(struct LexemeInfo *li_out)
}
-#define CMP_KW(length, keyword) \
- if (memcmp(ident, #keyword, (length)) == 0) { \
- return T_KW_##keyword; \
+#define CMP_KW(length, keyword_str, keyword_const) \
+ if (memcmp(ident, keyword_str, (length)) == 0) { \
+ return keyword_const; \
}
static enum Token match_keyword(const char *ident, size_t len)
{
+ /* These can be checked with `make -s check-tokens`
+ (included in `make check-all`) */
switch (len) {
case 2:
- CMP_KW(2, if)
- CMP_KW(2, in)
- CMP_KW(2, io)
- CMP_KW(2, of)
- CMP_KW(2, or)
- CMP_KW(2, to)
+ CMP_KW(2, "if", T_KW_if)
+ CMP_KW(2, "in", T_KW_in)
+ CMP_KW(2, "io", T_KW_io)
+ CMP_KW(2, "of", T_KW_of)
+ CMP_KW(2, "or", T_KW_or)
+ CMP_KW(2, "to", T_KW_to)
break;
case 3:
- CMP_KW(3, and)
- CMP_KW(3, end)
- CMP_KW(3, for)
- CMP_KW(3, int)
- CMP_KW(3, mod)
- CMP_KW(3, not)
+ CMP_KW(3, "and", T_KW_and)
+ CMP_KW(3, "end", T_KW_end)
+ CMP_KW(3, "for", T_KW_for)
+ CMP_KW(3, "int", T_KW_int)
+ CMP_KW(3, "mod", T_KW_mod)
+ CMP_KW(3, "not", T_KW_not)
/* XXX should there be `and`/`or`, or `all_of`/`any_of`/`none_of`?
maybe there should be a T... safe-vararg, like in Java. */
break;
case 4:
- CMP_KW(4, bool)
- CMP_KW(4, byte)
- CMP_KW(4, case)
- CMP_KW(4, code)
- CMP_KW(4, elif)
- CMP_KW(4, else)
- CMP_KW(4, enum)
- CMP_KW(4, from)
- CMP_KW(4, func)
- CMP_KW(4, long)
- CMP_KW(4, none)
- CMP_KW(4, sets)
- CMP_KW(4, this)
- CMP_KW(4, true)
+ CMP_KW(4, "bool", T_KW_bool)
+ CMP_KW(4, "byte", T_KW_byte)
+ CMP_KW(4, "case", T_KW_case)
+ CMP_KW(4, "code", T_KW_code)
+ CMP_KW(4, "elif", T_KW_elif)
+ CMP_KW(4, "else", T_KW_else)
+ CMP_KW(4, "enum", T_KW_enum)
+ CMP_KW(4, "from", T_KW_from)
+ CMP_KW(4, "func", T_KW_func)
+ CMP_KW(4, "long", T_KW_long)
+ CMP_KW(4, "none", T_KW_none)
+ CMP_KW(4, "sets", T_KW_sets)
+ CMP_KW(4, "this", T_KW_this)
+ CMP_KW(4, "true", T_KW_true)
break;
case 5:
- CMP_KW(5, break)
- CMP_KW(5, class)
- CMP_KW(5, entry)
- CMP_KW(5, false)
- CMP_KW(5, local)
- CMP_KW(5, reads)
- CMP_KW(5, trait)
- CMP_KW(5, while)
+ CMP_KW(5, "break", T_KW_break)
+ CMP_KW(5, "class", T_KW_class)
+ CMP_KW(5, "entry", T_KW_entry)
+ CMP_KW(5, "false", T_KW_false)
+ CMP_KW(5, "local", T_KW_local)
+ CMP_KW(5, "reads", T_KW_reads)
+ CMP_KW(5, "trait", T_KW_trait)
+ CMP_KW(5, "while", T_KW_while)
break;
case 6:
- CMP_KW(6, assert)
- CMP_KW(6, export)
- CMP_KW(6, giveme)
- CMP_KW(6, ignore)
- CMP_KW(6, record)
- CMP_KW(6, return)
- CMP_KW(6, signed)
- CMP_KW(6, switch)
+ CMP_KW(6, "assert", T_KW_assert)
+ CMP_KW(6, "export", T_KW_export)
+ CMP_KW(6, "giveme", T_KW_giveme)
+ CMP_KW(6, "ignore", T_KW_ignore)
+ CMP_KW(6, "record", T_KW_record)
+ CMP_KW(6, "return", T_KW_return)
+ CMP_KW(6, "signed", T_KW_signed)
+ CMP_KW(6, "switch", T_KW_switch)
break;
case 7:
- CMP_KW(7, aliased)
- CMP_KW(7, default)
- CMP_KW(7, loopend)
- CMP_KW(7, returns)
- CMP_KW(7, section)
+ CMP_KW(7, "aliased", T_KW_aliased)
+ CMP_KW(7, "default", T_KW_default)
+ CMP_KW(7, "loopend", T_KW_loopend)
+ CMP_KW(7, "returns", T_KW_returns)
+ CMP_KW(7, "section", T_KW_section)
break;
case 8:
- CMP_KW(8, continue)
- CMP_KW(8, modifies)
- CMP_KW(8, unsigned)
- CMP_KW(8, volatile)
- CMP_KW(8, wrapping)
+ CMP_KW(8, "continue", T_KW_continue)
+ CMP_KW(8, "modifies", T_KW_modifies)
+ CMP_KW(8, "unsigned", T_KW_unsigned)
+ CMP_KW(8, "volatile", T_KW_volatile)
+ CMP_KW(8, "wrapping", T_KW_wrapping)
break;
case 9:
- CMP_KW(9, loopempty)
- CMP_KW(9, templates)
+ CMP_KW(9, "loopempty", T_KW_loopempty)
+ CMP_KW(9, "templates", T_KW_templates)
break;
case 10:
- CMP_KW(10, calledfrom)
+ CMP_KW(10, "calledfrom", T_KW_calledfrom)
break;
case 11:
- CMP_KW(11, constructor)
+ CMP_KW(11, "constructor", T_KW_constructor)
break;
}
return 0;