Files
happening/server/src/parsing/keyword_parse.rs
T
2026-05-26 21:41:36 +01:00

166 lines
3.7 KiB
Rust

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<Mutex<VecDeque<api::DataToSend>>>,
labels: &HashMap<String, usize>,
variables: &mut HashMap<String, tokenise::Value>,
rx: &Receiver<(usize,String)>,
)
-> Result<usize, String>
{
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<Mutex<VecDeque<api::DataToSend>>>,
rx: &Receiver<(usize,String)>,
variables: &HashMap<String,tokenise::Value>,
)
-> Result<(usize,String), String>
{
let mut next_token: String = "or".to_string();
let mut choices: Vec<String> = Vec::new();
let mut choice_indeces: Vec<usize> = 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()))
}