168 lines
3.9 KiB
Rust
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)
|
|
}
|