rust_bison_skeleton/
lib.rs

1#![warn(missing_debug_implementations)]
2#![warn(missing_docs)]
3#![warn(trivial_casts, trivial_numeric_casts)]
4#![warn(unused_qualifications)]
5#![warn(deprecated_in_future)]
6#![warn(unused_lifetimes)]
7#![doc = include_str!("../README.md")]
8
9use std::error::Error;
10use std::fmt;
11use std::path::Path;
12use std::process::Command;
13
14/// An error returned from `bison` executable
15#[derive(Debug)]
16pub struct BisonErr {
17    /// stderr
18    pub message: String,
19    /// exit code
20    pub code: Option<i32>,
21}
22
23impl fmt::Display for BisonErr {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        write!(f, "BisonErr: {:#?} ({:#?})", self.message, self.code)
26    }
27}
28
29impl Error for BisonErr {}
30
31/// Creates a `.rs` file from the given `.y` file
32/// Output file is created in the same directory
33pub fn process_bison_file(filepath: &Path) -> Result<(), BisonErr> {
34    let input = filepath;
35    let output = filepath.with_extension("rs");
36
37    let bison_root_dir = Path::new(env!("CARGO_MANIFEST_DIR"))
38        .join("bison");
39
40    eprintln!("CARGO_MANIFEST_DIR = {:?}", env!("CARGO_MANIFEST_DIR"));
41    eprintln!("file = {:?}", file!());
42    eprintln!("current dir = {:?}", std::env::current_dir());
43    let bison_root_file = bison_root_dir.join("main.m4");
44
45    let args = &[
46        "-S",
47        bison_root_file.to_str().unwrap(),
48        "-o",
49        output.to_str().unwrap(),
50        input.to_str().unwrap(),
51    ];
52
53    let output = Command::new("bison").args(args).output().unwrap();
54
55    if output.status.success() {
56        Ok(())
57    } else {
58        let stderr = String::from_utf8(output.stderr).unwrap();
59        Err(BisonErr {
60            message: stderr,
61            code: output.status.code(),
62        })
63    }
64}