aboutsummaryrefslogtreecommitdiff
path: root/src/comp/pretty/pp.rs
diff options
context:
space:
mode:
authorMarijn Haverbeke <[email protected]>2011-03-24 16:33:20 +0100
committerGraydon Hoare <[email protected]>2011-03-31 14:41:39 +0000
commite7e6f396d888574e7184119818ac3300f10aacbf (patch)
tree143c2c918a5123d6ed07b8ee61909981d3aa47e5 /src/comp/pretty/pp.rs
parentTweak build command on rustc. (diff)
downloadrust-e7e6f396d888574e7184119818ac3300f10aacbf.tar.xz
rust-e7e6f396d888574e7184119818ac3300f10aacbf.zip
Preserve comments when pretty-printing.
The patch also includes a number of smaller fixes to the pretty-printer that were encountered on the way.
Diffstat (limited to 'src/comp/pretty/pp.rs')
-rw-r--r--src/comp/pretty/pp.rs221
1 files changed, 131 insertions, 90 deletions
diff --git a/src/comp/pretty/pp.rs b/src/comp/pretty/pp.rs
index 69eb01bc..b7b0c64a 100644
--- a/src/comp/pretty/pp.rs
+++ b/src/comp/pretty/pp.rs
@@ -4,9 +4,11 @@ import std._str;
tag boxtype {box_h; box_v; box_hv; box_align;}
tag contexttype {cx_h; cx_v;}
+tag scantype {scan_hv; scan_h; scan_none;}
tag token {
brk(uint);
+ hardbrk;
word(str);
cword(str); // closing token
open(boxtype, uint);
@@ -18,29 +20,45 @@ type context = rec(contexttype tp, uint indent);
type ps = @rec(mutable vec[context] context,
uint width,
io.writer out,
- mutable vec[token] buffered,
- mutable uint scandepth,
- mutable uint bufferedcol,
mutable uint col,
- mutable bool start_of_line);
+ mutable uint spaces,
+ mutable vec[token] buffered,
+ mutable scantype scanning,
+ mutable vec[boxtype] scandepth,
+ mutable uint scancol,
+ mutable bool start_of_line,
+ mutable bool start_of_box,
+ mutable bool potential_brk);
fn mkstate(io.writer out, uint width) -> ps {
let vec[context] stack = vec(rec(tp=cx_v, indent=0u));
let vec[token] buff = vec();
+ let vec[boxtype] sd = vec();
ret @rec(mutable context=stack,
width=width,
out=out,
- mutable buffered=buff,
- mutable scandepth=0u,
- mutable bufferedcol=0u,
mutable col=0u,
- mutable start_of_line=true);
+ mutable spaces=0u,
+ mutable buffered=buff,
+ mutable scanning=scan_none,
+ mutable scandepth=sd,
+ mutable scancol=0u,
+ mutable start_of_line=true,
+ mutable start_of_box=true,
+ mutable potential_brk=false);
+}
+
+impure fn write_spaces(ps p, uint i) {
+ while (i > 0u) {
+ i -= 1u;
+ p.out.write_str(" ");
+ }
}
impure fn push_context(ps p, contexttype tp, uint indent) {
before_print(p, false);
- _vec.push[context](p.context, rec(tp=tp, indent=base_indent(p)
- + indent));
+ _vec.push[context](p.context, rec(tp=tp, indent=indent));
+ p.start_of_box = true;
}
fn pop_context(ps p) {
@@ -49,15 +67,13 @@ fn pop_context(ps p) {
impure fn add_token(ps p, token tok) {
if (p.width == 0u) {direct_token(p, tok);}
- else if (p.scandepth == 0u) {do_token(p, tok);}
+ else if (p.scanning == scan_none) {do_token(p, tok);}
else {buffer_token(p, tok);}
}
impure fn direct_token(ps p, token tok) {
alt (tok) {
- case (brk(?sz)) {
- while (sz > 0u) {p.out.write_str(" "); sz -= 1u;}
- }
+ case (brk(?sz)) {write_spaces(p, sz);}
case (word(?w)) {p.out.write_str(w);}
case (cword(?w)) {p.out.write_str(w);}
case (_) {}
@@ -66,78 +82,75 @@ impure fn direct_token(ps p, token tok) {
impure fn buffer_token(ps p, token tok) {
p.buffered += vec(tok);
- p.bufferedcol += token_size(tok);
- alt (p.buffered.(0)) {
- case (brk(_)) {
- alt (tok) {
- case (brk(_)) {
- if (p.scandepth == 1u) {finish_break_scan(p);}
+ auto col = p.scancol;
+ p.scancol = col + token_size(tok);
+ if (p.scancol > p.width) {
+ finish_scan(p, false);
+ } else {
+ alt (tok) {
+ case (open(?tp,_)) {
+ _vec.push[boxtype](p.scandepth, tp);
+ if (p.scanning == scan_h) {
+ if (tp == box_h) {
+ check_potential_brk(p);
+ }
}
- case (open(box_h,_)) {p.scandepth += 1u;}
- case (open(_,_)) {finish_break_scan(p);}
- case (close) {
- p.scandepth -= 1u;
- if (p.scandepth == 0u) {finish_break_scan(p);}
+ }
+ case (close) {
+ _vec.pop[boxtype](p.scandepth);
+ if (_vec.len[boxtype](p.scandepth) == 0u) {
+ finish_scan(p, true);
}
- case (_) {}
}
- }
- case (open(_,_)) {
- if (p.bufferedcol > p.width) {finish_block_scan(p, cx_v);}
- else {
- alt (tok) {
- case (open(_,_)) {p.scandepth += 1u;}
- case (close) {
- p.scandepth -= 1u;
- if (p.scandepth == 0u) {finish_block_scan(p, cx_h);}
+ case (brk(_)) {
+ if (p.scanning == scan_h) {
+ if (p.scandepth.(_vec.len[boxtype](p.scandepth)-1u) == box_v) {
+ finish_scan(p, true);
}
- case (_) {}
}
}
+ case (_) {}
}
}
}
-impure fn finish_block_scan(ps p, contexttype tp) {
+impure fn check_potential_brk(ps p) {
+ for (boxtype tp in p.scandepth) {
+ if (tp != box_h) {ret;}
+ }
+ p.potential_brk = true;
+}
+
+impure fn finish_scan(ps p, bool fits) {
auto buf = p.buffered;
auto front = _vec.shift[token](buf);
- auto indent;
- alt (front){
- case (open(box_hv,?ind)) {
- indent = ind;
+ auto chosen_tp = cx_h;
+ if (!fits) {chosen_tp = cx_v;}
+ alt (front) {
+ case (open(box_hv, ?ind)) {
+ push_context(p, chosen_tp, base_indent(p) + ind);
}
case (open(box_align, _)) {
- indent = p.col - base_indent(p);
+ push_context(p, chosen_tp, p.col);
+ }
+ case (open(box_h, ?ind)) {
+ if (!fits && !p.start_of_box && !p.start_of_line && !p.potential_brk) {
+ line_break(p);
+ }
+ push_context(p, cx_h, base_indent(p) + ind);
}
}
- p.scandepth = 0u;
- p.buffered = vec();
- push_context(p, tp, indent);
+ p.scandepth = vec();
+ p.scanning = scan_none;
for (token t in buf) { add_token(p, t); }
}
-impure fn finish_break_scan(ps p) {
- auto buf = p.buffered;
- auto front = _vec.shift[token](buf);
- if (p.bufferedcol > p.width) {
- line_break(p);
- }
- else {
- auto width;
- alt (front) {case(brk(?w)) {width = w;}}
- auto i = 0u;
- while (i < width) {p.out.write_str(" "); i+=1u;}
- p.col += width;
- }
- p.scandepth = 0u;
+impure fn start_scan(ps p, token tok, scantype tp) {
p.buffered = vec();
- for (token t in buf) { add_token(p, t); }
-}
-
-impure fn start_scan(ps p, token tok) {
- p.buffered = vec(tok);
- p.scandepth = 1u;
- p.bufferedcol = p.col;
+ p.scancol = p.col;
+ p.scanning = tp;
+ buffer_token(p, tok);
+ p.potential_brk = false;
}
fn cur_context(ps p) -> context {
@@ -152,64 +165,91 @@ fn base_indent(ps p) -> uint {
}
}
+fn cx_is(contexttype a, contexttype b) -> bool {
+ if (a == b) {ret true;}
+ else {ret false;}
+}
+fn box_is(boxtype a, boxtype b) -> bool {
+ if (a == b) {ret true;}
+ else {ret false;}
+}
+
impure fn do_token(ps p, token tok) {
+ auto start_of_box = p.start_of_box;
+ p.start_of_box = false;
alt (tok) {
case (brk(?sz)) {
- alt (cur_context(p).tp) {
- case (cx_h) {
- before_print(p, false);
- start_scan(p, tok);
- }
- case (cx_v) {
- line_break(p);
- }
+ if (cx_is(cur_context(p).tp, cx_v) || sz + p.col > p.width) {
+ line_break(p);
+ }
+ else {
+ p.spaces += sz;
}
}
+ case (hardbrk) {
+ line_break(p);
+ }
case (word(?w)) {
+ auto len = _str.char_len(w);
+ if (len + p.col + p.spaces > p.width && !start_of_box &&
+ !p.start_of_line) {
+ line_break(p);
+ }
before_print(p, false);
p.out.write_str(w);
- p.col += _str.byte_len(w); // TODO char_len
+ p.col += len;
}
case (cword(?w)) {
before_print(p, true);
p.out.write_str(w);
- p.col += _str.byte_len(w); // TODO char_len
+ p.col += _str.char_len(w);
}
case (open(?tp, ?indent)) {
- alt (tp) {
- case (box_hv) {start_scan(p, tok);}
- case (box_align) {start_scan(p, tok);}
- case (box_h) {push_context(p, cx_h, indent);}
- case (box_v) {push_context(p, cx_v, indent);}
+ if (tp == box_v) {
+ push_context(p, cx_v, base_indent(p) + indent);
+ } else if (box_is(tp, box_h) && cx_is(cur_context(p).tp, cx_v)) {
+ push_context(p, cx_h, base_indent(p) + indent);
+ } else if (tp == box_h) {
+ p.start_of_box = start_of_box;
+ start_scan(p, tok, scan_h);
+ } else {
+ p.start_of_box = start_of_box;
+ start_scan(p, tok, scan_hv);
}
}
- case (close) {pop_context(p);}
+ case (close) {
+ pop_context(p);
+ }
}
}
impure fn line_break(ps p) {
p.out.write_str("\n");
p.col = 0u;
+ p.spaces = cur_context(p).indent;
p.start_of_line = true;
}
impure fn before_print(ps p, bool closing) {
if (p.start_of_line) {
p.start_of_line = false;
- auto ind;
- if (closing) {ind = base_indent(p);}
- else {ind = cur_context(p).indent;}
- p.col = ind;
- while (ind > 0u) {p.out.write_str(" "); ind -= 1u;}
+ if (closing) {p.spaces = base_indent(p);}
+ else {p.spaces = cur_context(p).indent;}
+ }
+ if (p.spaces > 0u) {
+ write_spaces(p, p.spaces);
+ p.col += p.spaces;
+ p.spaces = 0u;
}
}
fn token_size(token tok) -> uint {
alt (tok) {
case (brk(?sz)) {ret sz;}
- case (word(?w)) {ret _str.byte_len(w);}
- case (cword(?w)) {ret _str.byte_len(w);}
- case (open(_, _)) {ret 0u;} // TODO exception for V blocks?
+ case (hardbrk) {ret 0xFFFFFFu;}
+ case (word(?w)) {ret _str.char_len(w);}
+ case (cword(?w)) {ret _str.char_len(w);}
+ case (open(_, _)) {ret 0u;}
case (close) {ret 0u;}
}
}
@@ -224,3 +264,4 @@ impure fn cwrd(ps p, str wrd) {add_token(p, cword(wrd));}
impure fn space(ps p) {add_token(p, brk(1u));}
impure fn spaces(ps p, uint n) {add_token(p, brk(n));}
impure fn line(ps p) {add_token(p, brk(0u));}
+impure fn hardbreak(ps p) {add_token(p, hardbrk);}