use crate::tokenizer::If; use std::iter::Peekable; use crate::parser::{Expr, ExprT, Metadata, Scope}; #[derive(Clone, Debug)] pub enum DepthExpr<'a> { Decision { cond: Box<&'a str>, // TODO: take DepthExpr t: Scope, then_branch: Box>>, else_branch: Option>>>, }, IO(&'a str), Process(&'a str), } pub fn parse<'a>(vec: &Vec>) -> Vec> { let mut exprs: Vec> = Vec::new(); let mut it = vec .iter() .peekable(); while let Some(e) = it.next() { match e.expr { ExprT::Decision((cond, scope)) => { let then_branch = parse(&entire_scopes(&mut it)); let else_branch = if let Some(n) = it.peek() { match n.expr { ExprT::Decision((_, scope)) => { if let Scope::If(If::Else) = scope { it.next(); Some(Box::new(parse(&entire_scopes(&mut it)))) } else { None } } _ => None, } } else { None }; exprs.push(DepthExpr::Decision { cond: Box::new(cond), t: scope, then_branch: Box::new(then_branch), else_branch, }); } ExprT::IO(s) => { if !s.is_empty() { exprs.push(DepthExpr::IO(s)) } } ExprT::Process(s) => { if !s.is_empty() { exprs.push(DepthExpr::Process(s)) } } ExprT::StartOrStop(_) => {} } } exprs } fn entire_scopes<'a>(it: &mut Peekable>>) -> Vec> { let mut exprs: Vec> = Vec::new(); let mut scope_count: u32 = 1; // assume we already entered the scope for i in it { if let Some(meta) = i.meta { match meta { Metadata::StartScope => { scope_count = scope_count .checked_add(1) .expect("Scopes nested too deep") } Metadata::EndScope => { scope_count = scope_count .checked_sub(1) .expect("Closed not opened scope") } } } exprs.push(*i); if scope_count == 0 { break; } } exprs }