Improve comment handling in pp.

This commit is contained in:
Graydon Hoare 2011-05-30 14:10:54 -07:00
parent 30f8348473
commit d12ea39896
4 changed files with 335 additions and 207 deletions

View file

@ -22,6 +22,7 @@ state type reader = state obj {
fn get_mark_chpos() -> uint;
fn get_interner() -> @interner::interner[str];
fn get_chpos() -> uint;
fn get_col() -> uint;
fn get_filemap() -> codemap::filemap;
fn err(str m);
};
@ -33,6 +34,7 @@ fn new_reader(session sess, io::reader rdr,
state obj reader(session sess,
str file,
uint len,
mutable uint col,
mutable uint pos,
mutable char ch,
mutable uint mark_chpos,
@ -68,9 +70,11 @@ fn new_reader(session sess, io::reader rdr,
fn bump() {
if (pos < len) {
col += 1u;
chpos += 1u;
if (ch == '\n') {
codemap::next_line(fm, chpos);
col = 0u;
}
auto next = str::char_range_at(file, pos);
pos = next._1;
@ -82,6 +86,10 @@ fn new_reader(session sess, io::reader rdr,
fn get_interner() -> @interner::interner[str] { ret itr; }
fn get_col() -> uint {
ret col;
}
fn get_filemap() -> codemap::filemap {
ret fm;
}
@ -92,7 +100,8 @@ fn new_reader(session sess, io::reader rdr,
}
auto file = str::unsafe_from_bytes(rdr.read_whole_stream());
let vec[str] strs = [];
auto rd = reader(sess, file, str::byte_len(file), 0u, -1 as char,
auto rd = reader(sess, file, str::byte_len(file), 0u, 0u,
-1 as char,
filemap.start_pos, filemap.start_pos,
strs, filemap, itr);
rd.init();
@ -155,7 +164,7 @@ fn is_whitespace(char c) -> bool {
ret c == ' ' || c == '\t' || c == '\r' || c == '\n';
}
fn consume_any_whitespace(&reader rdr) {
fn consume_whitespace_and_comments(&reader rdr) {
while (is_whitespace(rdr.curr())) {
rdr.bump();
}
@ -170,7 +179,7 @@ fn consume_any_line_comment(&reader rdr) {
rdr.bump();
}
// Restart whitespace munch.
be consume_any_whitespace(rdr);
be consume_whitespace_and_comments(rdr);
}
case ('*') {
rdr.bump();
@ -207,7 +216,7 @@ fn consume_block_comment(&reader rdr) {
}
}
// restart whitespace munch.
be consume_any_whitespace(rdr);
be consume_whitespace_and_comments(rdr);
}
fn digits_to_string(str s) -> int {
@ -430,7 +439,7 @@ fn scan_numeric_escape(&reader rdr, uint n_hex_digits) -> char {
fn next_token(&reader rdr) -> token::token {
auto accum_str = "";
consume_any_whitespace(rdr);
consume_whitespace_and_comments(rdr);
if (rdr.is_eof()) { ret token::EOF; }
@ -720,70 +729,161 @@ fn next_token(&reader rdr) -> token::token {
fail;
}
tag cmnt_ {
cmnt_line(str);
cmnt_block(vec[str]);
tag cmnt_style {
isolated; // No code on either side of each line of the comment
trailing; // Code exists to the left of the comment
mixed; // Code before /* foo */ and after the comment
}
type cmnt = rec(cmnt_ val, uint pos, bool space_after);
type cmnt = rec(cmnt_style style, vec[str] lines, uint pos);
fn consume_whitespace(&reader rdr) -> uint {
auto lines = 0u;
while (is_whitespace(rdr.curr())) {
if (rdr.curr() == '\n') {lines += 1u;}
rdr.bump();
}
ret lines;
}
fn read_line_comment(&reader rdr) -> cmnt {
auto p = rdr.get_chpos();
rdr.bump(); rdr.bump();
while (rdr.curr() == ' ') {rdr.bump();}
fn read_to_eol(&reader rdr) -> str {
auto val = "";
while (rdr.curr() != '\n' && !rdr.is_eof()) {
str::push_char(val, rdr.curr());
rdr.bump();
}
ret rec(val=cmnt_line(val),
pos=p,
space_after=consume_whitespace(rdr) > 1u);
if (rdr.curr() == '\n') {
rdr.bump();
} else {
assert rdr.is_eof();
}
ret val;
}
fn read_block_comment(&reader rdr) -> cmnt {
fn read_one_line_comment(&reader rdr) -> str {
auto val = read_to_eol(rdr);
assert val.(0) == ('/' as u8) && val.(1) == ('/' as u8);
ret val;
}
fn consume_whitespace(&reader rdr) {
while (is_whitespace(rdr.curr()) && !rdr.is_eof()) {
rdr.bump();
}
}
fn consume_non_eol_whitespace(&reader rdr) {
while (is_whitespace(rdr.curr()) &&
rdr.curr() != '\n' && !rdr.is_eof()) {
rdr.bump();
}
}
fn read_line_comments(&reader rdr, bool code_to_the_left) -> cmnt {
log ">>> line comments";
auto p = rdr.get_chpos();
rdr.bump(); rdr.bump();
while (rdr.curr() == ' ') {rdr.bump();}
let vec[str] lines = [];
auto val = "";
auto level = 1;
while (true) {
if (rdr.curr() == '\n') {
vec::push[str](lines, val);
val = "";
consume_whitespace(rdr);
} else {
if (rdr.curr() == '*' && rdr.next() == '/') {
level -= 1;
if (level == 0) {
rdr.bump(); rdr.bump();
vec::push[str](lines, val);
break;
}
} else if (rdr.curr() == '/' && rdr.next() == '*') {
level += 1;
}
str::push_char(val, rdr.curr());
rdr.bump();
while (rdr.curr() == '/' && rdr.next() == '/') {
lines += [read_one_line_comment(rdr)];
consume_non_eol_whitespace(rdr);
}
log "<<< line comments";
ret rec(style = if (code_to_the_left) { trailing } else { isolated },
lines = lines,
pos=p);
}
fn all_whitespace(&str s, uint begin, uint end) -> bool {
let uint i = begin;
while (i != end) {
if (!is_whitespace(s.(i) as char)) {
ret false;
}
i += 1u;
}
ret true;
}
fn trim_whitespace_prefix_and_push_line(&mutable vec[str] lines,
&str s, uint col) {
auto s1;
if (all_whitespace(s, 0u, col)) {
if (col < str::byte_len(s)) {
s1 = str::slice(s, col, str::byte_len(s));
} else {
s1 = "";
}
} else {
s1 = s;
}
log "pushing line: " + s1;
lines += [s1];
}
fn read_block_comment(&reader rdr,
bool code_to_the_left) -> cmnt {
log ">>> block comment";
auto p = rdr.get_chpos();
let vec[str] lines = [];
let uint col = rdr.get_col();
rdr.bump();
rdr.bump();
auto curr_line = "/*";
let int level = 1;
while (level > 0) {
log #fmt("=== block comment level %d", level);
if (rdr.is_eof()) {
rdr.err("Unexpected end of file in block comment");
rdr.err("unterminated block comment");
fail;
}
if (rdr.curr() == '\n') {
trim_whitespace_prefix_and_push_line(lines, curr_line, col);
curr_line = "";
rdr.bump();
} else {
str::push_char(curr_line, rdr.curr());
if (rdr.curr() == '/' && rdr.next() == '*') {
rdr.bump();
rdr.bump();
curr_line += "*";
level += 1;
} else {
if (rdr.curr() == '*' && rdr.next() == '/') {
rdr.bump();
rdr.bump();
curr_line += "/";
level -= 1;
} else {
rdr.bump();
}
}
}
}
ret rec(val=cmnt_block(lines),
pos=p,
space_after=consume_whitespace(rdr) > 1u);
if (str::byte_len(curr_line) != 0u) {
trim_whitespace_prefix_and_push_line(lines, curr_line, col);
}
auto style = if (code_to_the_left) { trailing } else { isolated };
consume_non_eol_whitespace(rdr);
if (!rdr.is_eof() &&
rdr.curr() != '\n' &&
vec::len(lines) == 1u) {
style = mixed;
}
log "<<< block comment";
ret rec(style = style, lines = lines, pos=p);
}
fn peeking_at_comment(&reader rdr) -> bool {
ret (rdr.curr() == '/' && rdr.next() == '/') ||
(rdr.curr() == '/' && rdr.next() == '*');
}
fn consume_comment(&reader rdr, bool code_to_the_left,
&mutable vec[cmnt] comments) {
log ">>> consume comment";
if (rdr.curr() == '/' && rdr.next() == '/') {
vec::push[cmnt](comments,
read_line_comments(rdr, code_to_the_left));
} else if (rdr.curr() == '/' && rdr.next() == '*') {
vec::push[cmnt](comments,
read_block_comment(rdr, code_to_the_left));
} else { fail; }
log "<<< consume comment";
}
fn gather_comments(session sess, str path) -> vec[cmnt] {
@ -793,17 +893,22 @@ fn gather_comments(session sess, str path) -> vec[cmnt] {
let vec[cmnt] comments = [];
while (!rdr.is_eof()) {
while (true) {
consume_whitespace(rdr);
if (rdr.curr() == '/' && rdr.next() == '/') {
vec::push[cmnt](comments, read_line_comment(rdr));
} else if (rdr.curr() == '/' && rdr.next() == '*') {
vec::push[cmnt](comments, read_block_comment(rdr));
} else { break; }
auto code_to_the_left = true;
consume_non_eol_whitespace(rdr);
if (rdr.next() == '\n') {
code_to_the_left = false;
consume_whitespace(rdr);
}
while (peeking_at_comment(rdr)) {
consume_comment(rdr, code_to_the_left, comments);
consume_whitespace(rdr);
}
break;
}
next_token(rdr);
}
ret comments;
}
}
//

View file

@ -164,7 +164,7 @@ fn new_parser(session::session sess,
auto itr = @interner::mk[str](str::hash, str::eq);
auto rdr = lexer::new_reader(sess, srdr, filemap, itr);
// Make sure npos points at first actual token:
lexer::consume_any_whitespace(rdr);
lexer::consume_whitespace_and_comments(rdr);
auto npos = rdr.get_chpos();
ret stdio_parser(sess, env, ftype, lexer::next_token(rdr),
npos, npos, npos, initial_def._1, UNRESTRICTED,

View file

@ -34,6 +34,25 @@ import std::str;
* I also inverted the indentation arithmetic used in the print stack, since
* the Mesa implementation (somewhat randomly) stores the offset on the print
* stack in terms of margin-col rather than col itself. I store col.
*
* I also implemented a small change in the STRING token, in that I store an
* explicit length for the string. For most tokens this is just the length of
* the accompanying string. But it's necessary to permit it to differ, for
* encoding things that are supposed to "go on their own line" -- certain
* classes of comment and blank-line -- where relying on adjacent
* hardbreak-like BREAK tokens with long blankness indication doesn't actually
* work. To see why, consider when there is a "thing that should be on its own
* line" between two long blocks, say functions. If you put a hardbreak after
* each function (or before each) and the breaking algorithm decides to break
* there anyways (because the functions themselves are long) you wind up with
* extra blank lines. If you don't put hardbreaks you can wind up with the
* "thing which should be on its own line" not getting its own line in the
* rare case of "really small functions" or such. This re-occurs with comments
* and explicit blank lines. So in those cases we use a string with a payload
* we want isolated to a line and an explicit length that's huge, surrounded
* by two zero-length breaks. The algorithm will try its best to fit it on a
* line (which it can't) and so naturally place the content on its own line to
* avoid combining it with other lines and making matters even worse.
*/
tag breaks { consistent; inconsistent; }
@ -41,7 +60,7 @@ type break_t = rec(int offset, int blank_space);
type begin_t = rec(int offset, breaks breaks);
tag token {
STRING(str);
STRING(str,int);
BREAK(break_t);
BEGIN(begin_t);
END;
@ -51,7 +70,7 @@ tag token {
fn tok_str(token t) -> str {
alt (t) {
case (STRING(?s)) { ret "STR(" + s + ")"; }
case (STRING(?s, ?len)) { ret #fmt("STR(%s,%d)", s, len); }
case (BREAK(_)) { ret "BREAK"; }
case (BEGIN(_)) { ret "BEGIN"; }
case (END) { ret "END"; }
@ -279,8 +298,7 @@ obj printer(io::writer out,
right_total += b.blank_space;
}
case (STRING(?s)) {
auto len = str::char_len(s) as int;
case (STRING(?s, ?len)) {
if (scan_stack_empty) {
log #fmt("pp STRING/print [%u,%u]", left, right);
self.print(t, len);
@ -370,10 +388,9 @@ obj printer(io::writer out,
case (BREAK(?b)) {
left_total += b.blank_space;
}
case (STRING(?s)) {
// I think? paper says '1' here but 1 and L look same in
// it.
left_total += L;
case (STRING(_, ?len)) {
assert len == L;
left_total += len;
}
case (_) {}
}
@ -486,11 +503,11 @@ obj printer(io::writer out,
}
}
case (STRING(?s)) {
case (STRING(?s, ?len)) {
log "print STRING";
assert L as uint == str::char_len(s);
assert L == len;
// assert L <= space;
space -= L;
space -= len;
out.write_str(s);
}
@ -527,8 +544,14 @@ fn break_offset(printer p, uint n, int off) {
fn end(printer p) { p.pretty_print(END); }
fn eof(printer p) { p.pretty_print(EOF); }
fn wrd(printer p, str wrd) { p.pretty_print(STRING(wrd)); }
fn word(printer p, str wrd) {
p.pretty_print(STRING(wrd, str::char_len(wrd) as int));
}
fn word_and_eol(printer p, str wrd) {
p.pretty_print(STRING(wrd, 0xffff));
}
fn spaces(printer p, uint n) { break_offset(p, n, 0); }
fn zerobreak(printer p) { spaces(p, 0u); }
fn space(printer p) { spaces(p, 1u); }
fn hardbreak(printer p) { spaces(p, 0xffffu); }

View file

@ -14,8 +14,10 @@ import pp::break_offset;
import pp::box;
import pp::cbox;
import pp::ibox;
import pp::wrd;
import pp::word;
import pp::word_and_eol;
import pp::space;
import pp::zerobreak;
import pp::hardbreak;
import pp::breaks;
import pp::consistent;
@ -82,42 +84,42 @@ fn pat_to_str(&@ast::pat p) -> str {
ret writer.get_str();
}
fn word_nbsp(ps s, str word) {
wrd(s.s, word);
wrd(s.s, " ");
fn word_nbsp(ps s, str w) {
word(s.s, w);
word(s.s, " ");
}
fn word_space(ps s, str word) {
wrd(s.s, word);
fn word_space(ps s, str w) {
word(s.s, w);
space(s.s);
}
fn popen(ps s) {
wrd(s.s, "(");
word(s.s, "(");
}
fn pclose(ps s) {
wrd(s.s, ")");
word(s.s, ")");
}
fn head(ps s, str word) {
fn head(ps s, str w) {
// outer-box is consistent
cbox(s.s, indent_unit);
// head-box is inconsistent
ibox(s.s, str::char_len(word) + 1u);
ibox(s.s, str::char_len(w) + 1u);
// keyword that starts the head
word_nbsp(s, word);
word_nbsp(s, w);
}
fn bopen(ps s) {
wrd(s.s, "{");
word(s.s, "{");
end(s.s); // close the head-box
}
fn bclose(ps s, common::span span) {
maybe_print_comment(s, span.hi);
break_offset(s.s, 1u, -(indent_unit as int));
wrd(s.s, "}");
word(s.s, "}");
end(s.s); // close the outer-box
}
@ -141,7 +143,7 @@ fn commasep_cmnt[IN](ps s, breaks b, vec[IN] elts, fn(ps, &IN) op,
op(s, elt);
i += 1u;
if (i < len) {
wrd(s.s, ",");
word(s.s, ",");
if (!maybe_print_line_comment(s, get_span(elt))) {space(s.s);}
}
}
@ -172,41 +174,41 @@ fn print_type(ps s, &@ast::ty ty) {
maybe_print_comment(s, ty.span.lo);
ibox(s.s, 0u);
alt (ty.node) {
case (ast::ty_nil) {wrd(s.s, "()");}
case (ast::ty_bool) {wrd(s.s, "bool");}
case (ast::ty_bot) {wrd(s.s, "_|_");}
case (ast::ty_int) {wrd(s.s, "int");}
case (ast::ty_uint) {wrd(s.s, "uint");}
case (ast::ty_float) {wrd(s.s, "float");}
case (ast::ty_machine(?tm)) {wrd(s.s, common::ty_mach_to_str(tm));}
case (ast::ty_char) {wrd(s.s, "char");}
case (ast::ty_str) {wrd(s.s, "str");}
case (ast::ty_box(?mt)) {wrd(s.s, "@"); print_mt(s, mt);}
case (ast::ty_nil) {word(s.s, "()");}
case (ast::ty_bool) {word(s.s, "bool");}
case (ast::ty_bot) {word(s.s, "_|_");}
case (ast::ty_int) {word(s.s, "int");}
case (ast::ty_uint) {word(s.s, "uint");}
case (ast::ty_float) {word(s.s, "float");}
case (ast::ty_machine(?tm)) {word(s.s, common::ty_mach_to_str(tm));}
case (ast::ty_char) {word(s.s, "char");}
case (ast::ty_str) {word(s.s, "str");}
case (ast::ty_box(?mt)) {word(s.s, "@"); print_mt(s, mt);}
case (ast::ty_vec(?mt)) {
wrd(s.s, "vec["); print_mt(s, mt); wrd(s.s, "]");
word(s.s, "vec["); print_mt(s, mt); word(s.s, "]");
}
case (ast::ty_port(?t)) {
wrd(s.s, "port["); print_type(s, t); wrd(s.s, "]");
word(s.s, "port["); print_type(s, t); word(s.s, "]");
}
case (ast::ty_chan(?t)) {
wrd(s.s, "chan["); print_type(s, t); wrd(s.s, "]");
word(s.s, "chan["); print_type(s, t); word(s.s, "]");
}
case (ast::ty_type) {wrd(s.s, "type");}
case (ast::ty_type) {word(s.s, "type");}
case (ast::ty_tup(?elts)) {
wrd(s.s, "tup");
word(s.s, "tup");
popen(s);
auto f = print_mt;
commasep[ast::mt](s, inconsistent, elts, f);
pclose(s);
}
case (ast::ty_rec(?fields)) {
wrd(s.s, "rec");
word(s.s, "rec");
popen(s);
fn print_field(ps s, &ast::ty_field f) {
cbox(s.s, indent_unit);
print_mt(s, f.mt);
space(s.s);
wrd(s.s, f.ident);
word(s.s, f.ident);
end(s.s);
}
fn get_span(&ast::ty_field f) -> common::span {
@ -227,7 +229,7 @@ fn print_type(ps s, &@ast::ty ty) {
cbox(s.s, indent_unit);
print_ty_fn(s, m.proto, option::some[str](m.ident),
m.inputs, m.output, m.cf);
wrd(s.s, ";");
word(s.s, ";");
end(s.s);
}
bclose(s, ty.span);
@ -255,12 +257,12 @@ fn print_item(ps s, @ast::item item) {
end(s.s); // end the head-ibox
word_space(s, "=");
print_expr(s, expr);
wrd(s.s, ";");
word(s.s, ";");
end(s.s); // end the outer cbox
}
case (ast::item_fn(?name,?_fn,?typarams,_,_)) {
print_fn(s, _fn.decl, name, typarams);
wrd(s.s, " ");
word(s.s, " ");
print_block(s, _fn.body);
}
case (ast::item_mod(?id,?_mod,_)) {
@ -287,7 +289,7 @@ fn print_item(ps s, @ast::item item) {
alt (item.node) {
case (ast::native_item_ty(?id,_)) {
word_nbsp(s, "type");
wrd(s.s, id);
word(s.s, id);
}
case (ast::native_item_fn(?id,?lname,?decl,
?typarams,_,_)) {
@ -301,7 +303,7 @@ fn print_item(ps s, @ast::item item) {
}
}
}
wrd(s.s, ";");
word(s.s, ";");
end(s.s);
}
bclose(s, item.span);
@ -310,26 +312,26 @@ fn print_item(ps s, @ast::item item) {
ibox(s.s, indent_unit);
ibox(s.s, 0u);
word_nbsp(s, "type");
wrd(s.s, id);
word(s.s, id);
print_type_params(s, params);
end(s.s); // end the inner ibox
space(s.s);
word_space(s, "=");
print_type(s, ty);
wrd(s.s, ";");
word(s.s, ";");
end(s.s); // end the outer ibox
break_offset(s.s, 0u, 0);
}
case (ast::item_tag(?id,?variants,?params,_,_)) {
head(s, "tag");
wrd(s.s, id);
word(s.s, id);
print_type_params(s, params);
space(s.s);
bopen(s);
for (ast::variant v in variants) {
space(s.s);
maybe_print_comment(s, v.span.lo);
wrd(s.s, v.node.name);
word(s.s, v.node.name);
if (vec::len[ast::variant_arg](v.node.args) > 0u) {
popen(s);
fn print_variant_arg(ps s, &ast::variant_arg arg) {
@ -339,21 +341,21 @@ fn print_item(ps s, @ast::item item) {
commasep[ast::variant_arg](s, consistent, v.node.args, f);
pclose(s);
}
wrd(s.s, ";");
word(s.s, ";");
maybe_print_line_comment(s, v.span);
}
bclose(s, item.span);
}
case (ast::item_obj(?id,?_obj,?params,_,_)) {
head(s, "obj");
wrd(s.s, id);
word(s.s, id);
print_type_params(s, params);
popen(s);
fn print_field(ps s, &ast::obj_field field) {
ibox(s.s, indent_unit);
print_type(s, field.ty);
space(s.s);
wrd(s.s, field.ident);
word(s.s, field.ident);
end(s.s);
}
fn get_span(&ast::obj_field f) -> common::span {ret f.ty.span;}
@ -368,7 +370,7 @@ fn print_item(ps s, @ast::item item) {
hardbreak(s.s);
maybe_print_comment(s, meth.span.lo);
print_fn(s, meth.node.meth.decl, meth.node.ident, typarams);
wrd(s.s, " ");
word(s.s, " ");
print_block(s, meth.node.meth.body);
}
alt (_obj.dtor) {
@ -398,7 +400,7 @@ fn print_block(ps s, ast::block blk) {
print_expr(s, expr);
}
}
if (front::parser::stmt_ends_with_semi(st)) {wrd(s.s, ";");}
if (front::parser::stmt_ends_with_semi(st)) {word(s.s, ";");}
maybe_print_line_comment(s, st.span);
}
alt (blk.node.expr) {
@ -417,30 +419,30 @@ fn print_literal(ps s, @ast::lit lit) {
alt (lit.node) {
case (ast::lit_str(?st)) {print_string(s, st);}
case (ast::lit_char(?ch)) {
wrd(s.s, "'" + escape_str(str::from_bytes([ch as u8]), '\'')
word(s.s, "'" + escape_str(str::from_bytes([ch as u8]), '\'')
+ "'");
}
case (ast::lit_int(?val)) {
wrd(s.s, common::istr(val));
word(s.s, common::istr(val));
}
case (ast::lit_uint(?val)) { // FIXME clipping? uistr?
wrd(s.s, common::istr(val as int) + "u");
word(s.s, common::istr(val as int) + "u");
}
case (ast::lit_float(?fstr)) {
wrd(s.s, fstr);
word(s.s, fstr);
}
case (ast::lit_mach_int(?mach,?val)) {
wrd(s.s, common::istr(val as int));
wrd(s.s, common::ty_mach_to_str(mach));
word(s.s, common::istr(val as int));
word(s.s, common::ty_mach_to_str(mach));
}
case (ast::lit_mach_float(?mach,?val)) {
// val is already a str
wrd(s.s, val);
wrd(s.s, common::ty_mach_to_str(mach));
word(s.s, val);
word(s.s, common::ty_mach_to_str(mach));
}
case (ast::lit_nil) {wrd(s.s, "()");}
case (ast::lit_nil) {word(s.s, "()");}
case (ast::lit_bool(?val)) {
if (val) {wrd(s.s, "true");} else {wrd(s.s, "false");}
if (val) {word(s.s, "true");} else {word(s.s, "false");}
}
}
}
@ -460,9 +462,9 @@ fn print_expr(ps s, &@ast::expr expr) {
word_nbsp(s, "mutable");
}
ibox(s.s, indent_unit);
wrd(s.s, "[");
word(s.s, "[");
commasep_exprs(s, inconsistent, exprs);
wrd(s.s, "]");
word(s.s, "]");
end(s.s);
}
case (ast::expr_tup(?exprs,_)) {
@ -473,7 +475,7 @@ fn print_expr(ps s, &@ast::expr expr) {
end(s.s);
}
fn get_span(&ast::elt elt) -> common::span {ret elt.expr.span;}
wrd(s.s, "tup");
word(s.s, "tup");
popen(s);
auto f = printElt;
auto gs = get_span;
@ -484,15 +486,15 @@ fn print_expr(ps s, &@ast::expr expr) {
fn print_field(ps s, &ast::field field) {
ibox(s.s, indent_unit);
if (field.mut == ast::mut) {word_nbsp(s, "mutable");}
wrd(s.s, field.ident);
wrd(s.s, "=");
word(s.s, field.ident);
word(s.s, "=");
print_expr(s, field.expr);
end(s.s);
}
fn get_span(&ast::field field) -> common::span {
ret field.expr.span;
}
wrd(s.s, "rec");
word(s.s, "rec");
popen(s);
auto f = print_field;
auto gs = get_span;
@ -516,7 +518,7 @@ fn print_expr(ps s, &@ast::expr expr) {
pclose(s);
}
case (ast::expr_self_method(?ident,_)) {
wrd(s.s, "self.");
word(s.s, "self.");
print_ident(s, ident);
}
case (ast::expr_bind(?func,?args,_)) {
@ -525,7 +527,7 @@ fn print_expr(ps s, &@ast::expr expr) {
case (option::some[@ast::expr](?expr)) {
print_expr(s, expr);
}
case (_) {wrd(s.s, "_");}
case (_) {word(s.s, "_");}
}
}
word_nbsp(s, "bind");
@ -550,7 +552,7 @@ fn print_expr(ps s, &@ast::expr expr) {
print_maybe_parens(s, rhs, prec + 1);
}
case (ast::expr_unary(?op,?expr,_)) {
wrd(s.s, ast::unop_to_str(op));
word(s.s, ast::unop_to_str(op));
print_expr(s, expr);
}
case (ast::expr_lit(?lit,_)) {
@ -576,7 +578,7 @@ fn print_expr(ps s, &@ast::expr expr) {
// wrong column.
cbox(s.s, indent_unit-1u);
ibox(s.s, 0u);
wrd(s.s, " else ");
word(s.s, " else ");
alt (_else.node) {
case (ast::expr_block(?b, _)) {
print_block(s, block);
@ -658,7 +660,7 @@ fn print_expr(ps s, &@ast::expr expr) {
case (ast::expr_assign_op(?op,?lhs,?rhs,_)) {
print_expr(s, lhs);
space(s.s);
wrd(s.s, ast::binop_to_str(op));
word(s.s, ast::binop_to_str(op));
word_space(s, "=");
print_expr(s, rhs);
}
@ -676,12 +678,12 @@ fn print_expr(ps s, &@ast::expr expr) {
}
case (ast::expr_field(?expr,?id,_)) {
print_expr(s, expr);
wrd(s.s, ".");
wrd(s.s, id);
word(s.s, ".");
word(s.s, id);
}
case (ast::expr_index(?expr,?index,_)) {
print_expr(s, expr);
wrd(s.s, ".");
word(s.s, ".");
popen(s);
print_expr(s, index);
pclose(s);
@ -690,29 +692,29 @@ fn print_expr(ps s, &@ast::expr expr) {
print_path(s, path);
}
case (ast::expr_fail(_)) {
wrd(s.s, "fail");
word(s.s, "fail");
}
case (ast::expr_break(_)) {
wrd(s.s, "break");
word(s.s, "break");
}
case (ast::expr_cont(_)) {
wrd(s.s, "cont");
word(s.s, "cont");
}
case (ast::expr_ret(?result,_)) {
wrd(s.s, "ret");
word(s.s, "ret");
alt (result) {
case (option::some[@ast::expr](?expr)) {
wrd(s.s, " ");
word(s.s, " ");
print_expr(s, expr);
}
case (_) {}
}
}
case (ast::expr_put(?result,_)) {
wrd(s.s, "put");
word(s.s, "put");
alt (result) {
case (option::some[@ast::expr](?expr)) {
wrd(s.s, " ");
word(s.s, " ");
print_expr(s, expr);
}
case (_) {}
@ -742,7 +744,7 @@ fn print_expr(ps s, &@ast::expr expr) {
pclose(s);
}
case (ast::expr_ext(?path, ?args, ?body, _, _)) {
wrd(s.s, "#");
word(s.s, "#");
print_path(s, path);
if (vec::len[@ast::expr](args) > 0u) {
popen(s);
@ -752,19 +754,19 @@ fn print_expr(ps s, &@ast::expr expr) {
// FIXME: extension 'body'
}
case (ast::expr_port(_)) {
wrd(s.s, "port");
word(s.s, "port");
popen(s);
pclose(s);
}
case (ast::expr_chan(?expr, _)) {
wrd(s.s, "chan");
word(s.s, "chan");
popen(s);
print_expr(s, expr);
pclose(s);
}
case (ast::expr_anon_obj(_,_,_,_)) {
wrd(s.s, "anon obj");
word(s.s, "anon obj");
// TODO: nicer pretty-printing of anon objs
}
}
@ -774,9 +776,9 @@ fn print_expr(ps s, &@ast::expr expr) {
case (mo_untyped) { /* no-op */ }
case (mo_typed(?tcx)) {
space(s.s);
wrd(s.s, "as");
word(s.s, "as");
space(s.s);
wrd(s.s, ty::ty_to_str(tcx, ty::expr_ty(tcx, expr)));
word(s.s, ty::ty_to_str(tcx, ty::expr_ty(tcx, expr)));
pclose(s);
}
}
@ -810,7 +812,7 @@ fn print_decl(ps s, @ast::decl decl) {
}
}
}
wrd(s.s, loc.ident);
word(s.s, loc.ident);
alt (loc.init) {
case (option::some[ast::initializer](?init)) {
space(s.s);
@ -835,7 +837,7 @@ fn print_decl(ps s, @ast::decl decl) {
}
fn print_ident(ps s, ast::ident ident) {
wrd(s.s, ident);
word(s.s, ident);
}
fn print_for_decl(ps s, @ast::decl decl) {
@ -843,7 +845,7 @@ fn print_for_decl(ps s, @ast::decl decl) {
case (ast::decl_local(?loc)) {
print_type(s, option::get[@ast::ty](loc.ty));
space(s.s);
wrd(s.s, loc.ident);
word(s.s, loc.ident);
}
}
}
@ -853,22 +855,22 @@ fn print_path(ps s, ast::path path) {
auto first = true;
for (str id in path.node.idents) {
if (first) {first = false;}
else {wrd(s.s, "::");}
wrd(s.s, id);
else {word(s.s, "::");}
word(s.s, id);
}
if (vec::len[@ast::ty](path.node.types) > 0u) {
wrd(s.s, "[");
word(s.s, "[");
auto f = print_type;
commasep[@ast::ty](s, inconsistent, path.node.types, f);
wrd(s.s, "]");
word(s.s, "]");
}
}
fn print_pat(ps s, &@ast::pat pat) {
maybe_print_comment(s, pat.span.lo);
alt (pat.node) {
case (ast::pat_wild(_)) {wrd(s.s, "_");}
case (ast::pat_bind(?id,_,_)) {wrd(s.s, "?" + id);}
case (ast::pat_wild(_)) {word(s.s, "_");}
case (ast::pat_bind(?id,_,_)) {word(s.s, "?" + id);}
case (ast::pat_lit(?lit,_)) {print_literal(s, lit);}
case (ast::pat_tag(?path,?args,_)) {
print_path(s, path);
@ -892,15 +894,15 @@ fn print_fn(ps s, ast::fn_decl decl, str name,
head(s, "pred");
}
}
wrd(s.s, name);
word(s.s, name);
print_type_params(s, typarams);
popen(s);
fn print_arg(ps s, &ast::arg x) {
ibox(s.s, indent_unit);
if (x.mode == ast::alias) {wrd(s.s, "&");}
if (x.mode == ast::alias) {word(s.s, "&");}
print_type(s, x.ty);
space(s.s);
wrd(s.s, x.ident);
word(s.s, x.ident);
end(s.s);
}
auto f = print_arg;
@ -916,13 +918,13 @@ fn print_fn(ps s, ast::fn_decl decl, str name,
fn print_type_params(ps s, vec[ast::ty_param] params) {
if (vec::len[ast::ty_param](params) > 0u) {
wrd(s.s, "[");
word(s.s, "[");
fn printParam(ps s, &ast::ty_param param) {
wrd(s.s, param);
word(s.s, param);
}
auto f = printParam;
commasep[ast::ty_param](s, inconsistent, params, f);
wrd(s.s, "]");
word(s.s, "]");
}
}
@ -932,7 +934,7 @@ fn print_view_item(ps s, @ast::view_item item) {
alt (item.node) {
case (ast::view_item_use(?id,?mta,_,_)) {
head(s, "use");
wrd(s.s, id);
word(s.s, id);
if (vec::len[@ast::meta_item](mta) > 0u) {
popen(s);
fn print_meta(ps s, &@ast::meta_item item) {
@ -956,16 +958,16 @@ fn print_view_item(ps s, @ast::view_item item) {
auto first = true;
for (str elt in ids) {
if (first) {first = false;}
else {wrd(s.s, "::");}
wrd(s.s, elt);
else {word(s.s, "::");}
word(s.s, elt);
}
}
case (ast::view_item_export(?id)) {
head(s, "export");
wrd(s.s, id);
word(s.s, id);
}
}
wrd(s.s, ";");
word(s.s, ";");
end(s.s); // end inner head-block
end(s.s); // end outer head-block
}
@ -1028,21 +1030,21 @@ fn print_mt(ps s, &ast::mt mt) {
}
fn print_string(ps s, str st) {
wrd(s.s, "\""); wrd(s.s, escape_str(st, '"')); wrd(s.s, "\"");
word(s.s, "\""); word(s.s, escape_str(st, '"')); word(s.s, "\"");
}
fn print_ty_fn(ps s, ast::proto proto, option::t[str] id,
vec[ast::ty_arg] inputs, @ast::ty output,
ast::controlflow cf) {
if (proto == ast::proto_fn) {wrd(s.s, "fn");}
else {wrd(s.s, "iter");}
if (proto == ast::proto_fn) {word(s.s, "fn");}
else {word(s.s, "iter");}
alt (id) {
case (option::some[str](?id)) {space(s.s); wrd(s.s, id);}
case (option::some[str](?id)) {space(s.s); word(s.s, id);}
case (_) {}
}
popen(s);
fn print_arg(ps s, &ast::ty_arg input) {
if (input.mode == ast::alias) {wrd(s.s, "&");}
if (input.mode == ast::alias) {word(s.s, "&");}
print_type(s, input.ty);
}
auto f = print_arg;
@ -1086,7 +1088,7 @@ fn maybe_print_comment(ps s, uint pos) {
first = false;
break_offset(s.s, 0u, 0);
}
print_comment(s, cmnt.val);
print_comment(s, cmnt);
s.cur_cmnt += 1u;
} else { break; }
}
@ -1099,8 +1101,8 @@ fn maybe_print_line_comment(ps s, common::span span) -> bool {
alt (next_comment(s)) {
case (option::some[lexer::cmnt](?cmnt)) {
if (span.hi + 4u >= cmnt.pos) {
wrd(s.s, " ");
print_comment(s, cmnt.val);
word(s.s, " ");
print_comment(s, cmnt);
s.cur_cmnt += 1u;
ret true;
}
@ -1111,15 +1113,10 @@ fn maybe_print_line_comment(ps s, common::span span) -> bool {
}
fn print_remaining_comments(ps s) {
auto first = true;
while (true) {
alt (next_comment(s)) {
case (option::some[lexer::cmnt](?cmnt)) {
if (first) {
first = false;
break_offset(s.s, 0u, 0);
}
print_comment(s, cmnt.val);
print_comment(s, cmnt);
s.cur_cmnt += 1u;
}
case (_) {break;}
@ -1127,27 +1124,30 @@ fn print_remaining_comments(ps s) {
}
}
fn print_comment(ps s, lexer::cmnt_ cmnt) {
alt (cmnt) {
case (lexer::cmnt_line(?val)) {
wrd(s.s, "// " + val);
hardbreak(s.s);
}
case (lexer::cmnt_block(?lines)) {
cbox(s.s, 1u);
wrd(s.s, "/*");
auto first = true;
for (str ln in lines) {
if (first) {
first = false;
} else {
hardbreak(s.s);
}
wrd(s.s, ln);
fn print_comment(ps s, lexer::cmnt cmnt) {
alt (cmnt.style) {
case (lexer::isolated) {
cbox(s.s, 0u);
for (str line in cmnt.lines) {
zerobreak(s.s);
word_and_eol(s.s, line);
}
wrd(s.s, "*/");
zerobreak(s.s);
end(s.s);
hardbreak(s.s);
}
case (lexer::trailing) {
cbox(s.s, 0u);
for (str line in cmnt.lines) {
word_and_eol(s.s, line);
zerobreak(s.s);
}
end(s.s);
}
case (lexer::mixed) {
assert vec::len(cmnt.lines) == 1u;
zerobreak(s.s);
word(s.s, cmnt.lines.(0));
zerobreak(s.s);
}
}
}