43 lineno : usize, |
43 lineno : usize, |
44 input_only_ws : bool, |
44 input_only_ws : bool, |
45 cli : Config |
45 cli : Config |
46 } |
46 } |
47 |
47 |
48 type AnyChainRule = Box<dyn ChainRule>; |
48 type AnyChainRule<W> = Box<dyn ChainRule<W>>; |
49 type AnyNestedRule = Box<dyn NestedRule>; |
49 type AnyNestedRule<W> = Box<dyn NestedRule<W>>; |
50 |
50 |
51 trait ChainRule { |
51 trait ChainRule<W> { |
52 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule; |
52 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule<W>; |
53 fn flush(self : Box<Self>, ctx : &Context); |
53 fn flush(self : Box<Self>, ctx : &Context) -> W; |
54 } |
54 } |
55 |
55 |
56 trait NestedRule : ChainRule { |
56 trait NestedRule<W : Write> : ChainRule<W> { |
57 fn produce(&mut self, c : char, ctx : &Context); |
57 fn produce(&mut self, c : char, ctx : &Context); |
58 fn next(self : Box<Self>) -> AnyChainRule; |
58 fn next(self : Box<Self>) -> AnyChainRule<W>; |
59 fn produce_string(&mut self, s : String, ctx : &Context) { |
59 fn produce_string(&mut self, s : String, ctx : &Context) { |
60 s.chars().for_each(|c| self.produce(c, ctx)); |
60 s.chars().for_each(|c| self.produce(c, ctx)); |
61 } |
61 } |
62 fn start_ignored_comment(&mut self, c : char); |
62 fn start_ignored_comment(&mut self, c : char); |
63 } |
63 } |
64 |
64 |
65 impl<W : Write + 'static> ChainRule for Out<W> { |
65 impl<W : Write + 'static> ChainRule<W> for Out<W> { |
66 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule { |
66 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule<W> { |
67 basic_consume(self, c, ctx, true) |
67 basic_consume(self, c, ctx, true) |
68 } |
68 } |
69 fn flush(mut self : Box<Self>, _ctx : &Context) { |
69 fn flush(mut self : Box<Self>, _ctx : &Context) -> W { |
70 self.output.flush().unwrap(); |
70 self.output.flush().unwrap(); |
71 } |
71 self.output |
72 } |
72 } |
73 |
73 } |
74 impl<W : Write + 'static> NestedRule for Out<W> { |
74 |
|
75 impl<W : Write + 'static> NestedRule<W> for Out<W> { |
75 fn produce(&mut self, c : char, ctx : &Context) { |
76 fn produce(&mut self, c : char, ctx : &Context) { |
76 if c == '\n' { |
77 if c == '\n' { |
77 self.line_end(ctx.cli.strip_whitespace, ctx.input_only_ws) |
78 self.line_end(ctx.cli.strip_whitespace, ctx.input_only_ws) |
78 } else if c.is_whitespace() { |
79 } else if c.is_whitespace() { |
79 self.stored_whitespace.push(c); |
80 self.stored_whitespace.push(c); |
182 } |
187 } |
183 } |
188 } |
184 } |
189 } |
185 } |
190 } |
186 |
191 |
187 struct Comment(AnyNestedRule); |
192 struct Comment<W : Write>(AnyNestedRule<W>); |
188 |
193 |
189 impl ChainRule for Comment { |
194 impl<W : Write + 'static> ChainRule<W> for Comment<W> { |
190 fn consume(mut self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule { |
195 fn consume(mut self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule<W> { |
191 if c == '\n' { |
196 if c == '\n' { |
192 self.0.consume(c, ctx) |
197 self.0.consume(c, ctx) |
193 } else { |
198 } else { |
194 self.0.produce(c, ctx); |
199 self.0.produce(c, ctx); |
195 self |
200 self |
196 } |
201 } |
197 } |
202 } |
198 fn flush(self : Box<Self>, ctx : &Context) { |
203 fn flush(self : Box<Self>, ctx : &Context) -> W { |
199 self.0.flush(ctx) |
204 self.0.flush(ctx) |
200 } |
205 } |
201 } |
206 } |
202 |
207 |
203 struct IgnoreComment(AnyChainRule); |
208 struct IgnoreComment<W : Write>(AnyChainRule<W>); |
204 |
209 |
205 impl ChainRule for IgnoreComment { |
210 impl<W : Write +'static> ChainRule<W> for IgnoreComment<W> { |
206 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule { |
211 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule<W> { |
207 if c == '\n' { |
212 if c == '\n' { |
208 self.0.consume(c, ctx) |
213 self.0.consume(c, ctx) |
209 } else { |
214 } else { |
210 self |
215 self |
211 } |
216 } |
212 } |
217 } |
213 fn flush(self : Box<Self>, ctx : &Context) { |
218 fn flush(self : Box<Self>, ctx : &Context) -> W { |
214 self.0.flush(ctx) |
219 self.0.flush(ctx) |
215 } |
220 } |
216 } |
221 } |
217 |
222 |
218 struct Group(AnyNestedRule); |
223 struct Group<W : Write>(AnyNestedRule<W>); |
219 |
224 |
220 impl ChainRule for Group { |
225 impl<W : Write + 'static> ChainRule<W> for Group<W> { |
221 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule { |
226 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule<W> { |
222 basic_consume(self, c, ctx, true) |
227 basic_consume(self, c, ctx, true) |
223 } |
228 } |
224 fn flush(self : Box<Self>, ctx : &Context) { |
229 fn flush(self : Box<Self>, ctx : &Context) -> W { |
225 self.0.flush(ctx) |
230 self.0.flush(ctx) |
226 } |
231 } |
227 } |
232 } |
228 |
233 |
229 impl NestedRule for Group { |
234 impl<W : Write + 'static> NestedRule<W> for Group<W> { |
230 fn produce(&mut self, c : char, ctx : &Context) { |
235 fn produce(&mut self, c : char, ctx : &Context) { |
231 self.0.produce(c, ctx) |
236 self.0.produce(c, ctx) |
232 } |
237 } |
233 fn next(self : Box<Self>) -> AnyChainRule { |
238 fn next(self : Box<Self>) -> AnyChainRule<W> { |
234 self.0 |
239 self.0 |
235 } |
240 } |
236 fn start_ignored_comment(&mut self, c : char) { |
241 fn start_ignored_comment(&mut self, c : char) { |
237 self.0.start_ignored_comment(c) |
242 self.0.start_ignored_comment(c) |
238 } |
243 } |
239 } |
244 } |
240 |
245 |
241 struct Added(AnyNestedRule); |
246 struct Added<W : Write>(AnyNestedRule<W>); |
242 |
247 |
243 impl ChainRule for Added { |
248 impl<W : Write + 'static> ChainRule<W> for Added<W> { |
244 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule { |
249 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule<W> { |
245 basic_consume(self, c, ctx, false) |
250 basic_consume(self, c, ctx, false) |
246 } |
251 } |
247 fn flush(self : Box<Self>, ctx : &Context) { |
252 fn flush(self : Box<Self>, ctx : &Context) -> W { |
248 self.0.flush(ctx) |
253 self.0.flush(ctx) |
249 } |
254 } |
250 } |
255 } |
251 |
256 |
252 impl NestedRule for Added { |
257 impl<W : Write + 'static> NestedRule<W> for Added<W> { |
253 fn produce(&mut self, c : char, ctx : &Context) { |
258 fn produce(&mut self, c : char, ctx : &Context) { |
254 self.0.produce(c, ctx) |
259 self.0.produce(c, ctx) |
255 } |
260 } |
256 fn next(self : Box<Self>) -> AnyChainRule { |
261 fn next(self : Box<Self>) -> AnyChainRule<W> { |
257 self.0 |
262 self.0 |
258 } |
263 } |
259 fn start_ignored_comment(&mut self, c : char) { |
264 fn start_ignored_comment(&mut self, c : char) { |
260 self.0.start_ignored_comment(c) |
265 self.0.start_ignored_comment(c) |
261 } |
266 } |
262 } |
267 } |
263 struct Deleted(AnyNestedRule); |
268 struct Deleted<W : Write>(AnyNestedRule<W>); |
264 |
269 |
265 impl ChainRule for Deleted { |
270 impl<W : Write + 'static> ChainRule<W> for Deleted<W> { |
266 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule { |
271 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule<W> { |
267 basic_consume(self, c, ctx, false) |
272 basic_consume(self, c, ctx, false) |
268 } |
273 } |
269 fn flush(self : Box<Self>, ctx : &Context) { |
274 fn flush(self : Box<Self>, ctx : &Context) -> W { |
270 self.0.flush(ctx) |
275 self.0.flush(ctx) |
271 } |
276 } |
272 } |
277 } |
273 |
278 |
274 impl NestedRule for Deleted { |
279 impl<W : Write + 'static> NestedRule<W> for Deleted<W> { |
275 fn produce(&mut self, _c : char, _ctx : &Context) { |
280 fn produce(&mut self, _c : char, _ctx : &Context) { |
276 } |
281 } |
277 fn next(self : Box<Self>) -> AnyChainRule { |
282 fn next(self : Box<Self>) -> AnyChainRule<W> { |
278 self.0 |
283 self.0 |
279 } |
284 } |
280 fn start_ignored_comment(&mut self, c : char) { |
285 fn start_ignored_comment(&mut self, c : char) { |
281 self.0.start_ignored_comment(c) |
286 self.0.start_ignored_comment(c) |
282 } |
287 } |
283 } |
288 } |
284 |
289 |
285 struct Replaced(AnyNestedRule); |
290 struct Replaced<W : Write>(AnyNestedRule<W>); |
286 |
291 |
287 impl ChainRule for Replaced { |
292 impl<W : Write + 'static> ChainRule<W> for Replaced<W> { |
288 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule { |
293 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule<W> { |
289 basic_consume(self, c, ctx, false) |
294 basic_consume(self, c, ctx, false) |
290 } |
295 } |
291 fn flush(self : Box<Self>, ctx : &Context) { |
296 fn flush(self : Box<Self>, ctx : &Context) -> W { |
292 self.0.flush(ctx) |
297 self.0.flush(ctx) |
293 } |
298 } |
294 } |
299 } |
295 |
300 |
296 impl NestedRule for Replaced { |
301 impl<W : Write + 'static> NestedRule<W> for Replaced<W> { |
297 fn produce(&mut self, c : char, ctx : &Context) { |
302 fn produce(&mut self, c : char, ctx : &Context) { |
298 self.0.produce(c, ctx) |
303 self.0.produce(c, ctx) |
299 } |
304 } |
300 fn next(self : Box<Self>) -> AnyChainRule { |
305 fn next(self : Box<Self>) -> AnyChainRule<W> { |
301 Scan::new(Deleted(self.0)) |
306 Scan::new(Deleted(self.0)) |
302 } |
307 } |
303 fn start_ignored_comment(&mut self, c : char) { |
308 fn start_ignored_comment(&mut self, c : char) { |
304 self.0.start_ignored_comment(c) |
309 self.0.start_ignored_comment(c) |
305 } |
310 } |
306 } |
311 } |
307 |
312 |
308 struct Scan(AnyNestedRule); |
313 struct Scan<W : Write>(AnyNestedRule<W>); |
309 |
314 |
310 impl ChainRule for Scan { |
315 impl<W : Write + 'static> ChainRule<W> for Scan<W> { |
311 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule { |
316 fn consume(self : Box<Self>, c : char, ctx : &Context) -> AnyChainRule<W> { |
312 if c.is_whitespace() || c == '\n' { |
317 if c.is_whitespace() || c == '\n' { |
313 self |
318 self |
314 } else if c == '{' { |
319 } else if c == '{' { |
315 self.0 |
320 self.0 |
316 } else if c == '%' { |
321 } else if c == '%' { |
368 } |
373 } |
369 } |
374 } |
370 |
375 |
371 fn main() { |
376 fn main() { |
372 let cli = CommandLineArgs::parse(); |
377 let cli = CommandLineArgs::parse(); |
373 let input = cli.input.map_or_else( |
378 |
374 || Box::new(BufReader::new(io::stdin())) as Box<dyn BufRead>, |
379 match (cli.input, cli.output) { |
375 |f| Box::new(BufReader::new(File::open(f).unwrap())) as Box<dyn BufRead> |
380 (None, None) => { |
376 ); |
381 process_buffered(cli.config, io::stdin(), io::stdout()); |
377 let output = cli.output.map_or_else( |
382 }, |
378 || Box::new(BufWriter::new(io::stdout())) as Box<dyn Write>, |
383 (None, Some(o)) => { |
379 |f| Box::new(BufWriter::new(File::create(f).unwrap())) as Box<dyn Write> |
384 process_buffered(cli.config, io::stdin(), File::create(o).unwrap()); |
380 ); |
385 } |
|
386 (Some(i), None) => { |
|
387 process_buffered(cli.config, File::open(i).unwrap(), io::stdout()); |
|
388 } |
|
389 (Some(i), Some(o)) => { |
|
390 process_buffered(cli.config, File::open(i).unwrap(), File::create(o).unwrap()); |
|
391 } |
|
392 } |
|
393 } |
|
394 |
|
395 fn process_buffered<I : Read, O : Debug + Write + 'static>( |
|
396 config : Config, |
|
397 input : I, |
|
398 output : O |
|
399 ) -> O { |
|
400 process(config, BufReader::new(input), BufWriter::new(output)).into_inner().unwrap() |
|
401 } |
|
402 |
|
403 fn process<I : BufRead, O : Write + 'static>(config : Config, input : I, output : O) -> O { |
381 |
404 |
382 let mut rule : Box<dyn ChainRule> = Box::new(Out { |
405 let mut rule : Box<dyn ChainRule<O>> = Box::new(Out { |
383 only_whitespace : true, |
406 only_whitespace : true, |
384 stored_whitespace : String::new(), |
407 stored_whitespace : String::new(), |
385 output, |
408 output, |
386 whitespace_satisfied : true, |
409 whitespace_satisfied : true, |
387 par_satisfied : true, |
410 par_satisfied : true, |
388 ignored_comment_only_line : false |
411 ignored_comment_only_line : false |
389 }); |
412 }); |
390 |
413 |
391 let mut ctx = Context{ lineno : 0, cli : cli.config, input_only_ws : true}; |
414 let mut ctx = Context{ lineno : 0, cli : config, input_only_ws : true}; |
392 |
415 |
393 for l in input.lines().map(|l| l.unwrap()) { |
416 for l in input.lines().map(|l| l.unwrap()) { |
394 ctx.lineno += 1; |
417 ctx.lineno += 1; |
395 ctx.input_only_ws = true; |
418 ctx.input_only_ws = true; |
396 for c in l.chars() { |
419 for c in l.chars() { |