diff options
| author | 2022-08-12 16:43:06 +0200 | |
|---|---|---|
| committer | 2022-08-12 16:43:06 +0200 | |
| commit | 1eb17cda6780476b166b55d0fedc3ad355969e87 (patch) | |
| tree | ccb4ffa74cc37f24e93d4325ccf395d3fe73529f /src/fmt.cff | |
| parent | f14aee6184568bae34f8d8d8f9140fa760099fa5 (diff) | |
selfhosted lexer
Diffstat (limited to 'src/fmt.cff')
| -rw-r--r-- | src/fmt.cff | 113 |
1 files changed, 82 insertions, 31 deletions
diff --git a/src/fmt.cff b/src/fmt.cff index 885ea50..ecf7d74 100644 --- a/src/fmt.cff +++ b/src/fmt.cff @@ -3,41 +3,83 @@ import "all.hff"; extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) void { defmacro p(x) [ proc(x, parg) ] defmacro ps(s) [ - for let $i = 0; (s)[$i] != 0; ++$i { - p(s[$i]); + for let $s *const u8 = (s); *$s != 0; ++$s { + p(*$s); } ] - let buf [100]u8 = {}; + + defmacro pch(ch) [ { + extern fn isprint(int) int; + if isprint(ch) != 0 { + p(ch); + } else { + p('\\'); + p('0' + (ch % 8)); + p('0' + ((ch / 8) % 8)); + p('0' + ((ch / 8 / 8) % 8)); + } + } ] + + static buf [100]u8 = {}; + + fn pritok(proc typeof(proc), parg *void, quote bool, tok *const Tok) void { + switch tok.t { + case :int; + sprintf(buf, "%lld", tok.u.int); + ps(buf); + case :str; + pfmt(proc, parg, "%S", tok.u.str); + case :ident; + if quote { p('`'); } + ps(tok.u.ident); + if quote { p('\''); } + case else + if tok.t >= 0 and tok.t < NUM_KEYWORDS { + if quote { p('`'); } + ps(tok.u.ident); + if quote { p('\''); } + } else if tok.t > 0 { + if quote { p('`'); } + let t = bswap32(tok.t); + let i = 0; + while t != 0 { + if t & 0xFF != 0 { + p(t); + } + t >>= 8; + } + buf[i] = '\0'; + if quote { p('\''); } + } + } + } + for let c u8 = *fmt; c != 0; c = *++fmt { assert(c != 0, "?"); if c != '%' { p(c); if fmt[1] == 0 { break; } - continue; + continue; } let quote = #f; - #'fmt do { + for ;; { switch (c = *++fmt) { - case 'i'; - sprintf(buf, "%d", ap->arg(int)); - ps(buf); case 'q'; quote = #t; - continue #'fmt; + continue; + case 'i', 'd'; + sprintf(buf, "%d", ap->arg(int)); + ps(buf); + case 'p'; + sprintf(buf, "%p", ap->arg(*void)); + ps(buf); case 'c'; let ch u32 = ap->arg(int); if quote { - extern fn isprint(int) int; p('\''); for ch = bswap32(ch); ch != 0; ch >>= 8 { if ch & 0xFF != 0 { - if isprint(ch) != 0 { p(ch); } - else { - p('\\'); - p('0' + (ch % 8)); - p('0' + ((ch / 8) % 8)); - p('0' + ((ch / 8 / 8) % 8)); - } + pch(ch); } } p('\''); @@ -57,38 +99,47 @@ extern fn vpfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ap va_list) extern fn isprint(int) int; p('\"'); for let c u8 #?; (c = *s++) != 0; { - if isprint(c) != 0 { - p(c); - } else { - p('\\'); - p('0' + (c % 8)); - p('0' + ((c / 8) % 8)); - p('0' + ((c / 8 / 8) % 8)); - } + pch(c); } p('\"'); } else { ps(s); } + case 'S'; + let str = ap->arg([#]const u8); + p('"'); + foreach(c, i, str, + pch(c); + ) + p('"'); + case 'T'; + let tok = ap->arg(Tok); + pritok(proc, parg, quote, &tok); case else - // assert(#f, "bad fmt '%c' @ %d", c, i); + assert(#f, "bad fmt '%c'", c); } - } while #f; + break; + } } } +extern fn pfmt(proc *fn(u8, *void) void, parg *void, fmt *const u8, ...) void { + let ap va_list #?; + ap->start(fmt); + vpfmt(proc, parg, fmt, ap); + ap->end(); +} + extern fn vefmt(fmt *const u8, ap va_list) void { - fn epri(c u8, *void) void { + fn eputc(c u8, *void) void { fputc(c, stderr); } - - vpfmt(&epri, #null, fmt, ap); + vpfmt(&eputc, #null, fmt, ap); } extern fn efmt(fmt *const u8, ...) void { let ap va_list #?; ap->start(fmt); - vefmt(fmt, ap); ap->end(); } |