Files
happening/server/src/parsing.rs
T
2026-05-18 14:18:25 +01:00

168 lines
3.9 KiB
Rust

use std::collections::HashMap;
use crate::
{
// Internal code
character,
api,
tokenise,
// Libraries
mpsc::Receiver,
Arc,
Mutex,
info,
debug,
warn,
};
mod character_parse;
// Parse the tokens in a file
// Returns success or an error string
pub fn token_parse(
tokens: &[tokenise::Token],
labels: &HashMap<String,usize>,
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
data_to_send: &Arc<Mutex<api::DataToSend>>,
rx: &Receiver<(bool,usize,String)>,
) -> Result<(),String>
{
let mut index: usize = 0;
if rx.recv().is_err()
{
warn!("Some issue with api");
// TODO eh?
}
info!("Client has connected");
// Run an infinite loop
'parse_loop: loop
{
debug!("Reading {index}");
// Get the next token
let token: String = match tokens.get(index)
{
Some(tokenise::Token::Keyword(s)) => s.clone(),
// Ignore closing braces and jump over opening brace blocks
Some(tokenise::Token::Bracket((bracket,new_index))) =>
{
if bracket == &tokenise::Bracket::Closing { index += 1; }
else
{
warn!("Unexpected brace block, jumping over...");
index = new_index + 1;
}
continue 'parse_loop
},
// Handle a character
Some(tokenise::Token::Character(character_name)) => // TODO add support for narrator
{
index = match character_parse::character_parse(index+1,tokens,character_name.clone(),characters,data_to_send)
{
Ok(increment) => increment,
Err((err,increment)) =>
{
warn!("{err}");
increment
},
};
continue 'parse_loop
}
Some(_) =>
{
warn!("Unexpected token");
index += 1;
continue 'parse_loop
},
None => return Err("File unexpectedly reached termination point".to_string()),
};
debug!("{index}: {token}");
// The instructions are related to characters
match token.to_lowercase().as_str()
{
"end" =>
{
info!("END command, exiting");
return Ok(()) // quit successfully
},
"choice" =>
{
let choice_indeces = choice_parse(tokens, index, data_to_send)?;
debug!("{choice_indeces:?}");
if rx.recv().is_err() { warn!("Error sending choices to client"); }
let choice = match rx.recv()
{
Ok((_,choice,_)) => choice_indeces[choice],
Err(err) =>
{
warn!("Error receiving choice from client, defaulting to choice 0 {err}");
0
}
};
index = choice;
continue 'parse_loop
},
"or" =>
{
info!("OR command, jumping over");
index += 2;
let new_index = tokenise::get_closing_index(tokens, index)?;
index = new_index;
continue 'parse_loop
},
// Jump to a particular index based on a label eg GOTO character_check
"goto" =>
{
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}");
continue 'parse_loop
}
_ =>
{
warn!("Invalid command: {token}");
index += 1;
}
}
if rx.recv().is_err()
{
warn!("Some issue with api");
}
}
}
fn choice_parse(tokens: &[tokenise::Token], mut index: usize, data_to_send: &Arc<Mutex<api::DataToSend>>,)
-> Result<Vec<usize>, String>
{
let mut next_token: String = "choice".to_string();
let mut choices: Vec<String> = Vec::new();
let mut choice_indeces: Vec<usize> = Vec::new();
while next_token == "or" || next_token == "choice"
{
index += 1;
choices.push
(
tokenise::get_string_token(tokens, index)?
);
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(data_to_send, "choice".to_string(), String::new(), String::new(), choices);
Ok(choice_indeces)
}