use std::env;
use std::fs;
use std::path::Path;
fn generate_transitions(
symbol: &str,
states: &[&str],
next_state: &str,
) -> String {
let transitions = states
.iter()
.map(|state| {
format!(
"
((St::{}, St::{}), (St::{}, St::{})),",
symbol, state, next_state, next_state
)
})
.collect::<Vec<String>>()
.join("");
transitions
}
macro_rules! add {
($r:ident, $symbol:literal, $states:expr, $next_state:literal) => {
$r.push_str(&generate_transitions(
$symbol,
$states,
$next_state,
));
};
}
macro_rules! transitions_table {
($r:ident) => {
let all = &[
"ST", "HE", "GC", "OC", "FL", "CT", "PC", "PM", "PP",
"TC", "MS", "MP", "MX", "MI",
];
add!($r, "TC", &["ST", "HE"], "HE");
add!(
$r,
"TC",
&[
"GC", "OC", "FL", "TC", "PC", "PM", "PP", "MS", "MP",
"MX", "MI"
],
"TC"
);
add!($r, "GC", all, "GC");
add!($r, "OC", all, "OC");
add!($r, "FL", all, "FL");
add!($r, "PC", all, "PC");
add!($r, "PM", all, "PM");
add!($r, "PP", all, "PP");
add!(
$r,
"CT",
&[
"ST", "HE", "GC", "OC", "FL", "TC", "PC", "PM", "PP",
"MS", "MX"
],
"CT"
);
add!(
$r,
"MI",
&[
"ST", "HE", "GC", "OC", "FL", "CT", "TC", "PC", "PM",
"PP", "MS", "MX"
],
"MI"
);
add!($r, "MP", &["TC", "GC", "PC", "PM", "PP", "MI"], "MP");
add!($r, "MS", &["MI", "MP", "TC"], "MS");
add!($r, "MX", &["MI", "MX", "MP", "TC"], "MX");
add!(
$r,
"MC",
&["CT", "MI", "MP", "MS", "MX", "PM", "PP", "PC"],
"MC"
);
};
}
fn generate_build_transitions_function() -> String {
let mut r = String::from(
"fn build_transitions() -> Transitions {
HashMap::from([",
);
transitions_table!(r);
r.push_str(
"
])
}",
);
r
}
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path =
Path::new(&out_dir).join("poparser-transitions.rs");
fs::write(dest_path, generate_build_transitions_function())
.unwrap();
println!("cargo:rerun-if-changed=build.rs");
}