Cleaned code up a bit
TODD: make colour an enum make unwrap_or_exit return the error
This commit is contained in:
@@ -199,4 +199,4 @@ GOTO label
|
||||
| 12 | Failed to open archive | Make sure the story file is a zip archive. |
|
||||
| 13 | Unable to setup the characters hashmap. | Make sure the characters.json file exists, is valid JSON and contains valid characters. |
|
||||
| 14 | Unable to read the main story file. | Make sure the story.ha file exists and is readable. |
|
||||
| 15 | | |
|
||||
| 15 | Unable to tokenise data | Make sure your code is correctly formatted |
|
||||
|
||||
Generated
+11
@@ -462,6 +462,7 @@ dependencies = [
|
||||
"env_logger",
|
||||
"log",
|
||||
"serde",
|
||||
"serde-patch",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"warp",
|
||||
@@ -969,6 +970,16 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-patch"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ba8dcbff6509fa9394810d943e0e9d486a4256c23f6fcea8a58865fbe8260c4"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
|
||||
@@ -26,6 +26,7 @@ unwrap_used = "warn"
|
||||
env_logger = "0.11.10"
|
||||
log = "0.4.29"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde-patch = "0.2.3"
|
||||
serde_json = "1.0.149"
|
||||
tokio = { version = "1.51.0", features = ["rt-multi-thread","macros"] }
|
||||
warp = { version = "0.4.2", features = ["server"] }
|
||||
|
||||
+7
-25
@@ -7,6 +7,7 @@ use crate::{
|
||||
info,
|
||||
Deserialize,
|
||||
Serialize,
|
||||
apply_mut,
|
||||
Mutex,
|
||||
Arc,
|
||||
};
|
||||
@@ -27,7 +28,7 @@ pub struct Character
|
||||
torso_shape: String,
|
||||
arm_shape: String,
|
||||
leg_shape: String,
|
||||
hair_color: String,
|
||||
hair_color: String, // TODO RGB enum
|
||||
clothing: Clothing,
|
||||
}
|
||||
#[derive(Debug,Deserialize,Serialize,Clone,Default)]
|
||||
@@ -39,30 +40,11 @@ pub struct Clothing
|
||||
shoes: String,
|
||||
}
|
||||
impl Character {
|
||||
// Big ass ugly function because rust doesn't support referencing struct entries by string
|
||||
pub fn set_field(&mut self, field: &str, value: &str) -> Result<(), ()> {
|
||||
match field {
|
||||
"name" => self.name = value.to_string(),
|
||||
"gender" => self.gender = value.to_string(),
|
||||
"eye_color" => self.eye_color = value.to_string(),
|
||||
"pronoun_subject" => self.pronoun_subject = value.to_string(),
|
||||
"pronoun_object" => self.pronoun_object = value.to_string(),
|
||||
"pronoun_deppos" => self.pronoun_deppos = value.to_string(),
|
||||
"pronoun_indpos" => self.pronoun_indpos = value.to_string(),
|
||||
"pronoun_reflex" => self.pronoun_reflex = value.to_string(),
|
||||
"head_shape" => self.head_shape = value.to_string(),
|
||||
"hair_style" => self.hair_style = value.to_string(),
|
||||
"torso_shape" => self.torso_shape = value.to_string(),
|
||||
"arm_shape" => self.arm_shape = value.to_string(),
|
||||
"leg_shape" => self.leg_shape = value.to_string(),
|
||||
"hair_color" => self.hair_color = value.to_string(),
|
||||
"clothing.top" => self.clothing.top = value.to_string(),
|
||||
"clothing.bottom" => self.clothing.bottom = value.to_string(),
|
||||
"clothing.shoes" => self.clothing.shoes = value.to_string(),
|
||||
|
||||
_ => return Err(()),
|
||||
}
|
||||
|
||||
// Big ass ugly match case
|
||||
pub fn set_field(&mut self, field: &str, value: &str) -> Result<(), String> {
|
||||
let patch = format!("{{ \"{field}\": \"{value}\" }}");
|
||||
apply_mut(self, patch)
|
||||
.map_err(|_| "Invalid field".to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
+7
-16
@@ -27,6 +27,7 @@ use serde::
|
||||
Serialize
|
||||
};
|
||||
use serde_json::json;
|
||||
use serde_patch::apply_mut;
|
||||
use zip::
|
||||
{
|
||||
ZipArchive,
|
||||
@@ -51,17 +52,9 @@ async fn main()
|
||||
exit(10);
|
||||
});
|
||||
let file = File::open(format!("../stories/{file_name}")) // Get the file
|
||||
.unwrap_or_else
|
||||
(|err| {
|
||||
error!("Failed to open file: {err}");
|
||||
exit(11);
|
||||
});
|
||||
.unwrap_or_exit("Failed to read file.", 11);
|
||||
let mut archive = ZipArchive::new(file) // Open the archive
|
||||
.unwrap_or_else
|
||||
(|err| {
|
||||
error!("Failed to open archive: {err}");
|
||||
exit(12);
|
||||
});
|
||||
.unwrap_or_exit("Failed to open archive", 12);
|
||||
// Setup the characters hashmap which will store each character in it as a Character struct
|
||||
let characters = match character::character_parse(&mut archive)
|
||||
{
|
||||
@@ -102,11 +95,7 @@ async fn main()
|
||||
// Read the file and split it into tokens
|
||||
// file read from a zip file /story.ha
|
||||
let mut story_file = archive.by_name("story.ha")
|
||||
.unwrap_or_else
|
||||
(|err| {
|
||||
error!("Unable to read story file: {err}");
|
||||
exit(14);
|
||||
});
|
||||
.unwrap_or_exit("Unable to read story file", 14);
|
||||
let mut file_contents = String::new();
|
||||
story_file.read_to_string(&mut file_contents)
|
||||
.unwrap_or_else
|
||||
@@ -121,11 +110,13 @@ async fn main()
|
||||
{
|
||||
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_or_exit("Unable to tokenise data", 15);
|
||||
debug!("{tokens:?}");
|
||||
let data_clone2 = Arc::clone(&data_to_send);
|
||||
let characters_clone2 = Arc::clone(&characters);
|
||||
// Run the parsing process for the DSL
|
||||
info!("DSL parsing begun");
|
||||
match parsing::token_parse(&tokens, &characters_clone2, &data_clone2, &rx)
|
||||
{
|
||||
// Exit with error or success
|
||||
|
||||
@@ -20,13 +20,12 @@ mod character_parse;
|
||||
// Parse the tokens in a file
|
||||
// Returns success or an error string
|
||||
pub fn token_parse(
|
||||
tokens: &Vec<tokenise::Token>,
|
||||
tokens: &[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()
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ use crate::
|
||||
pub fn character_parse
|
||||
(
|
||||
index: usize,
|
||||
tokens: &Vec<tokenise::Token>,
|
||||
tokens: &[tokenise::Token],
|
||||
character_name: String,
|
||||
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
|
||||
data_to_send: &Arc<Mutex<api::DataToSend>>,
|
||||
@@ -44,7 +44,7 @@ pub fn character_parse
|
||||
let output = tokenise::get_string_token(tokens, sum_index)
|
||||
.map_err(|err| (err, index))?;
|
||||
debug!("Saying {output}");
|
||||
api::modify_data(data_to_send, "output".to_string(), output.to_string(), character_name, vec![]);
|
||||
api::modify_data(data_to_send, "output".to_string(), output, character_name, vec![]);
|
||||
},
|
||||
// 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
|
||||
@@ -71,7 +71,7 @@ pub fn character_parse
|
||||
sum_index += 1;
|
||||
let content = tokenise::get_string_token(tokens, sum_index)
|
||||
.map_err(|err| (err, 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, character_name, vec![]);
|
||||
},
|
||||
// Catch all condition, if the instruction is unrecognised as a
|
||||
// character command
|
||||
|
||||
+20
-24
@@ -6,28 +6,27 @@ use crate::
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Token
|
||||
{
|
||||
Null,
|
||||
String(String),
|
||||
Object(Vec<Token>),
|
||||
Object(Vec<Self>),
|
||||
}
|
||||
|
||||
pub fn get_string_token(tokens: &Vec<Token>, index: usize)
|
||||
pub fn get_string_token(tokens: &[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()),
|
||||
Some(Token::String(s)) => Ok(s.clone()),
|
||||
Some(_) => Err("Unexpected token".to_string()),
|
||||
None => Err("File unexpectedly reached termination point".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_object_token(tokens: &Vec<Token>, index: usize)
|
||||
pub fn get_object_token(tokens: &[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()),
|
||||
Some(Token::Object(v)) => Ok(v),
|
||||
Some(_) => Err("Unexpected token".to_string()),
|
||||
None => Err("File unexpectedly reached termination point".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,19 +41,19 @@ pub fn tokenise(space_seperated: &Vec<&str>, mut index: usize)
|
||||
while index < space_seperated.len()
|
||||
{
|
||||
let mut item = space_seperated[index].to_string();
|
||||
let mut object: Vec<Token>;
|
||||
if item.starts_with("\"")
|
||||
let object: Vec<Token>;
|
||||
if item.starts_with('"') // TODO support '
|
||||
{
|
||||
(index, item) = match tokenise_string(&space_seperated, index)
|
||||
(index, item) = match tokenise_string(space_seperated, index)
|
||||
{
|
||||
Some((index,item)) => (index, item),
|
||||
Some((index,item)) => (index,item),
|
||||
None => exit(1),
|
||||
};
|
||||
tokenised_data.push(Token::String(item));
|
||||
}
|
||||
else if item == "{"
|
||||
{
|
||||
(object, labels, index) = match tokenise(&space_seperated, index+1) // !WARNING! recursive call
|
||||
(object, labels, index) = match tokenise(space_seperated, index+1) // !WARNING! recursive call
|
||||
{
|
||||
Ok((object,labels,index)) => (object,labels,index),
|
||||
Err(err) => return Err(err),
|
||||
@@ -68,10 +67,10 @@ pub fn tokenise(space_seperated: &Vec<&str>, mut index: usize)
|
||||
else { tokenised_data.push(Token::String(item)); }
|
||||
index += 1;
|
||||
}
|
||||
return Ok((tokenised_data, labels, 0));
|
||||
Ok((tokenised_data, labels, 0))
|
||||
}
|
||||
|
||||
fn tokenise_string(space_seperated: &Vec<&str>, mut index: usize)
|
||||
fn tokenise_string(space_seperated: &[&str], mut index: usize)
|
||||
-> Option<(usize, String)>
|
||||
{
|
||||
let mut string = String::new();
|
||||
@@ -80,18 +79,15 @@ fn tokenise_string(space_seperated: &Vec<&str>, mut index: usize)
|
||||
string += chars.as_str();
|
||||
for item in &space_seperated[index+1..]
|
||||
{
|
||||
if item.ends_with("\"")
|
||||
if item.ends_with('"')
|
||||
{
|
||||
let mut chars = item.chars();
|
||||
chars.next_back();
|
||||
string += format!(" {}", chars.as_str()).as_str();
|
||||
break
|
||||
}
|
||||
else
|
||||
{
|
||||
string += format!(" {}", item).as_str();
|
||||
return Some((index+1,string))
|
||||
}
|
||||
string += format!(" {item}").as_str();
|
||||
index += 1;
|
||||
}
|
||||
return Some((index+1,string))
|
||||
None
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ use crate::
|
||||
exit,
|
||||
};
|
||||
|
||||
// TODO support Options
|
||||
// TODO pass error message back
|
||||
pub trait UnwrapOrExit<T>
|
||||
{
|
||||
fn unwrap_or_exit(self, error_message: &str, error_code: i32) -> T;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
@tim says "hello world, it's a good day"
|
||||
@tim change name "Timothy Fineshooter"
|
||||
@tim change boop "Timothy Fineshooter"
|
||||
@tim to fr
|
||||
choice "choice numero uno" {
|
||||
@tim animate wave
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user