use std::fs::{self, File};
use std::io::Write;
const FEEL_GRAMMAR: &str = include_str!("feel.y");
const GEN_SCRIPT: &str = include_str!("gen.sh");
const GRAMMAR_FILE_NAME: &str = "feel.y";
const GEN_SCRIPT_FILE_NAME: &str = "gen.sh";
const TABLES_FILE_NAME: &str = "feel.tab.c";
const TARGET_DIR: &str = "../target/feel-grammar";
#[cfg(target_os = "linux")]
fn set_file_permissions(file_name: &str) {
use std::fs::Permissions;
use std::os::unix::fs::PermissionsExt;
fs::set_permissions(file_name, Permissions::from_mode(0o755)).expect("setting script permissions failed");
}
#[cfg(not(target_os = "linux"))]
fn set_file_permissions(_file_name: &str) {
}
fn lalr_c_tables() -> String {
{
fs::create_dir_all(TARGET_DIR).expect("creating target directories failed");
let grammar_file_name = format!("{TARGET_DIR}/{GRAMMAR_FILE_NAME}");
let mut grammar_file = File::create(grammar_file_name).expect("creating grammar file failed");
grammar_file.write_all(FEEL_GRAMMAR.as_bytes()).expect("writing grammar file failed");
let script_file_name = format!("{TARGET_DIR}/{GEN_SCRIPT_FILE_NAME}");
let mut script_file = File::create(&script_file_name).expect("creating script file failed");
script_file.write_all(GEN_SCRIPT.as_bytes()).expect("writing script file failed");
set_file_permissions(&script_file_name);
}
{
let mut command_process = std::process::Command::new(format!("./{GEN_SCRIPT_FILE_NAME}"))
.current_dir(TARGET_DIR)
.spawn()
.expect("executing script failed");
command_process.wait().expect("waiting for command process failed");
}
fs::read_to_string(format!("{TARGET_DIR}/{TABLES_FILE_NAME}")).expect("generating parsing tables failed")
}
pub fn lalr_rust_tables(output_file: &str) {
let lalr_rust_tables = crate::extractor::extract(&lalr_c_tables());
fs::write(output_file, lalr_rust_tables).expect("writing output file failed");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_all_sequentially() {
if std::env::var("CI").is_err() {
test_feel_grammar();
test_lalr_c_tables();
test_lalr_rust_tables();
}
}
fn test_feel_grammar() {
let len = FEEL_GRAMMAR.len();
assert!(len > 1000);
assert_eq!("%start feel", &FEEL_GRAMMAR[71..82]);
assert_eq!("%%\n", &FEEL_GRAMMAR[len - 3..]);
}
fn test_lalr_c_tables() {
let lalr_c_tables = lalr_c_tables();
assert!(lalr_c_tables.len() > 1000);
assert_eq!("Bison", &lalr_c_tables[5..10]);
}
fn test_lalr_rust_tables() {
let output_file = format!("{TARGET_DIR}/lalr.rs");
lalr_rust_tables(&output_file);
let lalr = fs::read_to_string(output_file).expect("reading Rust LALR tables failed");
assert!(lalr.len() > 1000);
assert_eq!("Parsing tables", &lalr[5..19]);
}
}