61 private def force_nat(i: Int): Int = i max 0 |
61 private def force_nat(i: Int): Int = i max 0 |
62 |
62 |
63 type Markup_Body = (Markup, Option[XML.Body]) |
63 type Markup_Body = (Markup, Option[XML.Body]) |
64 val no_markup: Markup_Body = (Markup.Empty, None) |
64 val no_markup: Markup_Body = (Markup.Empty, None) |
65 val item_markup: Markup_Body = (Markup.Expression.item, None) |
65 val item_markup: Markup_Body = (Markup.Expression.item, None) |
66 |
|
67 def markup_elem(markup: Markup_Body, body: XML.Body): XML.Elem = |
|
68 markup match { |
|
69 case (m, None) => XML.Elem(m, body) |
|
70 case (m1, Some(m2)) => XML.Wrapped_Elem(m1, m2, body) |
|
71 } |
|
72 |
66 |
73 private sealed abstract class Tree { def length: Double } |
67 private sealed abstract class Tree { def length: Double } |
74 private case object End extends Tree { |
68 private case object End extends Tree { |
75 override def length: Double = 0.0 |
69 override def length: Double = 0.0 |
76 } |
70 } |
129 output_content(pure, unbreakable(input)) |
123 output_content(pure, unbreakable(input)) |
130 |
124 |
131 |
125 |
132 /* formatting */ |
126 /* formatting */ |
133 |
127 |
134 private type State = List[(Markup_Body, List[XML.Tree])] |
128 private sealed abstract class Tree_Buffer { def result: XML.Tree } |
135 private val init_state: State = List((no_markup, Nil)) |
129 private case class Elem_Buffer(markup: Markup_Body, body: XML.Body) extends Tree_Buffer { |
|
130 def result: XML.Elem = |
|
131 markup match { |
|
132 case (m, None) => XML.Elem(m, body) |
|
133 case (m1, Some(m2)) => XML.Wrapped_Elem(m1, m2, body) |
|
134 } |
|
135 } |
|
136 private case class Text_Buffer(buffer: List[String]) extends Tree_Buffer { |
|
137 def result: XML.Text = XML.Text(buffer.reverse.mkString) |
|
138 |
|
139 def add(s: String): Text_Buffer = |
|
140 if (s.isEmpty) this else copy(buffer = s :: buffer) |
|
141 } |
|
142 |
|
143 private case class Result_Buffer( |
|
144 markup: Markup_Body = no_markup, |
|
145 buffer: List[Tree_Buffer] = Nil |
|
146 ) { |
|
147 def result_body: XML.Body = buffer.foldLeft[XML.Body](Nil)((res, t) => t.result :: res) |
|
148 def result_elem: Elem_Buffer = Elem_Buffer(markup, result_body) |
|
149 |
|
150 def add(elem: Elem_Buffer): Result_Buffer = copy(buffer = elem :: buffer) |
|
151 |
|
152 def string(s: String): Result_Buffer = |
|
153 if (s.isEmpty) this |
|
154 else { |
|
155 buffer match { |
|
156 case (text: Text_Buffer) :: ts => copy(buffer = text.add(s) :: ts) |
|
157 case _ => copy(buffer = Text_Buffer(List(s)) :: buffer) |
|
158 } |
|
159 } |
|
160 } |
|
161 |
|
162 private type State = List[Result_Buffer] |
|
163 private val init_state: State = List(Result_Buffer()) |
136 |
164 |
137 private sealed case class Text( |
165 private sealed case class Text( |
138 state: State = init_state, |
166 state: State = init_state, |
139 pos: Double = 0.0, |
167 pos: Double = 0.0, |
140 nl: Int = 0 |
168 nl: Int = 0 |
141 ) { |
169 ) { |
142 def add(t: XML.Tree, len: Double = 0.0): Text = |
170 def add(elem: Elem_Buffer): Text = |
143 (state: @unchecked) match { |
171 (state: @unchecked) match { |
144 case (m, ts) :: rest => copy(state = (m, t :: ts) :: rest, pos = pos + len) |
172 case res :: rest => copy(state = res.add(elem) :: rest) |
145 } |
173 } |
146 |
174 |
147 def push(m: Markup_Body): Text = |
175 def push(m: Markup_Body): Text = |
148 copy(state = (m, Nil) :: state) |
176 copy(state = Result_Buffer(markup = m) :: state) |
149 |
177 |
150 def pop: Text = |
178 def pop: Text = |
151 (state: @unchecked) match { |
179 (state: @unchecked) match { |
152 case (m1, ts1) :: (m2, ts2) :: rest => |
180 case res1 :: res2 :: rest => copy(state = res2.add(res1.result_elem) :: rest) |
153 copy(state = (m2, markup_elem(m1, ts1.reverse) :: ts2) :: rest) |
|
154 } |
181 } |
155 |
182 |
156 def result: XML.Body = |
183 def result: XML.Body = |
157 (state: @unchecked) match { |
184 (state: @unchecked) match { |
158 case List((m, ts)) if m == no_markup => ts.reverse |
185 case List(res) if res.markup == no_markup => res.result_body |
159 } |
186 } |
160 |
187 |
161 def reset: Text = copy(state = init_state) |
188 def reset: Text = copy(state = init_state) |
162 def restore(other: Text): Text = copy(state = other.state) |
189 def restore(other: Text): Text = copy(state = other.state) |
163 |
190 |
164 def newline: Text = add(fbrk).copy(pos = 0.0, nl = nl + 1) |
|
165 |
|
166 def string(s: String, len: Double): Text = |
191 def string(s: String, len: Double): Text = |
167 if (s.isEmpty) copy(pos = pos + len) |
192 (state: @unchecked) match { |
168 else add(XML.Text(s), len = len) |
193 case res :: rest => copy(state = res.string(s) :: rest, pos = pos + len) |
169 |
194 } |
170 def blanks(wd: Int): Text = string(Symbol.spaces(wd), wd.toDouble) |
195 def blanks(wd: Int): Text = string(Symbol.spaces(wd), wd.toDouble) |
|
196 def newline: Text = string("\n", 0.0).copy(pos = 0.0, nl = nl + 1) |
171 } |
197 } |
172 |
198 |
173 private def break_dist(trees: List[Tree], after: Double): Double = |
199 private def break_dist(trees: List[Tree], after: Double): Double = |
174 trees match { |
200 trees match { |
175 case (_: Break) :: _ => 0.0 |
201 case (_: Break) :: _ => 0.0 |
233 else block.body |
259 else block.body |
234 val btext1 = |
260 val btext1 = |
235 if (block.markup == no_markup) format(body1, before1, after1, text) |
261 if (block.markup == no_markup) format(body1, before1, after1, text) |
236 else { |
262 else { |
237 val btext = format(body1, before1, after1, text.reset) |
263 val btext = format(body1, before1, after1, text.reset) |
238 val elem = markup_elem(block.markup, btext.result) |
264 val elem = Elem_Buffer(block.markup, btext.result) |
239 btext.restore(text.add(elem)) |
265 btext.restore(text.add(elem)) |
240 } |
266 } |
241 val ts1 = if (text.nl < btext1.nl) force_next(ts) else ts |
267 val ts1 = if (text.nl < btext1.nl) force_next(ts) else ts |
242 format(ts1, before, after, btext1) |
268 format(ts1, before, after, btext1) |
243 case Break(force, wd, ind) :: ts => |
269 case Break(force, wd, ind) :: ts => |