use crate:: { tokenise, api, HashMap, Arc, Mutex, VecDeque, warn, debug, info, mpsc::Receiver, }; use super::identifier_parse; pub fn keyword_parse( tokens: &[tokenise::Token], token: &str, mut index: usize, happening_queue: &Arc>>, labels: &HashMap, variables: &mut HashMap, rx: &Receiver<(usize,String)>, ) -> Result { match token.to_lowercase().as_str() { "choice" => { (index,_) = choice_parse(tokens, index, happening_queue, rx,variables)?; }, "if" => { // TODO can this go in a function? let mut keyword = "if".to_string(); while keyword == "if" || keyword == "elif" || keyword == "else" // TODO less beefy?? { index += 1; let mut result: bool = true; if keyword != "else" { let identifier = tokenise::get_identifier_token(tokens, index)?; (index,result) = match identifier_parse::identifier_parse(index+1, &identifier, tokens, variables,rx,happening_queue) { Ok((increment, result)) => (increment,result), Err((err,increment)) => { warn!("{err}"); (increment,false) } } } if result { index += 1; break; } index = tokenise::get_closing_index(tokens,index)?; index += 1; keyword = match tokenise::get_keyword_token(tokens,index) { Ok(keyword) => keyword, Err(_) => break, } } }, "else" => { index += 1; index = tokenise::get_closing_index(tokens, index)?; }, "elif" => { loop { index += 1; let Ok(new_index) = tokenise::get_closing_index(tokens, index) else { continue; }; index = new_index; break } }, "or" => { info!("OR command, jumping over"); index += 2; let new_index = tokenise::get_closing_index(tokens, index)?; index = new_index; }, // Jump to a particular index based on a label eg GOTO character_check "goto" => { info!("GOTO command, jumping there"); index += 1; let label = tokenise::get_keyword_token(tokens, index)?; index = if let Some(label_index) = labels.get(&label) { *label_index } else { warn!("Label {label} does not exist"); index + 1 }; debug!("Jumping to {index}"); }, "pan" => { info!("PAN command, informing client"); index += 1; let location = tokenise::get_keyword_token(tokens, index)?; api::modify_data(happening_queue, "pan".to_string(), location, String::new(), Vec::new()); }, _ => { warn!("Invalid command: {token}, index {index}"); index += 1; } } Ok(index) } pub fn choice_parse ( tokens: &[tokenise::Token], mut index: usize, happening_queue: &Arc>>, rx: &Receiver<(usize,String)>, variables: &HashMap, ) -> Result<(usize,String), String> { let mut next_token: String = "or".to_string(); let mut choices: Vec = Vec::new(); let mut choice_indeces: Vec = Vec::new(); while next_token == "or" { index += 1; choices.push ( tokenise::get_string_token(tokens, index,variables)? ); index += 1; choice_indeces.push(index+1); index = match tokenise::get_closing_index(tokens,index) { Ok(new_index) => new_index + 1, Err(_) => break, }; next_token = match tokenise::get_keyword_token(tokens, index) { Ok(string) => string, Err(_) => break, } }; api::modify_data(happening_queue, "choice".to_string(), String::new(), String::new(), choices.clone()); info!("Waiting for client choice"); debug!("{choice_indeces:?}"); let choice = match rx.recv() { Ok((choice,_)) => choice, Err(err) => { warn!("Error receiving choice from client, defaulting to choice 0 {err}"); 0 } }; Ok((choice_indeces[choice],choices[choice].clone())) }