commit 1cdd21249152b01d5d7c0e29ff161adb9d7adc56
parent caaed7002a569582b5ddbace90682c799a6a3b76
Author: Brian Swetland <swetland@frotz.net>
Date: Mon, 16 Oct 2023 16:13:19 -0700
compiler: String, keywords, keyword scanning
Diffstat:
M | compiler/compiler.spl | | | 110 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
1 file changed, 108 insertions(+), 2 deletions(-)
diff --git a/compiler/compiler.spl b/compiler/compiler.spl
@@ -12,10 +12,34 @@ fn error_end() {
os_exit(1);
}
+fn strneq(s1 str, s2 str, len u32) i32 {
+ var n u32 = 0;
+ while (n < len) {
+ if (s1[n] != s2[n]) {
+ return 0;
+ }
+ n++;
+ }
+ return 1;
+}
+
+fn strcpyn(dst str, src str, len u32) {
+ var n u32 = 0;
+ while (n < len) {
+ dst[n] = src[n];
+ n++;
+ }
+}
+
struct String {
+ next *String,
+ len u32,
+ text [256]u8,
};
struct Context {
+ stringlist *String, // intern table
+
linenumber u32, // line number of most recent line
lineoffset u32, // position of start of most recent line
byteoffset u32, // position of the most recent character
@@ -26,10 +50,66 @@ struct Context {
num u32, // for tNUM
tmp [256]u8, // for tIDN, tSTR
ident *String, // for tSTR
+
+ idn_if *String, // identifier strings
+ idn_fn *String,
+ idn_for *String,
+ idn_var *String,
+ idn_nil *String,
+ idn_new *String,
+ idn_case *String,
+ idn_else *String,
+ idn_enum *String,
+ idn_true *String,
+ idn_break *String,
+ idn_while *String,
+ idn_false *String,
+ idn_switch *String,
+ idn_struct *String,
+ idn_return *String,
+ idn_continue *String,
};
var ctx Context;
+fn string_make(text str, len u32) String {
+ var s String = ctx.stringlist;
+ while (s != nil) {
+ if (s.len == len) && strneq(text, s.text, len) {
+ return s;
+ }
+ s = s.next;
+ }
+ s = new(String);
+ s.len = len;
+ strcpyn(s.text, text, len + 1);
+ s.next = ctx.stringlist;
+ ctx.stringlist = s;
+ return s;
+}
+
+fn ctx_init() {
+ ctx = new(Context);
+
+ ctx.idn_if = string_make("if", 2);
+ ctx.idn_fn = string_make("fn", 2);
+ ctx.idn_for = string_make("for", 3);
+ ctx.idn_var = string_make("var", 3);
+ ctx.idn_nil = string_make("nil", 3);
+ ctx.idn_new = string_make("new", 3);
+ ctx.idn_case = string_make("case", 4);
+ ctx.idn_else = string_make("else", 4);
+ ctx.idn_enum = string_make("enum", 4);
+ ctx.idn_true = string_make("true", 4);
+ ctx.idn_break = string_make("break", 5);
+ ctx.idn_while = string_make("while", 5);
+ ctx.idn_false = string_make("false", 5);
+ ctx.idn_switch = string_make("switch", 6);
+ ctx.idn_struct = string_make("struct", 6);
+ ctx.idn_return = string_make("return", 6);
+ ctx.idn_continue = string_make("continue", 8);
+}
+
// ================================================================
// lexical scanner
@@ -192,7 +272,33 @@ fn scan_string(cc u32, nc u32) u32 {
fn scan_keyword(len u32) u32 {
ctx.tmp[len] = 0;
- // TODO
+ var idn String = string_make(ctx.tmp, len);
+ ctx.ident = idn;
+
+ if (len == 2) {
+ if (idn == ctx.idn_if) { return tIF; };
+ if (idn == ctx.idn_fn) { return tFN; }
+ } else if (len == 3) {
+ if (idn == ctx.idn_for) { return tFOR; }
+ if (idn == ctx.idn_var) { return tVAR; }
+ if (idn == ctx.idn_nil) { return tNIL; }
+ if (idn == ctx.idn_new) { return tNEW; }
+ } else if (len == 4) {
+ if (idn == ctx.idn_case) { return tCASE; }
+ if (idn == ctx.idn_else) { return tELSE; }
+ if (idn == ctx.idn_enum) { return tENUM; }
+ if (idn == ctx.idn_true) { return tTRUE; }
+ } else if (len == 5) {
+ if (idn == ctx.idn_break) { return tBREAK; }
+ if (idn == ctx.idn_while) { return tWHILE; }
+ if (idn == ctx.idn_false) { return tFALSE; }
+ } else if (len == 6) {
+ if (idn == ctx.idn_switch) { return tSWITCH; }
+ if (idn == ctx.idn_struct) { return tSTRUCT; }
+ if (idn == ctx.idn_return) { return tRETURN; }
+ } else if (len == 8) {
+ if (idn == ctx.idn_continue) { return tCONTINUE; }
+ }
return tIDN;
}
@@ -374,7 +480,7 @@ fn next() u32 {
}
fn start() i32 {
- ctx = new(Context);
+ ctx_init();
scan();
while(next() != tEOF) {