use crate::op::*; use crate::tokenizer::Token; use std::iter::Peekable; fn is_mul_text_token(text_token: &str) -> bool { text_token.ends_with("mul") } fn parse_mul<'a>(token_iter: &mut Peekable>) -> Option { // Take OpenParenthesis or return None token_iter.next_if_eq(&&Token::OpenParenthesis)?; // Take Number or return None let lhs = if let Some(Token::Number(lhs)) = token_iter.next_if(|v| matches!(v, Token::Number(_))) { lhs.to_owned() } else { return None; }; // Take Comma or return None token_iter.next_if_eq(&&Token::Comma)?; // Take Number or return None let rhs = if let Some(Token::Number(rhs)) = token_iter.next_if(|v: &&Token| matches!(v, Token::Number(_))) { rhs.to_owned() } else { return None; }; // Take CloseParenthesis or return None token_iter.next_if_eq(&&Token::CloseParenthesis)?; Some(MulOp::new(lhs, rhs)) } fn is_do_text_token(text_token: &str) -> bool { text_token.ends_with("do") } fn parse_do<'a>(token_iter: &mut Peekable>) -> Option { // Take OpenParenthesis or return None token_iter.next_if_eq(&&Token::OpenParenthesis)?; // Take CloseParenthesis or return None token_iter.next_if_eq(&&Token::CloseParenthesis)?; Some(DoOp::new()) } fn is_dont_text_token(text_token: &str) -> bool { text_token.ends_with("don't") } fn parse_dont<'a>(token_iter: &mut Peekable>) -> Option { // Take OpenParenthesis or return None token_iter.next_if_eq(&&Token::OpenParenthesis)?; // Take CloseParenthesis or return None token_iter.next_if_eq(&&Token::CloseParenthesis)?; Some(DontOp::new()) } /// Parse all tokens into Ops pub fn parse_tokens(tokens: &[Token]) -> Vec { let mut tokens = tokens.iter().peekable(); let mut muls: Vec = Vec::new(); while let Some(token) = tokens.next() { if let Token::Text(t) = token { if is_mul_text_token(t) { let op = parse_mul(tokens.by_ref()); if let Some(op) = op { muls.push(Ops::Mul(op)); } } else if is_do_text_token(t) { let op = parse_do(tokens.by_ref()); if let Some(op) = op { muls.push(Ops::Do(op)); } } else if is_dont_text_token(t) { let op = parse_dont(tokens.by_ref()); if let Some(op) = op { muls.push(Ops::Dont(op)); } } } } muls }