# HG changeset patch # User Tuomo Valkonen # Date 1697831944 18000 # Node ID 68538da191c76af75598d42a57784f78d2add8de # Parent de1cf8032322f2b9183acd32e1417ee0b3f18d29 Make ChainRules dependent on the Write diff -r de1cf8032322 -r 68538da191c7 src/main.rs --- a/src/main.rs Thu Oct 19 23:25:34 2023 -0500 +++ b/src/main.rs Fri Oct 20 14:59:04 2023 -0500 @@ -5,12 +5,12 @@ use std::io; use std::fs::File; -use std::io::{BufWriter, BufRead, BufReader}; -use std::io::Write; +use std::io::{BufWriter, BufRead, BufReader, Write, Read}; +use std::fmt::Debug; use clap::Parser; /// Command line parameters -#[derive(Parser, Debug)] +#[derive(Parser, Debug, Clone)] #[clap( about = env!("CARGO_PKG_DESCRIPTION"), author = env!("CARGO_PKG_AUTHORS"), @@ -28,7 +28,7 @@ config : Config } -#[derive(Parser, Debug)] +#[derive(Parser, Debug, Clone)] struct Config { #[arg(long, short = 'c')] /// Strip comments @@ -45,33 +45,34 @@ cli : Config } -type AnyChainRule = Box; -type AnyNestedRule = Box; +type AnyChainRule = Box>; +type AnyNestedRule = Box>; -trait ChainRule { - fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule; - fn flush(self : Box, ctx : &Context); +trait ChainRule { + fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule; + fn flush(self : Box, ctx : &Context) -> W; } -trait NestedRule : ChainRule { +trait NestedRule : ChainRule { fn produce(&mut self, c : char, ctx : &Context); - fn next(self : Box) -> AnyChainRule; + fn next(self : Box) -> AnyChainRule; fn produce_string(&mut self, s : String, ctx : &Context) { s.chars().for_each(|c| self.produce(c, ctx)); } fn start_ignored_comment(&mut self, c : char); } -impl ChainRule for Out { - fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { +impl ChainRule for Out { + fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { basic_consume(self, c, ctx, true) } - fn flush(mut self : Box, _ctx : &Context) { + fn flush(mut self : Box, _ctx : &Context) -> W { self.output.flush().unwrap(); + self.output } } -impl NestedRule for Out { +impl NestedRule for Out { fn produce(&mut self, c : char, ctx : &Context) { if c == '\n' { self.line_end(ctx.cli.strip_whitespace, ctx.input_only_ws) @@ -86,7 +87,7 @@ } } - fn next(self : Box) -> AnyChainRule { + fn next(self : Box) -> AnyChainRule { self } @@ -103,8 +104,12 @@ } } -fn basic_consume(mut s : AnyNestedRule, c : char, ctx : &Context, print_end : bool) --> AnyChainRule { +fn basic_consume( + mut s : AnyNestedRule, + c : char, + ctx : &Context, + print_end : bool +) -> AnyChainRule { match c { '{' => { s.produce(c, ctx); @@ -135,13 +140,13 @@ } } -struct CommandName { - parent : AnyNestedRule, +struct CommandName { + parent : AnyNestedRule, command : String } -impl ChainRule for CommandName { - fn consume(mut self : Box, c : char, ctx : &Context) -> AnyChainRule { +impl ChainRule for CommandName { + fn consume(mut self : Box, c : char, ctx : &Context) -> AnyChainRule { match c { '}' | '{' | '\\' if self.command.len() <= 1 => { self.command.push(c); @@ -158,14 +163,14 @@ } } - fn flush(self : Box, ctx : &Context) { + fn flush(self : Box, ctx : &Context) -> W { self.handle(ctx) .flush(ctx) } } -impl CommandName { - fn handle(mut self, ctx : &Context) -> AnyChainRule { +impl CommandName { + fn handle(mut self, ctx : &Context) -> AnyChainRule { match self.command.as_str() { "\\added" => { Scan::new(Added(self.parent)) @@ -184,10 +189,10 @@ } } -struct Comment(AnyNestedRule); +struct Comment(AnyNestedRule); -impl ChainRule for Comment { - fn consume(mut self : Box, c : char, ctx : &Context) -> AnyChainRule { +impl ChainRule for Comment { + fn consume(mut self : Box, c : char, ctx : &Context) -> AnyChainRule { if c == '\n' { self.0.consume(c, ctx) } else { @@ -195,42 +200,42 @@ self } } - fn flush(self : Box, ctx : &Context) { + fn flush(self : Box, ctx : &Context) -> W { self.0.flush(ctx) } } -struct IgnoreComment(AnyChainRule); +struct IgnoreComment(AnyChainRule); -impl ChainRule for IgnoreComment { - fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { +impl ChainRule for IgnoreComment { + fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { if c == '\n' { self.0.consume(c, ctx) } else { self } } - fn flush(self : Box, ctx : &Context) { + fn flush(self : Box, ctx : &Context) -> W { self.0.flush(ctx) } } -struct Group(AnyNestedRule); +struct Group(AnyNestedRule); -impl ChainRule for Group { - fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { +impl ChainRule for Group { + fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { basic_consume(self, c, ctx, true) } - fn flush(self : Box, ctx : &Context) { + fn flush(self : Box, ctx : &Context) -> W { self.0.flush(ctx) } } -impl NestedRule for Group { +impl NestedRule for Group { fn produce(&mut self, c : char, ctx : &Context) { self.0.produce(c, ctx) } - fn next(self : Box) -> AnyChainRule { + fn next(self : Box) -> AnyChainRule { self.0 } fn start_ignored_comment(&mut self, c : char) { @@ -238,43 +243,43 @@ } } -struct Added(AnyNestedRule); +struct Added(AnyNestedRule); -impl ChainRule for Added { - fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { +impl ChainRule for Added { + fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { basic_consume(self, c, ctx, false) } - fn flush(self : Box, ctx : &Context) { + fn flush(self : Box, ctx : &Context) -> W { self.0.flush(ctx) } } -impl NestedRule for Added { +impl NestedRule for Added { fn produce(&mut self, c : char, ctx : &Context) { self.0.produce(c, ctx) } - fn next(self : Box) -> AnyChainRule { + fn next(self : Box) -> AnyChainRule { self.0 } fn start_ignored_comment(&mut self, c : char) { self.0.start_ignored_comment(c) } } -struct Deleted(AnyNestedRule); +struct Deleted(AnyNestedRule); -impl ChainRule for Deleted { - fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { +impl ChainRule for Deleted { + fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { basic_consume(self, c, ctx, false) } - fn flush(self : Box, ctx : &Context) { + fn flush(self : Box, ctx : &Context) -> W { self.0.flush(ctx) } } -impl NestedRule for Deleted { +impl NestedRule for Deleted { fn produce(&mut self, _c : char, _ctx : &Context) { } - fn next(self : Box) -> AnyChainRule { + fn next(self : Box) -> AnyChainRule { self.0 } fn start_ignored_comment(&mut self, c : char) { @@ -282,22 +287,22 @@ } } -struct Replaced(AnyNestedRule); +struct Replaced(AnyNestedRule); -impl ChainRule for Replaced { - fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { +impl ChainRule for Replaced { + fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { basic_consume(self, c, ctx, false) } - fn flush(self : Box, ctx : &Context) { + fn flush(self : Box, ctx : &Context) -> W { self.0.flush(ctx) } } -impl NestedRule for Replaced { +impl NestedRule for Replaced { fn produce(&mut self, c : char, ctx : &Context) { self.0.produce(c, ctx) } - fn next(self : Box) -> AnyChainRule { + fn next(self : Box) -> AnyChainRule { Scan::new(Deleted(self.0)) } fn start_ignored_comment(&mut self, c : char) { @@ -305,10 +310,10 @@ } } -struct Scan(AnyNestedRule); +struct Scan(AnyNestedRule); -impl ChainRule for Scan { - fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { +impl ChainRule for Scan { + fn consume(self : Box, c : char, ctx : &Context) -> AnyChainRule { if c.is_whitespace() || c == '\n' { self } else if c == '{' { @@ -320,13 +325,13 @@ line {lineno}", lineno = ctx.lineno) } } - fn flush(self : Box, ctx : &Context) { + fn flush(self : Box, ctx : &Context) -> W { self.0.flush(ctx) } } -impl Scan { - fn new(r : R) -> Box { +impl Scan { + fn new + 'static>(r : R) -> Box> { Box::new(Scan(Box::new(r))) } } @@ -370,16 +375,34 @@ fn main() { let cli = CommandLineArgs::parse(); - let input = cli.input.map_or_else( - || Box::new(BufReader::new(io::stdin())) as Box, - |f| Box::new(BufReader::new(File::open(f).unwrap())) as Box - ); - let output = cli.output.map_or_else( - || Box::new(BufWriter::new(io::stdout())) as Box, - |f| Box::new(BufWriter::new(File::create(f).unwrap())) as Box - ); + + match (cli.input, cli.output) { + (None, None) => { + process_buffered(cli.config, io::stdin(), io::stdout()); + }, + (None, Some(o)) => { + process_buffered(cli.config, io::stdin(), File::create(o).unwrap()); + } + (Some(i), None) => { + process_buffered(cli.config, File::open(i).unwrap(), io::stdout()); + } + (Some(i), Some(o)) => { + process_buffered(cli.config, File::open(i).unwrap(), File::create(o).unwrap()); + } + } +} + +fn process_buffered( + config : Config, + input : I, + output : O +) -> O { + process(config, BufReader::new(input), BufWriter::new(output)).into_inner().unwrap() +} + +fn process(config : Config, input : I, output : O) -> O { - let mut rule : Box = Box::new(Out { + let mut rule : Box> = Box::new(Out { only_whitespace : true, stored_whitespace : String::new(), output, @@ -388,7 +411,7 @@ ignored_comment_only_line : false }); - let mut ctx = Context{ lineno : 0, cli : cli.config, input_only_ws : true}; + let mut ctx = Context{ lineno : 0, cli : config, input_only_ws : true}; for l in input.lines().map(|l| l.unwrap()) { ctx.lineno += 1; @@ -400,5 +423,5 @@ rule = rule.consume('\n', &ctx); } - rule.flush(&ctx); + rule.flush(&ctx) }