use std::fmt::Display;
use pest::iterators::Pair;
use crate::ccarp::error::Result;
use pest_derive::Parser;
#[derive(Parser)]
#[grammar = "lang.pest"]
pub struct ParserTy;
#[allow(clippy::style)]
pub trait AST : Sized {
fn take(pair: Pair<Rule>) -> Result<Self>;
}
pub fn print_vec<T: Display>(v: &[T], sep: &str) -> String {
v.iter().map(ToString::to_string).collect::<Vec<_>>().join(sep)
}
macro_rules! list_ast {
($for:ty : $t:ty where $p1:ident => $p2:ident) => {
impl AST for $for {
fn take(pair: Pair<Rule>) -> Result<Self> {
match pair.as_rule() {
Rule::$p1 => {
let mut v=vec![];
for pair in pair.into_inner() {
match pair.as_rule() {
Rule::$p2 => v.push(<$t>::take(pair)?),
_ => return Err(rule_mismatch!(pair,$p2))
}
}
Ok(Self(v))
},
_ => return Err(rule_mismatch!(pair,$p1))
}
}
}
};
}
pub(crate) use list_ast;
macro_rules! bin_ast {
($for:ty : $t:ty where $p1:ident => $p2:ident, $($sp1:ident => $sp2:expr),+; if $ex:literal) => {
impl AST for $for {
fn take(pair: Pair<Rule>) -> Result<Self> {
match pair.as_rule() {
Rule::$p1 => {
let mut fst=None;
let mut last_op=Default::default();
let mut v=vec![];
for pair in pair.into_inner() {
match pair.as_rule() {
Rule::$p2 => {
if fst.is_none() { fst=Some(<$t>::take(pair)?) }
else { v.push((last_op,<$t>::take(pair)?)); }
},
$(
Rule::$sp1 => last_op=$sp2,
)+
_ => return Err(rule_mismatch!(pair))
}
}
Ok(Self(Box::new(safe_unwrap!(fst,$ex)),v))
},
_ => Err(rule_mismatch!(pair,$p1))
}
}
}
};
}
pub(crate) use bin_ast;