1
use std::fs::File;
2
use std::io::Write;
3
use std::process::ExitCode;
4

            
5
use clap::Parser;
6
use clap::Subcommand;
7

            
8
use merc_rec_tests::load_rec_from_file;
9
use merc_tools::VerbosityFlag;
10
use merc_tools::Version;
11
use merc_tools::VersionFlag;
12
use merc_unsafety::print_allocator_metrics;
13
use merc_utilities::MercError;
14

            
15
use merc_rewrite::Rewriter;
16
use merc_rewrite::rewrite_rec;
17

            
18
mod trs_format;
19

            
20
pub use trs_format::*;
21

            
22
#[derive(clap::Parser, Debug)]
23
#[command(about = "A command line rewriting tool", arg_required_else_help = true)]
24
struct Cli {
25
    #[command(flatten)]
26
    version: VersionFlag,
27

            
28
    #[command(flatten)]
29
    verbosity: VerbosityFlag,
30

            
31
    #[command(subcommand)]
32
    commands: Option<Commands>,
33
}
34

            
35
#[derive(Debug, Subcommand)]
36
enum Commands {
37
    Rewrite(RewriteArgs),
38
    Convert(ConvertArgs),
39
}
40

            
41
#[derive(clap::Args, Debug)]
42
#[command(about = "Rewrite mCRL2 data specifications and REC files")]
43
struct RewriteArgs {
44
    rewriter: Rewriter,
45

            
46
    #[arg(value_name = "SPEC")]
47
    specification: String,
48

            
49
    #[arg(help = "File containing the terms to be rewritten.")]
50
    terms: Option<String>,
51

            
52
    #[arg(long = "output", default_value_t = false, help = "Print the rewritten term(s)")]
53
    output: bool,
54
}
55

            
56
#[derive(clap::Args, Debug)]
57
#[command(about = "Convert input rewrite system to the TRS format")]
58
struct ConvertArgs {
59
    #[arg(value_name = "SPEC")]
60
    specification: String,
61

            
62
    output: String,
63
}
64

            
65
fn main() -> Result<ExitCode, MercError> {
66
    let cli = Cli::parse();
67

            
68
    env_logger::Builder::new()
69
        .filter_level(cli.verbosity.log_level_filter())
70
        .parse_default_env()
71
        .init();
72

            
73
    if cli.version.into() {
74
        eprintln!("{}", Version);
75
        return Ok(ExitCode::SUCCESS);
76
    }
77

            
78
    if let Some(command) = cli.commands {
79
        match command {
80
            Commands::Rewrite(args) => {
81
                if args.specification.ends_with(".rec") {
82
                    assert!(args.terms.is_none());
83
                    rewrite_rec(args.rewriter, &args.specification, args.output)?;
84
                }
85
            }
86
            Commands::Convert(args) => {
87
                if args.specification.ends_with(".rec") {
88
                    // Read the data specification
89
                    let (spec_text, _) = load_rec_from_file(args.specification.into())?;
90
                    let spec = spec_text.to_rewrite_spec();
91

            
92
                    let mut output = File::create(args.output)?;
93
                    write!(output, "{}", TrsFormatter::new(&spec))?;
94
                }
95
            }
96
        }
97
    }
98

            
99
    print_allocator_metrics();
100
    Ok(ExitCode::SUCCESS)
101
}