From 9528c34774ff27b112c9e66afff6e10fa7021635 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 23 Feb 2011 23:48:01 -0500 Subject: Begin implementing #fmt in rustc --- src/comp/front/extfmt.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/comp/front/extfmt.rs (limited to 'src/comp/front/extfmt.rs') diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs new file mode 100644 index 00000000..cb70805a --- /dev/null +++ b/src/comp/front/extfmt.rs @@ -0,0 +1,84 @@ +/* The 'fmt' extension is modeled on the posix printf system. + * + * A posix conversion ostensibly looks like this: + * + * %[parameter][flags][width][.precision][length]type + * + * Given the different numeric type bestiary we have, we omit the 'length' + * parameter and support slightly different conversions for 'type': + * + * %[parameter][flags][width][.precision]type + * + * we also only support translating-to-rust a tiny subset of the possible + * combinations at the moment. + */ + +use std; + +import std.option; + +tag signedness { + signed; + unsigned; +} + +tag caseness { + case_upper; + case_lower; +} + +tag ty { + ty_bool; + ty_str; + ty_char; + ty_int(signedness); + ty_bits; + ty_hex(caseness); + // FIXME: More types +} + +tag flag { + flag_left_justify; + flag_left_zero_pad; + flag_left_space_pad; + flag_plus_if_positive; + flag_alternate; +} + +tag count { + count_is(int); + count_is_param(int); + count_is_next_param; + count_implied; +} + +// A formatted conversion from an expression to a string +tag conv { + conv_param(option.t[int]); + conv_flags(vec[flag]); + conv_width(count); + conv_precision(count); + conv_ty(ty); +} + +// A fragment of the output sequence +tag piece { + piece_string(str); + piece_conv(str); +} + +fn expand_syntax_ext(vec[@ast.expr] args, + option.t[@ast.expr] body) -> @ast.expr { + fail; +} + +// +// Local Variables: +// mode: rust +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: +// -- cgit v1.2.3 From 1c60399257cde71fc265eb10cae1f398a0ac2516 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 24 Feb 2011 23:22:36 -0500 Subject: Begin work on #fmt parsing --- src/comp/front/extfmt.rs | 100 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 2 deletions(-) (limited to 'src/comp/front/extfmt.rs') diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index cb70805a..7018ef14 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -13,8 +13,10 @@ * combinations at the moment. */ -use std; +import front.parser; +import std._str; +import std._vec; import std.option; tag signedness { @@ -64,14 +66,108 @@ tag conv { // A fragment of the output sequence tag piece { piece_string(str); - piece_conv(str); + piece_conv(conv); +} + +fn bad_fmt_call() { + log "malformed #fmt call"; + fail; } fn expand_syntax_ext(vec[@ast.expr] args, option.t[@ast.expr] body) -> @ast.expr { + + if (_vec.len[@ast.expr](args) == 0u) { + bad_fmt_call(); + } + + auto fmt = expr_to_str(args.(0)); + log fmt; + auto pieces = parse_fmt_string(fmt); + ret pieces_to_expr(pieces, args); +} + +fn expr_to_str(@ast.expr expr) -> str { + alt (expr.node) { + case (ast.expr_lit(?l, _)) { + alt (l.node) { + case (ast.lit_str(?s)) { + ret s; + } + } + } + } + bad_fmt_call(); fail; } +fn parse_fmt_string(str s) -> vec[piece] { + let vec[piece] pieces = vec(); + // FIXME: Should be counting codepoints instead of bytes + auto lim = _str.byte_len(s); + auto buf = ""; + + // TODO: This is super ugly + fn flush_buf(str buf, vec[piece] pieces) -> str { + log "flushing"; + if (_str.byte_len(buf) > 0u) { + auto piece = piece_string(buf); + pieces += piece; + } + log "buf:"; + log buf; + log "pieces:"; + for (piece p in pieces) { + alt (p) { + case (piece_string(?s)) { + log s; + } + case (piece_conv(_)) { + log "conv"; + } + } + } + ret ""; + } + + auto i = 0u; + while (i < lim) { + log "step:"; + log i; + auto curr = _str.substr(s, i, 1u); + if (_str.eq(curr, "%")) { + i += 1u; + if (i >= lim) { + log "unterminated conversion at end of string"; + fail; + } + auto curr2 = _str.substr(s, i, 1u); + if (_str.eq(curr2, "%")) { + i += 1u; + } else { + buf = flush_buf(buf, pieces); + } + } else { + buf += curr; + log "buf:"; + log buf; + i += 1u; + } + } + + ret pieces; +} + +fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { + auto lo = args.(0).span; + auto hi = args.(0).span; + auto strlit = ast.lit_str("TODO"); + auto spstrlit = @parser.spanned[ast.lit_](lo, hi, strlit); + auto expr = ast.expr_lit(spstrlit, ast.ann_none); + auto spexpr = @parser.spanned[ast.expr_](lo, hi, expr); + ret spexpr; +} + // // Local Variables: // mode: rust -- cgit v1.2.3 From fe5de6bfffee3c277f540517b5766547f34e81c7 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 14:30:44 -0500 Subject: Parse parameter types for fmt extension --- src/comp/front/extfmt.rs | 148 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 120 insertions(+), 28 deletions(-) (limited to 'src/comp/front/extfmt.rs') diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 7018ef14..998bfa4d 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -18,6 +18,8 @@ import front.parser; import std._str; import std._vec; import std.option; +import std.option.none; +import std.option.some; tag signedness { signed; @@ -55,13 +57,11 @@ tag count { } // A formatted conversion from an expression to a string -tag conv { - conv_param(option.t[int]); - conv_flags(vec[flag]); - conv_width(count); - conv_precision(count); - conv_ty(ty); -} +type conv = rec(option.t[int] param, + vec[flag] flags, + count width, + count precision, + ty typ); // A fragment of the output sequence tag piece { @@ -84,6 +84,18 @@ fn expand_syntax_ext(vec[@ast.expr] args, auto fmt = expr_to_str(args.(0)); log fmt; auto pieces = parse_fmt_string(fmt); + log "printing all pieces"; + for (piece p in pieces) { + alt (p) { + case (piece_string(?s)) { + log s; + } + case (piece_conv(_)) { + log "conv"; + } + } + } + log "done printing all pieces"; ret pieces_to_expr(pieces, args); } @@ -107,33 +119,16 @@ fn parse_fmt_string(str s) -> vec[piece] { auto lim = _str.byte_len(s); auto buf = ""; - // TODO: This is super ugly - fn flush_buf(str buf, vec[piece] pieces) -> str { - log "flushing"; + fn flush_buf(str buf, &vec[piece] pieces) -> str { if (_str.byte_len(buf) > 0u) { auto piece = piece_string(buf); pieces += piece; } - log "buf:"; - log buf; - log "pieces:"; - for (piece p in pieces) { - alt (p) { - case (piece_string(?s)) { - log s; - } - case (piece_conv(_)) { - log "conv"; - } - } - } ret ""; } auto i = 0u; while (i < lim) { - log "step:"; - log i; auto curr = _str.substr(s, i, 1u); if (_str.eq(curr, "%")) { i += 1u; @@ -146,18 +141,115 @@ fn parse_fmt_string(str s) -> vec[piece] { i += 1u; } else { buf = flush_buf(buf, pieces); + auto res = parse_conversion(s, i, lim); + pieces += res._0; + i = res._1; } } else { buf += curr; - log "buf:"; - log buf; i += 1u; } } - + buf = flush_buf(buf, pieces); ret pieces; } +fn peek_num(str s, uint i, uint lim) -> option.t[tup(int, int)] { + if (i >= lim) { + ret none[tup(int, int)]; + } else { + ret none[tup(int, int)]; + /*if ('0' <= c && c <= '9') { + log c; + fail; + } else { + ret option.none[tup(int, int)]; + } + */ + } +} + +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 prec = parse_precision(s, width._1, lim); + auto ty = parse_type(s, prec._1, lim); + ret tup(piece_conv(rec(param = parm._0, + flags = flags._0, + width = width._0, + precision = prec._0, + typ = ty._0)), + ty._1); +} + +fn parse_parameter(str s, uint i, uint lim) -> tup(option.t[int], uint) { + if (i >= lim) { + ret tup(none[int], i); + } + + auto num = peek_num(s, i, lim); + alt (num) { + case (none[tup(int, int)]) { + ret tup(none[int], i); + } + case (some[tup(int, int)](?t)) { + fail; + } + } +} + +fn parse_flags(str s, uint i, uint lim) -> tup(vec[flag], uint) { + let vec[flag] flags = vec(); + ret tup(flags, i); +} + +fn parse_width(str s, uint i, uint lim) -> tup(count, uint) { + ret tup(count_implied, i); +} + +fn parse_precision(str s, uint i, uint lim) -> tup(count, uint) { + ret tup(count_implied, i); +} + +fn parse_type(str s, uint i, uint lim) -> tup(ty, uint) { + if (i >= lim) { + log "missing type in conversion"; + fail; + } + + auto t; + auto tstr = _str.substr(s, i, 1u); + if (_str.eq(tstr, "b")) { + t = ty_bool; + } else if (_str.eq(tstr, "s")) { + t = ty_str; + } else if (_str.eq(tstr, "c")) { + t = ty_char; + } else if (_str.eq(tstr, "d") + || _str.eq(tstr, "i")) { + // TODO: Do we really want two signed types here? + // How important is it to be printf compatible? + t = ty_int(signed); + } else if (_str.eq(tstr, "u")) { + t = ty_int(unsigned); + } else if (_str.eq(tstr, "x")) { + t = ty_hex(case_lower); + } else if (_str.eq(tstr, "X")) { + t = ty_hex(case_upper); + } else if (_str.eq(tstr, "t")) { + t = ty_bits; + } else { + // FIXME: This is a hack to avoid 'unsatisfied precondition + // constraint' on uninitialized variable t below + t = ty_bool; + log "unknown type in conversion"; + fail; + } + + ret tup(t, i + 1u); +} + fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { auto lo = args.(0).span; auto hi = args.(0).span; -- cgit v1.2.3 From f9144d5972aef3e7078b272703bf275691991297 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 18:23:16 -0500 Subject: Start generating AST nodes for #fmt --- src/comp/front/extfmt.rs | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) (limited to 'src/comp/front/extfmt.rs') diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 998bfa4d..38c2ea8c 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -13,7 +13,7 @@ * combinations at the moment. */ -import front.parser; +import util.common; import std._str; import std._vec; @@ -251,13 +251,39 @@ fn parse_type(str s, uint i, uint lim) -> tup(ty, uint) { } fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { - auto lo = args.(0).span; - auto hi = args.(0).span; - auto strlit = ast.lit_str("TODO"); - auto spstrlit = @parser.spanned[ast.lit_](lo, hi, strlit); - auto expr = ast.expr_lit(spstrlit, ast.ann_none); - auto spexpr = @parser.spanned[ast.expr_](lo, hi, expr); - ret spexpr; + + fn make_new_str(common.span sp, str s) -> @ast.expr { + auto strlit = ast.lit_str(s); + auto spstrlit = @parser.spanned[ast.lit_](sp, sp, strlit); + auto expr = ast.expr_lit(spstrlit, ast.ann_none); + ret @parser.spanned[ast.expr_](sp, sp, expr); + } + + fn make_add_expr(common.span sp, + @ast.expr lhs, @ast.expr rhs) -> @ast.expr { + auto binexpr = ast.expr_binary(ast.add, lhs, rhs, ast.ann_none); + ret @parser.spanned[ast.expr_](sp, sp, binexpr); + } + + auto sp = args.(0).span; + auto n = 0; + auto tmp_expr = make_new_str(sp, "whatever"); + + for (piece p in pieces) { + alt (p) { + case (piece_string(?s)) { + auto s_expr = make_new_str(sp, s); + tmp_expr = make_add_expr(sp, tmp_expr, s_expr); + } + case (piece_conv(?conv)) { + } + } + } + + // TODO: Remove this print and return the real expanded AST + log "dumping expanded ast:"; + log pretty.print_expr(tmp_expr); + ret make_new_str(sp, "TODO"); } // -- cgit v1.2.3 From 61edf544a2d16b43d0c4ba1c7537d6a8475f681c Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 19:44:57 -0500 Subject: Implement #fmt conversion for int and uint --- src/comp/front/extfmt.rs | 115 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 107 insertions(+), 8 deletions(-) (limited to 'src/comp/front/extfmt.rs') diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 38c2ea8c..bd5bab5b 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -21,6 +21,8 @@ import std.option; import std.option.none; import std.option.some; +export expand_syntax_ext; + tag signedness { signed; unsigned; @@ -61,7 +63,7 @@ type conv = rec(option.t[int] param, vec[flag] flags, count width, count precision, - ty typ); + ty ty); // A fragment of the output sequence tag piece { @@ -74,6 +76,7 @@ fn bad_fmt_call() { fail; } +// TODO: Need to thread parser through here to handle errors correctly fn expand_syntax_ext(vec[@ast.expr] args, option.t[@ast.expr] body) -> @ast.expr { @@ -96,6 +99,8 @@ fn expand_syntax_ext(vec[@ast.expr] args, } } log "done printing all pieces"; + auto args_len = _vec.len[@ast.expr](args); + auto fmt_args = _vec.slice[@ast.expr](args, 1u, args_len - 1u); ret pieces_to_expr(pieces, args); } @@ -179,7 +184,7 @@ fn parse_conversion(str s, uint i, uint lim) -> tup(piece, uint) { flags = flags._0, width = width._0, precision = prec._0, - typ = ty._0)), + ty = ty._0)), ty._1); } @@ -252,22 +257,107 @@ fn parse_type(str s, uint i, uint lim) -> tup(ty, uint) { fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { - fn make_new_str(common.span sp, str s) -> @ast.expr { - auto strlit = ast.lit_str(s); - auto spstrlit = @parser.spanned[ast.lit_](sp, sp, strlit); - auto expr = ast.expr_lit(spstrlit, ast.ann_none); + fn make_new_lit(common.span sp, ast.lit_ lit) -> @ast.expr { + auto sp_lit = @parser.spanned[ast.lit_](sp, sp, lit); + auto expr = ast.expr_lit(sp_lit, ast.ann_none); ret @parser.spanned[ast.expr_](sp, sp, expr); } + fn make_new_str(common.span sp, str s) -> @ast.expr { + auto lit = ast.lit_str(s); + ret make_new_lit(sp, lit); + } + + fn make_new_uint(common.span sp, uint u) -> @ast.expr { + auto lit = ast.lit_uint(u); + ret make_new_lit(sp, lit); + } + fn make_add_expr(common.span sp, @ast.expr lhs, @ast.expr rhs) -> @ast.expr { auto binexpr = ast.expr_binary(ast.add, lhs, rhs, ast.ann_none); ret @parser.spanned[ast.expr_](sp, sp, binexpr); } + fn make_call(common.span sp, vec[ast.ident] fn_path, + vec[@ast.expr] args) -> @ast.expr { + let vec[ast.ident] path_idents = fn_path; + let vec[@ast.ty] path_types = vec(); + auto path = rec(idents = path_idents, types = path_types); + auto sp_path = parser.spanned[ast.path_](sp, sp, path); + auto pathexpr = ast.expr_path(sp_path, none[ast.def], ast.ann_none); + auto sp_pathexpr = @parser.spanned[ast.expr_](sp, sp, pathexpr); + auto callexpr = ast.expr_call(sp_pathexpr, args, ast.ann_none); + auto sp_callexpr = @parser.spanned[ast.expr_](sp, sp, callexpr); + ret sp_callexpr; + } + + fn make_new_conv(conv cnv, @ast.expr arg) -> @ast.expr { + + auto unsupported = "conversion not supported in #fmt string"; + + alt (cnv.param) { + case (option.none[int]) { + } + case (_) { + log unsupported; + fail; + } + } + + if (_vec.len[flag](cnv.flags) != 0u) { + log unsupported; + fail; + } + + alt (cnv.width) { + case (count_implied) { + } + case (_) { + log unsupported; + fail; + } + } + + alt (cnv.precision) { + case (count_implied) { + } + case (_) { + log unsupported; + fail; + } + } + + alt (cnv.ty) { + case (ty_str) { + ret arg; + } + case (ty_int(?sign)) { + alt (sign) { + case (signed) { + let vec[str] path = vec("std", "_int", "to_str"); + auto radix_expr = make_new_uint(arg.span, 10u); + let vec[@ast.expr] args = vec(arg, radix_expr); + ret make_call(arg.span, path, args); + } + case (unsigned) { + let vec[str] path = vec("std", "_uint", "to_str"); + auto radix_expr = make_new_uint(arg.span, 10u); + let vec[@ast.expr] args = vec(arg, radix_expr); + ret make_call(arg.span, path, args); + } + } + } + case (_) { + log unsupported; + fail; + } + } + } + auto sp = args.(0).span; - auto n = 0; - auto tmp_expr = make_new_str(sp, "whatever"); + auto n = 0u; + auto tmp_expr = make_new_str(sp, ""); for (piece p in pieces) { alt (p) { @@ -276,6 +366,15 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { tmp_expr = make_add_expr(sp, tmp_expr, s_expr); } case (piece_conv(?conv)) { + if (n >= _vec.len[@ast.expr](args)) { + log "too many conversions in #fmt string"; + fail; + } + + n += 1u; + auto arg_expr = args.(n); + auto c_expr = make_new_conv(conv, arg_expr); + tmp_expr = make_add_expr(sp, tmp_expr, c_expr); } } } -- cgit v1.2.3 From 41a043303a53550590b2a8f10b3e57b79a92ecaa Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 27 Feb 2011 22:17:59 -0500 Subject: Remove debug logging from extfmt --- src/comp/front/extfmt.rs | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'src/comp/front/extfmt.rs') diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index bd5bab5b..938704b9 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -85,20 +85,7 @@ fn expand_syntax_ext(vec[@ast.expr] args, } auto fmt = expr_to_str(args.(0)); - log fmt; auto pieces = parse_fmt_string(fmt); - log "printing all pieces"; - for (piece p in pieces) { - alt (p) { - case (piece_string(?s)) { - log s; - } - case (piece_conv(_)) { - log "conv"; - } - } - } - log "done printing all pieces"; auto args_len = _vec.len[@ast.expr](args); auto fmt_args = _vec.slice[@ast.expr](args, 1u, args_len - 1u); ret pieces_to_expr(pieces, args); -- cgit v1.2.3 From 77a0dc06a7cead4a1d38cdb68f1465cbeccf48c1 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 1 Mar 2011 19:51:21 -0500 Subject: Whitespace cleanup --- src/comp/front/extfmt.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/comp/front/extfmt.rs') diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 938704b9..dfeb79de 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -1,14 +1,14 @@ /* The 'fmt' extension is modeled on the posix printf system. - * + * * A posix conversion ostensibly looks like this: - * + * * %[parameter][flags][width][.precision][length]type - * + * * Given the different numeric type bestiary we have, we omit the 'length' * parameter and support slightly different conversions for 'type': - * + * * %[parameter][flags][width][.precision]type - * + * * we also only support translating-to-rust a tiny subset of the possible * combinations at the moment. */ -- cgit v1.2.3 From 4bc9052e135c25c79d4fa8556c44876e620ba1f7 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 1 Mar 2011 21:03:44 -0500 Subject: Add debug logging for #fmt conv. Implement peek_num fn --- src/comp/front/extfmt.rs | 144 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 123 insertions(+), 21 deletions(-) (limited to 'src/comp/front/extfmt.rs') diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index dfeb79de..5ca50c05 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -71,17 +71,13 @@ tag piece { piece_conv(conv); } -fn bad_fmt_call() { - log "malformed #fmt call"; - fail; -} - // TODO: Need to thread parser through here to handle errors correctly fn expand_syntax_ext(vec[@ast.expr] args, option.t[@ast.expr] body) -> @ast.expr { if (_vec.len[@ast.expr](args) == 0u) { - bad_fmt_call(); + log "malformed #fmt call"; + fail; } auto fmt = expr_to_str(args.(0)); @@ -101,7 +97,7 @@ fn expr_to_str(@ast.expr expr) -> str { } } } - bad_fmt_call(); + log "malformed #fmt call"; fail; } @@ -146,19 +142,29 @@ fn parse_fmt_string(str s) -> vec[piece] { ret pieces; } -fn peek_num(str s, uint i, uint lim) -> option.t[tup(int, int)] { +fn peek_num(str s, uint i, uint lim) -> option.t[tup(uint, uint)] { if (i >= lim) { - ret none[tup(int, int)]; - } else { - ret none[tup(int, int)]; - /*if ('0' <= c && c <= '9') { - log c; - fail; - } else { - ret option.none[tup(int, int)]; + ret none[tup(uint, uint)]; + } + + // FIXME: Presumably s.(i) will return char eventually + auto c = s.(i); + if (!('0' as u8 <= c && c <= '9' as u8)) { + ret option.none[tup(uint, uint)]; + } + + auto n = (c - ('0' as u8)) as uint; + alt (peek_num(s, i + 1u, lim)) { + case (none[tup(uint, uint)]) { + ret some[tup(uint, uint)](tup(n, i + 1u)); + } + case (some[tup(uint, uint)](?next)) { + auto m = next._0; + auto j = next._1; + ret some[tup(uint, uint)](tup(n * 10u + m, j)); } - */ } + } fn parse_conversion(str s, uint i, uint lim) -> tup(piece, uint) { @@ -182,10 +188,10 @@ fn parse_parameter(str s, uint i, uint lim) -> tup(option.t[int], uint) { auto num = peek_num(s, i, lim); alt (num) { - case (none[tup(int, int)]) { + case (none[tup(uint, uint)]) { ret tup(none[int], i); } - case (some[tup(int, int)](?t)) { + case (some[tup(uint, uint)](?t)) { fail; } } @@ -342,6 +348,98 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { } } + fn log_conv(conv c) { + alt (c.param) { + case (some[int](?p)) { + log "param: " + std._int.to_str(p, 10u); + } + case (_) { + log "param: none"; + } + } + for (flag f in c.flags) { + alt (f) { + case (flag_left_justify) { + log "flag: left justify"; + } + case (flag_left_zero_pad) { + log "flag: left zero pad"; + } + case (flag_left_space_pad) { + log "flag: left space pad"; + } + case (flag_plus_if_positive) { + log "flag: plus if positive"; + } + case (flag_alternate) { + log "flag: alternate"; + } + } + } + alt (c.width) { + case (count_is(?i)) { + log "width: count is " + std._int.to_str(i, 10u); + } + case (count_is_param(?i)) { + log "width: count is param " + std._int.to_str(i, 10u); + } + case (count_is_next_param) { + log "width: count is next param"; + } + case (count_implied) { + log "width: count is implied"; + } + } + alt (c.precision) { + case (count_is(?i)) { + log "prec: count is " + std._int.to_str(i, 10u); + } + case (count_is_param(?i)) { + log "prec: count is param " + std._int.to_str(i, 10u); + } + case (count_is_next_param) { + log "prec: count is next param"; + } + case (count_implied) { + log "prec: count is implied"; + } + } + alt (c.ty) { + case (ty_bool) { + log "type: bool"; + } + case (ty_str) { + log "type: str"; + } + case (ty_char) { + log "type: char"; + } + case (ty_int(?s)) { + alt (s) { + case (signed) { + log "type: signed"; + } + case (unsigned) { + log "type: unsigned"; + } + } + } + case (ty_bits) { + log "type: bits"; + } + case (ty_hex(?cs)) { + alt (cs) { + case (case_upper) { + log "type: uhex"; + } + case (case_lower) { + log "type: lhex"; + } + } + } + } + } + auto sp = args.(0).span; auto n = 0u; auto tmp_expr = make_new_str(sp, ""); @@ -358,6 +456,10 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { fail; } + // TODO: Remove debug logging + log "Building conversion:"; + log_conv(conv); + n += 1u; auto arg_expr = args.(n); auto c_expr = make_new_conv(conv, arg_expr); @@ -366,10 +468,10 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { } } - // TODO: Remove this print and return the real expanded AST + // TODO: Remove this debug logging log "dumping expanded ast:"; log pretty.print_expr(tmp_expr); - ret make_new_str(sp, "TODO"); + ret tmp_expr; } // -- cgit v1.2.3 From 012c2d18d04f27ad52322a1a7673a14817c7d291 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 1 Mar 2011 22:43:19 -0500 Subject: Finish #fmt string parsing. Completely untested. --- src/comp/front/extfmt.rs | 96 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 7 deletions(-) (limited to 'src/comp/front/extfmt.rs') 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) { -- cgit v1.2.3 From fc722b17c92a91853f75c31e05b9a50d45fbe5e9 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 2 Mar 2011 13:53:08 -0800 Subject: Comment-out some logging chatter in extfmt. --- src/comp/front/extfmt.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/comp/front/extfmt.rs') diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 3f1e5c30..48f05df7 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -82,8 +82,8 @@ fn expand_syntax_ext(vec[@ast.expr] args, auto fmt = expr_to_str(args.(0)); - log "Format string:"; - log fmt; + // log "Format string:"; + // log fmt; auto pieces = parse_fmt_string(fmt); auto args_len = _vec.len[@ast.expr](args); @@ -539,8 +539,8 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { } // TODO: Remove debug logging - log "Building conversion:"; - log_conv(conv); + // log "Building conversion:"; + // log_conv(conv); n += 1u; auto arg_expr = args.(n); @@ -551,8 +551,8 @@ fn pieces_to_expr(vec[piece] pieces, vec[@ast.expr] args) -> @ast.expr { } // TODO: Remove this debug logging - log "dumping expanded ast:"; - log pretty.print_expr(tmp_expr); + // log "dumping expanded ast:"; + // log pretty.print_expr(tmp_expr); ret tmp_expr; } -- cgit v1.2.3 From 5876da00cfb78a849211804c820547fadef935f8 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 2 Mar 2011 19:08:04 -0500 Subject: Remove some erroneous FIXMEs from #fmt parser --- src/comp/front/extfmt.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/comp/front/extfmt.rs') diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 48f05df7..7201a17c 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -107,7 +107,6 @@ fn expr_to_str(@ast.expr expr) -> str { fn parse_fmt_string(str s) -> vec[piece] { let vec[piece] pieces = vec(); - // FIXME: Should be counting codepoints instead of bytes auto lim = _str.byte_len(s); auto buf = ""; @@ -151,7 +150,6 @@ fn peek_num(str s, uint i, uint lim) -> option.t[tup(uint, uint)] { ret none[tup(uint, uint)]; } - // FIXME: Presumably s.(i) will return char eventually auto c = s.(i); if (!('0' as u8 <= c && c <= '9' as u8)) { ret option.none[tup(uint, uint)]; -- cgit v1.2.3 From d39da6f97819becd9ea41c194b5f0daa178814fe Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 6 Mar 2011 13:56:38 -0500 Subject: Remove typestate workarounds --- src/comp/front/extfmt.rs | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'src/comp/front/extfmt.rs') diff --git a/src/comp/front/extfmt.rs b/src/comp/front/extfmt.rs index 7201a17c..255614d0 100644 --- a/src/comp/front/extfmt.rs +++ b/src/comp/front/extfmt.rs @@ -244,9 +244,7 @@ fn parse_count(str s, uint i, uint lim) -> tup(count, uint) { 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) { + if (s.(i) == ('*' as u8)) { auto param = parse_parameter(s, i + 1u, lim); auto j = param._1; alt (param._0) { @@ -257,9 +255,7 @@ fn parse_count(str s, uint i, uint lim) -> tup(count, uint) { ret tup(count_is_param(n), j); } } - } - - fn parse_count_(str s, uint i, uint lim) -> tup(count, uint) { + } else { auto num = peek_num(s, i, lim); alt (num) { case (none[tup(uint, uint)]) { @@ -270,12 +266,6 @@ fn parse_count(str s, uint i, uint lim) -> tup(count, uint) { } } } - - 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) { @@ -318,9 +308,6 @@ fn parse_type(str s, uint i, uint lim) -> tup(ty, uint) { } else if (_str.eq(tstr, "t")) { t = ty_bits; } else { - // FIXME: This is a hack to avoid 'unsatisfied precondition - // constraint' on uninitialized variable t below - t = ty_bool; log "unknown type in conversion"; fail; } -- cgit v1.2.3