aboutsummaryrefslogtreecommitdiff
path: root/src/parse.cff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-12 11:20:43 +0200
committerlemon <lsof@mailbox.org>2022-08-12 11:20:43 +0200
commiteff929f0d323559f3b2e9272e3c1d4aa82fc5c80 (patch)
treec3dd54fe4ed4a3082f455c8fe37436f767760977 /src/parse.cff
parent19f1093f0929b989a06cdee2e7d175e6db15559c (diff)
va list, cont fix
Diffstat (limited to 'src/parse.cff')
-rw-r--r--src/parse.cff83
1 files changed, 83 insertions, 0 deletions
diff --git a/src/parse.cff b/src/parse.cff
index f659322..d672173 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -80,6 +80,20 @@ fn issep(c u8) bool {
return #f;
}
+fn readtilsep(P *Parser, buf [#]u8, dot bool) int {
+ let i = 0,
+ c u8 #?;
+ while (not issep(c = chrpeek(P))) or (dot and c == '.') {
+ chr(P);
+ if i >= buf.#len - 1 {
+ return -1;
+ }
+ buf[i++] = c;
+ }
+ buf[i++] = 0;
+ return i;
+}
+
fn eatspaces(P *Parser) void {
for ;;chr(P) {
if not isspace(chrpeek(P)) {
@@ -115,6 +129,59 @@ fn str2keyword(s *const u8) int {
return -1;
}
+fn readnumber(s *const u8) Option<Tok> {
+ let c u8 #?,
+ acc = 0u64,
+ accf = 0.0f64,
+ fmul = 0.1,
+ base = 10,
+ flt = #f,
+ nused = 0,
+ suffix *const u8 = #null;
+
+ for let i = 0; (c = s[i]) != 0; ++i {
+ if i == 0 and c == '0' {
+ --nused;
+ }
+ if i == 1 and tolower(c) == 'x' {
+ base = 16;
+ continue;
+ }
+ if not flt and c == '.' and base == 10 {
+ flt = #t;
+ accf = acc;
+ continue;
+ }
+ if nused > 0 and c == '_' { continue; }
+ if (base == 16 and not isdigit(c))
+ or (base != 16 and (c < '0' or c > ('0' + base) - 1)) {
+ suffix = s + i;
+ }
+
+ ++nused;
+ if flt {
+ accf = accf + ((c - '0') * fmul);
+ fmul *= 0.1;
+ } else {
+ c = tolower(c);
+ acc = (acc * base) + (c <= '9' ? c - '0' : (c - 'a') + 10);
+ }
+ }
+
+ let tok = Tok {};
+ if flt {
+ tok.t = :flo;
+ tok.u.flo = accf;
+ return :Some tok;
+ } else {
+ tok.t = :int;
+ tok.u.uint = acc;
+ return :Some tok;
+ }
+
+ return :None;
+}
+
fn lex(P *Parser) Tok {
let c int #?;
let tok Tok = {};
@@ -129,7 +196,22 @@ fn lex(P *Parser) Tok {
tok.loc = (P.tokloc = P.curloc);
if isdigit(c = chrpeek(P)) {
let s [80]u8 = {};
+ if readtilsep(P, s[0::], #t) < 0 {
+ // fatal
+ }
+ switch readnumber(s) {
+ case None;
+ fatal(P, tok.loc, "bad number literal %qs", s);
+ case Some tok;
+ tok.loc = P.tokloc;
+ return tok;
+ }
+ }
+ if c == EOF {
+ tok.t = :eof;
+ return tok;
}
+ fatal(P, tok.loc, "stray %qc in program", c);
}
extern fn parse(P *Parser) [#]Decl {
@@ -137,6 +219,7 @@ extern fn parse(P *Parser) [#]Decl {
}
extern fn parser_init(P *Parser, path *const u8) void {
+ assert(NUM_KEYWORDS - 1 < '!', "2manykw");
*P = {};
P.curfile = path;
if (P.fp = fopen(path, "r")) == #null {