diff options
| author | Brian Anderson <[email protected]> | 2011-03-01 22:43:19 -0500 |
|---|---|---|
| committer | Graydon Hoare <[email protected]> | 2011-03-02 10:28:15 -0800 |
| commit | 012c2d18d04f27ad52322a1a7673a14817c7d291 (patch) | |
| tree | 97c78c9b22632148e59e70746572caefbec59d96 /src | |
| parent | Add debug logging for #fmt conv. Implement peek_num fn (diff) | |
| download | rust-012c2d18d04f27ad52322a1a7673a14817c7d291.tar.xz rust-012c2d18d04f27ad52322a1a7673a14817c7d291.zip | |
Finish #fmt string parsing. Completely untested.
Diffstat (limited to 'src')
| -rw-r--r-- | src/comp/front/extfmt.rs | 96 |
1 files changed, 89 insertions, 7 deletions
diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 5ca50c05..3f1e5c30 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -81,6 +81,10 @@ fn expand_syntax_ext(vec[@ast.expr] args, } auto fmt = expr_to_str(args.(0)); + + log "Format string:"; + log fmt; + auto pieces = parse_fmt_string(fmt); auto args_len = _vec.len[@ast.expr](args); auto fmt_args = _vec.slice[@ast.expr](args, 1u, args_len - 1u); @@ -170,7 +174,7 @@ fn peek_num(str s, uint i, uint lim) -> option.t[tup(uint, uint)] { fn parse_conversion(str s, uint i, uint lim) -> tup(piece, uint) { auto parm = parse_parameter(s, i, lim); auto flags = parse_flags(s, parm._1, lim); - auto width = parse_width(s, flags._1, lim); + auto width = parse_count(s, flags._1, lim); auto prec = parse_precision(s, width._1, lim); auto ty = parse_type(s, prec._1, lim); ret tup(piece_conv(rec(param = parm._0, @@ -192,22 +196,100 @@ fn parse_parameter(str s, uint i, uint lim) -> tup(option.t[int], uint) { ret tup(none[int], i); } case (some[tup(uint, uint)](?t)) { - fail; + auto n = t._0; + auto j = t._1; + if (j < lim && s.(j) == '$' as u8) { + ret tup(some[int](n as int), j + 1u); + } + else { + ret tup(none[int], i); + } } } } fn parse_flags(str s, uint i, uint lim) -> tup(vec[flag], uint) { - let vec[flag] flags = vec(); - ret tup(flags, i); + let vec[flag] noflags = vec(); + + if (i >= lim) { + ret tup(noflags, i); + } + + fn more_(flag f, str s, uint i, uint lim) -> tup(vec[flag], uint) { + auto next = parse_flags(s, i + 1u, lim); + auto rest = next._0; + auto j = next._1; + let vec[flag] curr = vec(f); + ret tup(curr + rest, j); + } + + auto more = bind more_(_, s, i, lim); + + auto f = s.(i); + if (f == ('-' as u8)) { + ret more(flag_left_justify); + } else if (f == ('0' as u8)) { + ret more(flag_left_zero_pad); + } else if (f == (' ' as u8)) { + ret more(flag_left_space_pad); + } else if (f == ('+' as u8)) { + ret more(flag_plus_if_positive); + } else if (f == ('#' as u8)) { + ret more(flag_alternate); + } else { + ret tup(noflags, i); + } } -fn parse_width(str s, uint i, uint lim) -> tup(count, uint) { - ret tup(count_implied, i); +fn parse_count(str s, uint i, uint lim) -> tup(count, uint) { + if (i >= lim) { + ret tup(count_implied, i); + } + + // FIXME: These inner functions are just to avoid a rustboot + // "Unsatisfied precondition constraint" bug with alts nested in ifs + fn parse_star_count(str s, uint i, uint lim) -> tup(count, uint) { + auto param = parse_parameter(s, i + 1u, lim); + auto j = param._1; + alt (param._0) { + case (none[int]) { + ret tup(count_is_next_param, j); + } + case (some[int](?n)) { + ret tup(count_is_param(n), j); + } + } + } + + fn parse_count_(str s, uint i, uint lim) -> tup(count, uint) { + auto num = peek_num(s, i, lim); + alt (num) { + case (none[tup(uint, uint)]) { + ret tup(count_implied, i); + } + case (some[tup(uint, uint)](?num)) { + ret tup(count_is(num._0 as int), num._1); + } + } + } + + if (s.(i) == ('*' as u8)) { + ret parse_star_count(s, i, lim); + } else { + ret parse_count_(s, i, lim); + } } fn parse_precision(str s, uint i, uint lim) -> tup(count, uint) { - ret tup(count_implied, i); + if (i >= lim) { + ret tup(count_implied, i); + } + + if (s.(i) == '.' as u8) { + ret parse_count(s, i + 1u, lim); + } else { + ret tup(count_implied, i); + } } fn parse_type(str s, uint i, uint lim) -> tup(ty, uint) { |