Changed how the data is tokenised
This commit is contained in:
+18
-11
@@ -1,23 +1,30 @@
|
|||||||
import requests
|
import requests
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
# Loop and get new api
|
# Loop and get new api
|
||||||
def main():
|
def main():
|
||||||
response = {}
|
response = {}
|
||||||
|
id = -1
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
response = api_get()
|
response = api_get()
|
||||||
print(response)
|
if response["id"] != id:
|
||||||
match response["action_type"]:
|
id = response["id"]
|
||||||
case "output":
|
print(response)
|
||||||
character = get_character(response["character"])
|
match response["action_type"]:
|
||||||
output(character, response["content"])
|
case "output":
|
||||||
case "choice":
|
character = get_character(response["character"])
|
||||||
user_choice = choice(response["choices"])
|
output(character, response["content"])
|
||||||
continue
|
case "choice":
|
||||||
case "end":
|
user_choice = choice(response["choices"])
|
||||||
print("Exitting successfully")
|
time.sleep(0.5)
|
||||||
os._exit(0)
|
continue
|
||||||
|
case "end":
|
||||||
|
print("Exitting successfully")
|
||||||
|
os._exit(0)
|
||||||
|
else:
|
||||||
|
continue
|
||||||
except:
|
except:
|
||||||
print("Server not up or cannot be reached")
|
print("Server not up or cannot be reached")
|
||||||
input() # Enter to go to next loop (testing)
|
input() # Enter to go to next loop (testing)
|
||||||
|
|||||||
+184
@@ -0,0 +1,184 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use crate::
|
||||||
|
{
|
||||||
|
// Internal code
|
||||||
|
character,
|
||||||
|
api,
|
||||||
|
tokenise,
|
||||||
|
|
||||||
|
// Libraries
|
||||||
|
mpsc::Receiver,
|
||||||
|
Arc,
|
||||||
|
Mutex,
|
||||||
|
info,
|
||||||
|
debug,
|
||||||
|
warn,
|
||||||
|
type_name,
|
||||||
|
};
|
||||||
|
|
||||||
|
mod strings;
|
||||||
|
mod character_parse;
|
||||||
|
|
||||||
|
// Parse the tokens in a file
|
||||||
|
// Returns success or an error string
|
||||||
|
pub fn token_parse(
|
||||||
|
tokens: &Vec<tokenise::Token>,
|
||||||
|
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
|
||||||
|
data_to_send: &Arc<Mutex<api::DataToSend>>,
|
||||||
|
rx: &Receiver<(bool,usize,String)>,
|
||||||
|
) -> Result<(),String>
|
||||||
|
{
|
||||||
|
info!("DSL parsing begun");
|
||||||
|
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
|
||||||
|
{
|
||||||
|
// Get the next token
|
||||||
|
let token = match tokens.get(index) {
|
||||||
|
Some(tokenise::Token::String(s)) => s.clone(),
|
||||||
|
Some(_) => return Err("Unexpected token".to_string()),
|
||||||
|
None => return Err("File unexpectedly reached termination point".to_string()),
|
||||||
|
};
|
||||||
|
debug!("{index}: {token}");
|
||||||
|
// The instructions are related to characters
|
||||||
|
if token.starts_with('@')
|
||||||
|
{
|
||||||
|
let character_name: String = token.chars().skip(1).collect();
|
||||||
|
debug!("Doing something with a character: {character_name}");
|
||||||
|
// The index is incremented to after the character's instructions
|
||||||
|
index = match character_parse::character_parse(index+1, tokens, character_name, characters, data_to_send)
|
||||||
|
{
|
||||||
|
Ok(increment) => increment,
|
||||||
|
Err((err,increment)) =>
|
||||||
|
{
|
||||||
|
warn!("{err}");
|
||||||
|
increment
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Miscelleneous instructions
|
||||||
|
else
|
||||||
|
{
|
||||||
|
match token.to_lowercase().as_str()
|
||||||
|
{
|
||||||
|
"end" =>
|
||||||
|
{
|
||||||
|
info!("END command, exiting");
|
||||||
|
return Ok(()) // quit successfully
|
||||||
|
},
|
||||||
|
"choice" =>
|
||||||
|
{
|
||||||
|
let mut choices: Vec<String> = Vec::new();
|
||||||
|
let mut choice_indeces: Vec<usize> = Vec::new();
|
||||||
|
index += 1;
|
||||||
|
choices.push
|
||||||
|
(match tokens.get(index) {
|
||||||
|
Some(tokenise::Token::String(s)) => s.clone(),
|
||||||
|
Some(_) => return Err("Unexpected token".to_string()),
|
||||||
|
None => return Err("File unexpectedly reached termination point".to_string()),
|
||||||
|
});
|
||||||
|
choice_indeces.push(index+1);
|
||||||
|
index += 2;
|
||||||
|
let next_token = match tokens.get(index) {
|
||||||
|
Some(tokenise::Token::String(s)) => s.clone(),
|
||||||
|
Some(_) => return Err("Unexpected token".to_string()),
|
||||||
|
None => return Err("File unexpectedly reached termination point".to_string()),
|
||||||
|
};
|
||||||
|
while next_token == "or"
|
||||||
|
{
|
||||||
|
index += 1
|
||||||
|
choices.push
|
||||||
|
(match tokens.get(index) {
|
||||||
|
Some(tokenise::Token::String(s)) => s.clone(),
|
||||||
|
Some(_) => return Err("Unexpected token".to_string()),
|
||||||
|
None => return Err("File unexpectedly reached termination point".to_string()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
"choice" =>
|
||||||
|
{
|
||||||
|
let (_,jump_points) = match choice_parse(index+1, tokens, data_to_send)
|
||||||
|
{
|
||||||
|
Ok((increment,jump_point)) => (increment,jump_point),
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
};
|
||||||
|
if rx.recv().is_err() { warn!("Error sending choices to client"); }
|
||||||
|
let (_, choice, _) = match rx.recv()
|
||||||
|
{
|
||||||
|
Ok((_,choice,_)) => (None::<bool>, choice, None::<String>),
|
||||||
|
Err(err) =>
|
||||||
|
{
|
||||||
|
warn!("Error receiving choice from client, defaulting to choice 0 {err}");
|
||||||
|
(None::<bool>, 0, None::<String>)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
index = jump_points[choice];
|
||||||
|
info!("CHOICE command with {} choices",jump_points.len());
|
||||||
|
debug!("{jump_points:?} {choice} {index}");
|
||||||
|
continue 'parse_loop
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
"or" =>
|
||||||
|
{
|
||||||
|
info!("OR command, jumping over");
|
||||||
|
index += 2;
|
||||||
|
continue
|
||||||
|
},
|
||||||
|
_ =>
|
||||||
|
{
|
||||||
|
warn!("Invalid command: {token}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rx.recv().is_err()
|
||||||
|
{
|
||||||
|
warn!("Some issue with api");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the options in a choice clause and returns the idexes of the code blocks
|
||||||
|
fn choice_parse
|
||||||
|
(
|
||||||
|
index: usize,
|
||||||
|
tokens: &[&str],
|
||||||
|
data_to_send: &Arc<Mutex<api::DataToSend>>,
|
||||||
|
) -> Result<(usize, Vec<usize>), String>
|
||||||
|
{
|
||||||
|
let mut sum_index: usize = index;
|
||||||
|
let mut choices: Vec<String> = Vec::new();
|
||||||
|
let mut choice_indeces: Vec<usize> = Vec::new();
|
||||||
|
// Ensure the index is valid (the index is not beyond the vector)
|
||||||
|
// Get the initial choice
|
||||||
|
let (choice_string, counter) = strings::extract_quoted(&tokens[sum_index..])
|
||||||
|
.ok_or_else(|| "No choice string".to_string())?;
|
||||||
|
sum_index += counter;
|
||||||
|
choices.push(choice_string);
|
||||||
|
choice_indeces.push(sum_index+1);
|
||||||
|
sum_index += strings::closing_char(&tokens[sum_index..], '{','}')
|
||||||
|
.ok_or_else(|| "No closing brace".to_string())? + 1;
|
||||||
|
// Find all the alternate choices labelled with OR
|
||||||
|
// Fill out the choices vector with all the choice strings
|
||||||
|
while tokens[sum_index].to_lowercase() == "or"
|
||||||
|
{
|
||||||
|
let (choice_string, counter) = strings::extract_quoted(&tokens[sum_index+1..])
|
||||||
|
.ok_or_else(|| "No choice string".to_string())?;
|
||||||
|
sum_index += counter;
|
||||||
|
choices.push(choice_string);
|
||||||
|
choice_indeces.push(sum_index+2);
|
||||||
|
sum_index += strings::closing_char(&tokens[sum_index..], '{','}')
|
||||||
|
.ok_or_else(|| "No closing brace".to_string())? + 1;
|
||||||
|
}
|
||||||
|
debug!("{choices:?}");
|
||||||
|
// Send the choices to the Client via the API
|
||||||
|
api::modify_data(data_to_send, "choice".to_string(), String::new(), String::new(), choices);
|
||||||
|
// Return the choice indeces
|
||||||
|
Ok((sum_index + 1, choice_indeces))
|
||||||
|
}
|
||||||
+3
-1
@@ -20,6 +20,7 @@ use crate::
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||||
pub struct DataToSend {
|
pub struct DataToSend {
|
||||||
|
pub id: u32,
|
||||||
pub action_type: String,
|
pub action_type: String,
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub character: String,
|
pub character: String,
|
||||||
@@ -53,7 +54,7 @@ pub async fn api_process
|
|||||||
// Perform this code on a GET request
|
// Perform this code on a GET request
|
||||||
.map(|state: Arc<Mutex<DataToSend>>, tx_handle: Sender<(bool,usize,String)>|
|
.map(|state: Arc<Mutex<DataToSend>>, tx_handle: Sender<(bool,usize,String)>|
|
||||||
{
|
{
|
||||||
debug!("GET: {state:?}");
|
//debug!("GET: {state:?}");
|
||||||
let reply = state.as_ref();
|
let reply = state.as_ref();
|
||||||
let _ = tx_handle.send((true,0,String::new()));
|
let _ = tx_handle.send((true,0,String::new()));
|
||||||
warp::reply::json(&reply) // Send the reply data (data_to_send formatted as JSON)
|
warp::reply::json(&reply) // Send the reply data (data_to_send formatted as JSON)
|
||||||
@@ -126,6 +127,7 @@ pub fn modify_data
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
let mut data = data_to_send.lock().unwrap_or_exit("Data to send Mutex was poisoned",2); // TODO eh?
|
let mut data = data_to_send.lock().unwrap_or_exit("Data to send Mutex was poisoned",2); // TODO eh?
|
||||||
|
data.id += 1;
|
||||||
data.action_type = action_type;
|
data.action_type = action_type;
|
||||||
data.content = content;
|
data.content = content;
|
||||||
data.character = character_name;
|
data.character = character_name;
|
||||||
|
|||||||
+7
-13
@@ -45,7 +45,7 @@ async fn main()
|
|||||||
let (tx,rx) = mpsc::channel();
|
let (tx,rx) = mpsc::channel();
|
||||||
// Unzip zip archive to get data for story
|
// Unzip zip archive to get data for story
|
||||||
let file_name = args().nth(1) // Get filename from arguments
|
let file_name = args().nth(1) // Get filename from arguments
|
||||||
.unwrap_or_else
|
.unwrap_or_else // TODO unwrap or exit
|
||||||
(|| {
|
(|| {
|
||||||
error!("No filename specified");
|
error!("No filename specified");
|
||||||
exit(10);
|
exit(10);
|
||||||
@@ -79,6 +79,7 @@ async fn main()
|
|||||||
// Initialise the data strcut that will be sent out during API GET requests
|
// Initialise the data strcut that will be sent out during API GET requests
|
||||||
let data_to_send = Arc::new(Mutex::new(api::DataToSend
|
let data_to_send = Arc::new(Mutex::new(api::DataToSend
|
||||||
{
|
{
|
||||||
|
id: 0,
|
||||||
action_type: "begin".to_owned(),
|
action_type: "begin".to_owned(),
|
||||||
content: String::new(),
|
content: String::new(),
|
||||||
character: String::new(),
|
character: String::new(),
|
||||||
@@ -113,22 +114,15 @@ async fn main()
|
|||||||
error!("Unable to read story file to string: {err}");
|
error!("Unable to read story file to string: {err}");
|
||||||
exit(14);
|
exit(14);
|
||||||
});
|
});
|
||||||
// Tokenise story file
|
|
||||||
/*
|
|
||||||
let tokens: Vec<&str> = file_contents
|
|
||||||
.split_whitespace()
|
|
||||||
.collect();
|
|
||||||
if ! tokens.contains(&"END")
|
|
||||||
{
|
|
||||||
warn!("No END statement, story may exit unexpectedly");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
let space_seperated: Vec<&str> = file_contents
|
let space_seperated: Vec<&str> = file_contents
|
||||||
.split_whitespace()
|
.split_whitespace()
|
||||||
.collect();
|
.collect();
|
||||||
|
if ! space_seperated.contains(&"END")
|
||||||
|
{
|
||||||
|
warn!("No END statement, story may exit unexpectedly");
|
||||||
|
}
|
||||||
let (tokens, labels,_) = tokenise::tokenise(&space_seperated, 0).unwrap();
|
let (tokens, labels,_) = tokenise::tokenise(&space_seperated, 0).unwrap();
|
||||||
debug!("{tokens:?}");
|
debug!("{tokens:?}");
|
||||||
/*
|
|
||||||
let data_clone2 = Arc::clone(&data_to_send);
|
let data_clone2 = Arc::clone(&data_to_send);
|
||||||
let characters_clone2 = Arc::clone(&characters);
|
let characters_clone2 = Arc::clone(&characters);
|
||||||
// Run the parsing process for the DSL
|
// Run the parsing process for the DSL
|
||||||
@@ -138,6 +132,7 @@ async fn main()
|
|||||||
Ok(()) =>
|
Ok(()) =>
|
||||||
{
|
{
|
||||||
api::modify_data(&data_to_send, "end".to_string(), String::new(), String::new(), vec![]);
|
api::modify_data(&data_to_send, "end".to_string(), String::new(), String::new(), vec![]);
|
||||||
|
// TODO fix quitting instantly
|
||||||
let _ = rx.recv(); // Wait for the client to respond
|
let _ = rx.recv(); // Wait for the client to respond
|
||||||
info!("Program exited successfully");
|
info!("Program exited successfully");
|
||||||
exit(0);
|
exit(0);
|
||||||
@@ -148,5 +143,4 @@ async fn main()
|
|||||||
exit(1);
|
exit(1);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-65
@@ -4,6 +4,7 @@ use crate::
|
|||||||
// Internal code
|
// Internal code
|
||||||
character,
|
character,
|
||||||
api,
|
api,
|
||||||
|
tokenise,
|
||||||
|
|
||||||
// Libraries
|
// Libraries
|
||||||
mpsc::Receiver,
|
mpsc::Receiver,
|
||||||
@@ -14,13 +15,12 @@ use crate::
|
|||||||
warn,
|
warn,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod strings;
|
|
||||||
mod character_parse;
|
mod character_parse;
|
||||||
|
|
||||||
// Parse the tokens in a file
|
// Parse the tokens in a file
|
||||||
// Returns success or an error string
|
// Returns success or an error string
|
||||||
pub fn token_parse(
|
pub fn token_parse(
|
||||||
tokens: &Vec<&str>,
|
tokens: &Vec<tokenise::Token>,
|
||||||
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
|
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
|
||||||
data_to_send: &Arc<Mutex<api::DataToSend>>,
|
data_to_send: &Arc<Mutex<api::DataToSend>>,
|
||||||
rx: &Receiver<(bool,usize,String)>,
|
rx: &Receiver<(bool,usize,String)>,
|
||||||
@@ -31,16 +31,14 @@ pub fn token_parse(
|
|||||||
if rx.recv().is_err()
|
if rx.recv().is_err()
|
||||||
{
|
{
|
||||||
warn!("Some issue with api");
|
warn!("Some issue with api");
|
||||||
// TOD eh?
|
// TODO eh?
|
||||||
}
|
}
|
||||||
info!("Client has connected");
|
info!("Client has connected");
|
||||||
// Run an infinite loop
|
// Run an infinite loop
|
||||||
'parse_loop: loop
|
'parse_loop: loop
|
||||||
{
|
{
|
||||||
// Get the next token
|
// Get the next token
|
||||||
let token = tokens
|
let token = tokenise::get_string_token(tokens, index)?;
|
||||||
.get(index)
|
|
||||||
.ok_or_else(|| "File unexpectedly reached termination point".to_string())?;
|
|
||||||
debug!("{index}: {token}");
|
debug!("{index}: {token}");
|
||||||
// The instructions are related to characters
|
// The instructions are related to characters
|
||||||
if token.starts_with('@')
|
if token.starts_with('@')
|
||||||
@@ -70,39 +68,48 @@ pub fn token_parse(
|
|||||||
},
|
},
|
||||||
"choice" =>
|
"choice" =>
|
||||||
{
|
{
|
||||||
let (_,jump_points) = match choice_parse(index+1, tokens, data_to_send)
|
debug!("Doing CHOICE");
|
||||||
|
let mut next_token = token;
|
||||||
|
let mut choices: Vec<String> = Vec::new();
|
||||||
|
let mut choice_indeces: Vec<usize> = Vec::new();
|
||||||
|
while next_token == "or" || next_token == "choice"
|
||||||
{
|
{
|
||||||
Ok((increment,jump_point)) => (increment,jump_point),
|
index += 1;
|
||||||
Err(error) => return Err(error),
|
choices.push
|
||||||
};
|
(
|
||||||
|
tokenise::get_string_token(tokens, index)?
|
||||||
|
);
|
||||||
|
choice_indeces.push(index+1);
|
||||||
|
index += 2;
|
||||||
|
next_token = match tokenise::get_string_token(tokens, index)
|
||||||
|
{
|
||||||
|
Ok(string) => string,
|
||||||
|
Err(_) => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug!("{choices:?}");
|
||||||
|
debug!("{choice_indeces:?}");
|
||||||
|
api::modify_data(data_to_send, "choice".to_string(), String::new(), String::new(), choices);
|
||||||
if rx.recv().is_err() { warn!("Error sending choices to client"); }
|
if rx.recv().is_err() { warn!("Error sending choices to client"); }
|
||||||
let (_, choice, _) = match rx.recv()
|
let choice = match rx.recv()
|
||||||
{
|
{
|
||||||
Ok((_,choice,_)) => (None::<bool>, choice, None::<String>),
|
Ok((_,choice,_)) => choice_indeces[choice],
|
||||||
Err(err) =>
|
Err(err) =>
|
||||||
{
|
{
|
||||||
warn!("Error receiving choice from client, defaulting to choice 0 {err}");
|
warn!("Error receiving choice from client, defaulting to choice 0 {err}");
|
||||||
(None::<bool>, 0, None::<String>)
|
0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
index = jump_points[choice];
|
let object = tokenise::get_object_token(tokens, choice)?; // TODO make more efficient
|
||||||
info!("CHOICE command with {} choices",jump_points.len());
|
debug!("{object:?}");
|
||||||
debug!("{jump_points:?} {choice} {index}");
|
// Don't propogate exit error
|
||||||
|
let _ = token_parse(object, characters, data_to_send, rx);
|
||||||
continue 'parse_loop
|
continue 'parse_loop
|
||||||
},
|
},
|
||||||
"or" =>
|
"or" =>
|
||||||
{
|
{
|
||||||
info!("OR command, jumping over");
|
info!("OR command, jumping over");
|
||||||
index += match strings::closing_char(&tokens[index..], '{','}')
|
index += 2;
|
||||||
{
|
|
||||||
Some(index) => index,
|
|
||||||
None => return Err(String::from("No closing brace")),
|
|
||||||
};
|
|
||||||
continue
|
|
||||||
},
|
|
||||||
"}" =>
|
|
||||||
{
|
|
||||||
index += 1;
|
|
||||||
continue
|
continue
|
||||||
},
|
},
|
||||||
_ =>
|
_ =>
|
||||||
@@ -117,42 +124,3 @@ pub fn token_parse(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the options in a choice clause and returns the idexes of the code blocks
|
|
||||||
fn choice_parse
|
|
||||||
(
|
|
||||||
index: usize,
|
|
||||||
tokens: &[&str],
|
|
||||||
data_to_send: &Arc<Mutex<api::DataToSend>>,
|
|
||||||
) -> Result<(usize, Vec<usize>), String>
|
|
||||||
{
|
|
||||||
let mut sum_index: usize = index;
|
|
||||||
let mut choices: Vec<String> = Vec::new();
|
|
||||||
let mut choice_indeces: Vec<usize> = Vec::new();
|
|
||||||
// Ensure the index is valid (the index is not beyond the vector)
|
|
||||||
// Get the initial choice
|
|
||||||
let (choice_string, counter) = strings::extract_quoted(&tokens[sum_index..])
|
|
||||||
.ok_or_else(|| "No choice string".to_string())?;
|
|
||||||
sum_index += counter;
|
|
||||||
choices.push(choice_string);
|
|
||||||
choice_indeces.push(sum_index+1);
|
|
||||||
sum_index += strings::closing_char(&tokens[sum_index..], '{','}')
|
|
||||||
.ok_or_else(|| "No closing brace".to_string())? + 1;
|
|
||||||
// Find all the alternate choices labelled with OR
|
|
||||||
// Fill out the choices vector with all the choice strings
|
|
||||||
while tokens[sum_index].to_lowercase() == "or"
|
|
||||||
{
|
|
||||||
let (choice_string, counter) = strings::extract_quoted(&tokens[sum_index+1..])
|
|
||||||
.ok_or_else(|| "No choice string".to_string())?;
|
|
||||||
sum_index += counter;
|
|
||||||
choices.push(choice_string);
|
|
||||||
choice_indeces.push(sum_index+2);
|
|
||||||
sum_index += strings::closing_char(&tokens[sum_index..], '{','}')
|
|
||||||
.ok_or_else(|| "No closing brace".to_string())? + 1;
|
|
||||||
}
|
|
||||||
debug!("{choices:?}");
|
|
||||||
// Send the choices to the Client via the API
|
|
||||||
api::modify_data(data_to_send, "choice".to_string(), String::new(), String::new(), choices);
|
|
||||||
// Return the choice indeces
|
|
||||||
Ok((sum_index + 1, choice_indeces))
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use super::strings;
|
|
||||||
use crate::
|
use crate::
|
||||||
{
|
{
|
||||||
// Internal code
|
// Internal code
|
||||||
character,
|
character,
|
||||||
api,
|
api,
|
||||||
|
tokenise,
|
||||||
UnwrapOrExit,
|
UnwrapOrExit,
|
||||||
//Libs
|
//Libs
|
||||||
Mutex,
|
Mutex,
|
||||||
@@ -20,7 +20,7 @@ use crate::
|
|||||||
pub fn character_parse
|
pub fn character_parse
|
||||||
(
|
(
|
||||||
index: usize,
|
index: usize,
|
||||||
tokens: &Vec<&str>,
|
tokens: &Vec<tokenise::Token>,
|
||||||
character_name: String,
|
character_name: String,
|
||||||
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
|
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
|
||||||
data_to_send: &Arc<Mutex<api::DataToSend>>,
|
data_to_send: &Arc<Mutex<api::DataToSend>>,
|
||||||
@@ -28,9 +28,11 @@ pub fn character_parse
|
|||||||
{
|
{
|
||||||
let mut sum_index: usize = index;
|
let mut sum_index: usize = index;
|
||||||
// Ensure the index is valid (the index is not beyond the vector)
|
// Ensure the index is valid (the index is not beyond the vector)
|
||||||
let token = tokens
|
let token = match tokens.get(sum_index) {
|
||||||
.get(sum_index)
|
Some(tokenise::Token::String(s)) => s.clone(),
|
||||||
.ok_or_else(|| ("File unexpectedly reached termination point".to_string(), sum_index))?;
|
Some(_) => return Err(("Unexpected token".to_string(), sum_index + 1)),
|
||||||
|
None => return Err(("File unexpectedly reached termination point".to_string(), sum_index)),
|
||||||
|
};
|
||||||
match token.to_lowercase().as_str()
|
match token.to_lowercase().as_str()
|
||||||
{
|
{
|
||||||
// The character is saying something, so grab the text and pass it
|
// The character is saying something, so grab the text and pass it
|
||||||
@@ -38,35 +40,26 @@ pub fn character_parse
|
|||||||
"says" =>
|
"says" =>
|
||||||
{
|
{
|
||||||
info!("SAYS command with character {character_name}");
|
info!("SAYS command with character {character_name}");
|
||||||
match strings::extract_quoted(&tokens[sum_index+1..])
|
sum_index += 1;
|
||||||
{
|
let output = tokenise::get_string_token(tokens, sum_index)
|
||||||
Some((output_string, counter)) =>
|
.map_err(|err| (err, index))?;
|
||||||
{
|
debug!("Saying {output}");
|
||||||
debug!("{output_string}");
|
api::modify_data(data_to_send, "output".to_string(), output.to_string(), character_name, vec![]);
|
||||||
sum_index += counter;
|
|
||||||
api::modify_data(data_to_send, "output".to_string(), output_string, character_name, vec![]);
|
|
||||||
},
|
|
||||||
None => return Err(("Unable to read output string".to_string(), sum_index)),
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
// Change the property of the selected character eg @tim CHANGE name "Bill Buffins"
|
// Change the property of the selected character eg @tim CHANGE name "Bill Buffins"
|
||||||
// will change the character with ID tim to "Bill Buffins"; a character's ID cannot change
|
// will change the character with ID tim to "Bill Buffins"; a character's ID cannot change
|
||||||
"change" =>
|
"change" =>
|
||||||
{
|
{
|
||||||
sum_index += 1;
|
sum_index += 1;
|
||||||
let feature = tokens
|
let feature = tokenise::get_string_token(tokens, sum_index)
|
||||||
.get(sum_index)
|
.map_err(|err| (err, index))?;
|
||||||
.ok_or_else(|| ("File unexpectedly reached termination point".to_string(), sum_index))?;
|
sum_index += 1;
|
||||||
let output_string: String;
|
let string = tokenise::get_string_token(tokens, sum_index)
|
||||||
(output_string, sum_index) = match strings::extract_quoted(&tokens[sum_index+1..])
|
.map_err(|err| (err, index))?;
|
||||||
{
|
|
||||||
Some((string,counter)) => (string,sum_index+counter),
|
|
||||||
None => return Err(("Unable to parse property to change character".to_string(),sum_index)),
|
|
||||||
};
|
|
||||||
info!("CHANGE command with character {character_name} feature {feature}");
|
info!("CHANGE command with character {character_name} feature {feature}");
|
||||||
let mut characters = characters.lock().unwrap_or_exit("Character Mutex was poisoned",3);
|
let mut characters = characters.lock().unwrap_or_exit("Character Mutex was poisoned",3);
|
||||||
if let Some(character) = characters.get_mut(&character_name)
|
if let Some(character) = characters.get_mut(&character_name)
|
||||||
&& character.set_field(feature, &output_string)
|
&& character.set_field(&feature, &string)
|
||||||
.is_err() { warn!("Feature {feature} does not exist") }
|
.is_err() { warn!("Feature {feature} does not exist") }
|
||||||
drop(characters);
|
drop(characters);
|
||||||
api::modify_data(data_to_send, "change".to_string(), String::new(), character_name, vec![]);
|
api::modify_data(data_to_send, "change".to_string(), String::new(), character_name, vec![]);
|
||||||
@@ -76,9 +69,8 @@ pub fn character_parse
|
|||||||
"to"|"animate" =>
|
"to"|"animate" =>
|
||||||
{
|
{
|
||||||
sum_index += 1;
|
sum_index += 1;
|
||||||
let content = tokens
|
let content = tokenise::get_string_token(tokens, sum_index)
|
||||||
.get(sum_index)
|
.map_err(|err| (err, index))?;
|
||||||
.ok_or_else(|| ("File unexpectedly reached termination point".to_string(), sum_index))?;
|
|
||||||
api::modify_data(data_to_send, token.to_lowercase(), content.to_string(), character_name, vec![]);
|
api::modify_data(data_to_send, token.to_lowercase(), content.to_string(), character_name, vec![]);
|
||||||
},
|
},
|
||||||
// Catch all condition, if the instruction is unrecognised as a
|
// Catch all condition, if the instruction is unrecognised as a
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
pub fn closing_char(parts: &[&str], open: char, close: char)
|
|
||||||
-> Option<usize>
|
|
||||||
{
|
|
||||||
let mut indentation: usize = 0;
|
|
||||||
let mut flag = false; // flag to mark you've passed open
|
|
||||||
for (index, part) in parts.iter().enumerate()
|
|
||||||
{
|
|
||||||
if part.contains(open)
|
|
||||||
{
|
|
||||||
indentation += 1;
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
if part.contains(close) { indentation -= 1; }
|
|
||||||
if indentation == 0 && flag { return Some(index); }
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
pub fn extract_quoted(parts: &[&str])
|
|
||||||
-> Option<(String, usize)>
|
|
||||||
{
|
|
||||||
let mut vec_string = Vec::new();
|
|
||||||
let mut counter: usize = 0;
|
|
||||||
for part in parts
|
|
||||||
{
|
|
||||||
counter += 1;
|
|
||||||
vec_string.push(*part);
|
|
||||||
// End of the string
|
|
||||||
if part.ends_with('\"') // TODO allow for backslashes and '
|
|
||||||
{
|
|
||||||
let final_string: String = vec_string.join(" ");
|
|
||||||
let final_string: String = final_string
|
|
||||||
.chars()
|
|
||||||
.skip(1)
|
|
||||||
.take(
|
|
||||||
final_string.chars()
|
|
||||||
.count() - 2)
|
|
||||||
.collect();
|
|
||||||
return Some((final_string, counter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
+25
-4
@@ -1,10 +1,9 @@
|
|||||||
use crate::
|
use crate::
|
||||||
{
|
{
|
||||||
debug,
|
|
||||||
exit,
|
exit,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Token
|
pub enum Token
|
||||||
{
|
{
|
||||||
Null,
|
Null,
|
||||||
@@ -12,6 +11,29 @@ pub enum Token
|
|||||||
Object(Vec<Token>),
|
Object(Vec<Token>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_string_token(tokens: &Vec<Token>, index: usize)
|
||||||
|
-> Result<String, String>
|
||||||
|
{
|
||||||
|
match tokens.get(index) {
|
||||||
|
Some(Token::String(s)) => return Ok(s.clone()),
|
||||||
|
Some(_) => return Err("Unexpected token".to_string()),
|
||||||
|
None => return Err("File unexpectedly reached termination point".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_object_token(tokens: &Vec<Token>, index: usize)
|
||||||
|
-> Result<&Vec<Token>, String>
|
||||||
|
{
|
||||||
|
match tokens.get(index) {
|
||||||
|
Some(Token::Object(v)) => return Ok(v),
|
||||||
|
Some(_) => return Err("Unexpected token".to_string()),
|
||||||
|
None => return Err("File unexpectedly reached termination point".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tokenise the story to Vec<Token>
|
||||||
|
// It can contain sub-objects (using recursive calls)
|
||||||
|
// TODO check for END
|
||||||
pub fn tokenise(space_seperated: &Vec<&str>, mut index: usize)
|
pub fn tokenise(space_seperated: &Vec<&str>, mut index: usize)
|
||||||
-> Result<(Vec<Token>,Vec<(String,usize)>,usize),String>
|
-> Result<(Vec<Token>,Vec<(String,usize)>,usize),String>
|
||||||
{
|
{
|
||||||
@@ -20,8 +42,7 @@ pub fn tokenise(space_seperated: &Vec<&str>, mut index: usize)
|
|||||||
while index < space_seperated.len()
|
while index < space_seperated.len()
|
||||||
{
|
{
|
||||||
let mut item = space_seperated[index].to_string();
|
let mut item = space_seperated[index].to_string();
|
||||||
let mut object: Vec<Token> = Vec::new();
|
let mut object: Vec<Token>;
|
||||||
debug!("{item}");
|
|
||||||
if item.starts_with("\"")
|
if item.starts_with("\"")
|
||||||
{
|
{
|
||||||
(index, item) = match tokenise_string(&space_seperated, index)
|
(index, item) = match tokenise_string(&space_seperated, index)
|
||||||
|
|||||||
@@ -4,8 +4,21 @@
|
|||||||
choice "choice numero uno" {
|
choice "choice numero uno" {
|
||||||
@tim animate wave
|
@tim animate wave
|
||||||
@tim says "super sad"
|
@tim says "super sad"
|
||||||
|
choice "choice numero uno" {
|
||||||
|
@tim animate wave
|
||||||
|
@tim says "super sad"
|
||||||
|
}
|
||||||
|
or "choice numero duo" {
|
||||||
|
@tim says "super unsad"
|
||||||
|
}
|
||||||
|
or "choice numero tres" {
|
||||||
|
@tim says "hola mi amigos"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
or "choice numero duo" {
|
or "choice numero duo" {
|
||||||
@tim says "super unsad"
|
@tim says "super unsad"
|
||||||
}
|
}
|
||||||
|
or "choice numero tres" {
|
||||||
|
@tim says "hola mi amigos"
|
||||||
|
}
|
||||||
END
|
END
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user