1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use crate::command::Command;
use crate::commands::{OUTPUT, PARSE_TREE, PRINT_JSON, PRINT_YAML, RULES};
use crate::rules::Result;
use crate::utils::reader::Reader;
use crate::utils::writer::Writer;
use clap::{Arg, ArgAction, ArgMatches, ValueHint};
use std::fs::File;

#[derive(Clone, Copy, Eq, PartialEq)]
pub struct ParseTree {}

#[allow(clippy::new_without_default)]
impl ParseTree {
    pub fn new() -> Self {
        ParseTree {}
    }
}

impl Command for ParseTree {
    fn name(&self) -> &'static str {
        PARSE_TREE
    }

    fn command(&self) -> clap::Command {
        clap::Command::new(PARSE_TREE)
            .about("Prints out the parse tree for the rules defined in the file.")
            .arg(
                Arg::new(RULES.0)
                    .long(RULES.0)
                    .short(RULES.1)
                    .help("Provide a rules file")
                    .value_hint(ValueHint::FilePath)
                    .required(false),
            )
            .arg(
                Arg::new(OUTPUT.0)
                    .long(OUTPUT.0)
                    .short(OUTPUT.1)
                    .help("Write to output file")
                    .value_hint(ValueHint::FilePath)
                    .required(false),
            )
            .arg(
                Arg::new(PRINT_JSON.0)
                    .long(PRINT_JSON.0)
                    .short(PRINT_JSON.1)
                    .action(ArgAction::SetTrue)
                    .help("Print output in JSON format. Use -p as the short flag"),
            )
            .arg(
                Arg::new(PRINT_YAML.0)
                    .long(PRINT_YAML.0)
                    .short(PRINT_YAML.1)
                    .action(ArgAction::SetTrue)
                    .required(false)
                    .help("Print output in YAML format"),
            )
            .arg_required_else_help(true)
    }

    fn execute(&self, app: &ArgMatches, writer: &mut Writer, reader: &mut Reader) -> Result<i32> {
        let mut file: Box<dyn std::io::Read> = match app.get_one::<String>(RULES.0) {
            Some(file) => Box::new(std::io::BufReader::new(File::open(file)?)),
            None => Box::new(reader),
        };

        let mut content = String::new();
        file.read_to_string(&mut content)?;
        let span = crate::rules::parser::Span::new_extra(&content, "");

        let rules = crate::rules::parser::rules_file(span)?;

        match app.get_flag(PRINT_JSON.0) {
            true => serde_json::to_writer_pretty(writer, &rules)?,
            false => serde_yaml::to_writer(writer, &rules)?,
        }

        Ok(0_i32)
    }
}