commit b0066ae3ca26f1017fca8efd31a474f59304f696
parent 2a882b165c7cc5eede197109e2bdf65a73d1421f
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 5 Feb 2021 16:26:14 -0500
fmt: expand format string parser
Diffstat:
M | fmt/fmt.ha | | | 64 | +++++++++++++++++++++++++++++++++++----------------------------- |
1 file changed, 35 insertions(+), 29 deletions(-)
diff --git a/fmt/fmt.ha b/fmt/fmt.ha
@@ -104,25 +104,31 @@ export fn fprintf(
r: rune => r,
};
- let mod = modifiers { ... };
- const arg = switch (r) {
- '{' => match (io::write(s, utf8::encode_rune('{'))) {
- err: io::error => return err,
- w: size => {
- n += w;
- continue;
- },
- },
- '}' => {
- i += 1z;
- args[i - 1z];
- },
- ':' => {
- scan_modifiers(&iter, &mod);
- i += 1z;
- args[i - 1z];
+ const arg = if (r == '{') match (io::write(
+ s, utf8::encode_rune('{'))) {
+ err: io::error => return err,
+ w: size => {
+ n += w;
+ continue;
},
- * => args[scan_uint(r, &iter)],
+ } else if (ascii::isdigit(r)) {
+ strings::push(&iter, r);
+ args[scan_uint(&iter)];
+ } else {
+ strings::push(&iter, r);
+ i += 1z;
+ args[i - 1z];
+ };
+
+ let mod = modifiers { ... };
+ r = match (strings::next(&iter)) {
+ void => abort("Invalid format string (unterminated '{')"),
+ r: rune => r,
+ };
+ switch (r) {
+ ':' => scan_modifiers(&iter, &mod),
+ '}' => void,
+ * => abort("Invalid format string"),
};
format(s, arg, &mod);
@@ -173,29 +179,29 @@ fn format(
},
};
-fn scan_uint(r: rune, iter: *strings::iterator) uint = {
- assert(ascii::isdigit(r));
- let num = alloc([]u8, [r: u32: u8], 1z); // XXX: alloc slice w/o cap
+fn scan_uint(iter: *strings::iterator) uint = {
+ let num = alloc([]u8, [], 1z); // TODO: alloc slice w/o cap
defer free(num);
for (true) {
- r = match (strings::next(iter)) {
- void => abort("Invalid format string (unterminated '(')"),
+ let r = match (strings::next(iter)) {
+ void => abort("Invalid format string (unterminated '{')"),
r: rune => r,
};
- switch (r) {
- * => append(num, r: u32: u8),
- ':' => abort(), // TODO: Format modifiers
- '}' => match (strconv::stou(strings::from_utf8(num))) {
+ if (ascii::isdigit(r)) {
+ append(num, r: u32: u8);
+ } else {
+ strings::push(iter, r);
+ match (strconv::stou(strings::from_utf8(num))) {
(strconv::invalid | strconv::overflow) =>
abort("Invalid format string (invalid index)"),
u: uint => return u,
- },
+ };
};
};
abort("unreachable");
};
fn scan_modifiers(iter: *strings::iterator, mod: *modifiers) void = {
- abort(); // TODO
+ abort("TODO: format modifiers");
};