diff --git a/server/src/parsing.rs b/server/src/parsing.rs index 8ae25a6..cc38a64 100644 --- a/server/src/parsing.rs +++ b/server/src/parsing.rs @@ -20,6 +20,7 @@ mod character_parse; mod keyword_parse; mod identifier_parse; + // Parse the tokens in a file // Returns success or an error string pub fn token_parse( @@ -31,6 +32,7 @@ pub fn token_parse( ) -> Result<(),String> { let mut index: usize = 0; + let mut variables: HashMap = HashMap::new(); info!("Client has connected"); // Run an infinite loop loop @@ -70,7 +72,7 @@ pub fn token_parse( // Identifier Some(tokenise::Token::Identifier(name)) => { - index = match identifier_parse::identifier_parse(index+1,tokens) + index = match identifier_parse::identifier_parse(index+1,name,tokens,&mut variables) { Ok(increment) => increment, Err((err,increment)) => diff --git a/server/src/parsing/character_parse.rs b/server/src/parsing/character_parse.rs index a179c89..43d727d 100644 --- a/server/src/parsing/character_parse.rs +++ b/server/src/parsing/character_parse.rs @@ -46,7 +46,7 @@ pub fn character_parse info!("SAYS command with character {character_name}"); sum_index += 1; let output = tokenise::get_string_token(tokens, sum_index) - .map_err(|err| (err, index))?; + .map_err(|err| (err, sum_index))?; debug!("Saying {output}"); api::modify_data(happening_queue, "output".to_string(), output, character_name, vec![]); }, @@ -56,10 +56,10 @@ pub fn character_parse { sum_index += 1; let feature = tokenise::get_keyword_token(tokens, sum_index) - .map_err(|err| (err, index))?; + .map_err(|err| (err, sum_index))?; sum_index += 1; let string = tokenise::get_string_token(tokens, sum_index) - .map_err(|err| (err, index))?; + .map_err(|err| (err, sum_index))?; info!("CHANGE command with character {character_name} feature {feature}"); let mut characters = characters.lock().unwrap_or_exit("Character Mutex was poisoned",3); if let Some(character) = characters.get_mut(&character_name) @@ -74,7 +74,7 @@ pub fn character_parse { sum_index += 1; let content = tokenise::get_keyword_token(tokens, sum_index) - .map_err(|err| (err, index))?; + .map_err(|err| (err, sum_index))?; api::modify_data(happening_queue, keyword.to_lowercase(), content, character_name, vec![]); }, // Catch all condition, if the instruction is unrecognised as a diff --git a/server/src/parsing/identifier_parse.rs b/server/src/parsing/identifier_parse.rs index 2f9140b..db7d044 100644 --- a/server/src/parsing/identifier_parse.rs +++ b/server/src/parsing/identifier_parse.rs @@ -2,12 +2,10 @@ use crate:: { // Internal code character, - api, tokenise, UnwrapOrExit, + parsing, //Libs - Mutex, - Arc, HashMap, VecDeque, info, @@ -19,10 +17,55 @@ use crate:: pub fn identifier_parse ( index: usize, + identifier: &String, tokens: &[tokenise::Token], + variables: &mut HashMap, ) -> Result { let mut sum_index: usize = index; + if ! variables.contains_key(identifier) + { + variables.insert(identifier.to_string(), tokenise::Value::Null); + } + let operator = tokenise::get_operator_token(tokens, sum_index) + .map_err(|err| (err, sum_index))?; + sum_index += 1; + let value = tokenise::get_value_token(tokens, sum_index) + .map_err(|err| (err, sum_index))?; + match operator + { + // Changing a value + tokenise::Operator::Assignment => + { + variables.insert(identifier.to_string(), value); + } , + tokenise::Operator::Add => + { + let current = variables.get(identifier).unwrap(); + let result: tokenise::Value = match (value.clone(), current) + { + (tokenise::Value::Integer(int1),tokenise::Value::Integer(int2)) => tokenise::Value::Integer(int1 + int2), + (tokenise::Value::String(str1),tokenise::Value::String(str2)) => tokenise::Value::String(format!("{str1}{str2}")), + _ => value.clone(), // otherwise invalid + + }; + variables.insert(identifier.to_string(), result); + }, + tokenise::Operator::Sub => + { + let current = variables.get(identifier).unwrap(); + let result: tokenise::Value = match (value.clone(), current) + { + (tokenise::Value::Integer(int1),tokenise::Value::Integer(int2)) => tokenise::Value::Integer(int2 - int1), + _ => value.clone(), // otherwise invalid + + }; + // TODO comparisons :DDD + variables.insert(identifier.to_string(), result); + }, + _ => (), + } + debug!("{variables:?}"); sum_index += 1; Ok(sum_index) } diff --git a/server/src/tokenise.rs b/server/src/tokenise.rs index d273129..fa213fd 100644 --- a/server/src/tokenise.rs +++ b/server/src/tokenise.rs @@ -6,19 +6,21 @@ use crate:: #[derive(Debug, Clone)] pub enum Token { - String(String), - #[allow(dead_code)] - Integer(i64), // idk someone might want to do a big number - #[allow(dead_code)] - Bool(bool), - - #[allow(dead_code)] + Value(Value), Operator(Operator), Keyword(String), // Keywords aren't checked for validity in this stage Identifier(String), Bracket((Bracket,usize)), // Stores the index of the matching deliminator Character(String), } +#[derive(Debug,Clone)] +pub enum Value +{ + String(String), + Integer(i64), + Bool(bool), + Null, +} #[derive(Debug,Clone,PartialEq,Eq)] pub enum Bracket { @@ -41,11 +43,27 @@ pub enum Operator LessOrEqual, } +pub fn get_operator_token(tokens: &[Token], index: usize) +-> Result +{ + match tokens.get(index) { + Some(Token::Operator(op)) => Ok(op.clone()), + Some(_) => Err("Unexpected token".to_string()), + None => Err("File unexpectedly reached termination point".to_string()), + } +} pub fn get_string_token(tokens: &[Token], index: usize) -> Result { match tokens.get(index) { - Some(Token::String(s)) => Ok(s.clone()), + Some(Token::Value(val)) => + { + match val + { + Value::String(s) => Ok(s.clone()), + _ => Err("Unexpected value type".to_string()), + } + }, Some(_) => Err("Unexpected token".to_string()), None => Err("File unexpectedly reached termination point".to_string()), } @@ -68,6 +86,15 @@ pub fn get_closing_index(tokens: &[Token], index: usize) None => Err("File unexpectedly reached termination point".to_string()), } } +pub fn get_value_token(tokens: &[Token], index: usize) +-> Result +{ + match tokens.get(index) { + Some(Token::Value(val)) => Ok(val.clone()), + Some(_) => Err("Unexpected token".to_string()), + None => Err("File unexpectedly reached termination point".to_string()), + } +} // Tokenise the story to Vec // It can contain sub-objects (using recursive calls) @@ -122,7 +149,7 @@ pub fn tokenise(file_contents: &str) else { return Err("File unexpectedly ended: No closing quote".to_string()) }; index = new_index; item = new_item; - tokenised_data.push(Token::String(item)); + tokenised_data.push(Token::Value(Value::String(item))); } // variable/identifier else if item.starts_with("$") @@ -134,7 +161,7 @@ pub fn tokenise(file_contents: &str) // Integer else if item.parse::().is_ok() { - tokenised_data.push(Token::Integer(item.parse::().unwrap())); + tokenised_data.push(Token::Value(Value::Integer(item.parse::().unwrap()))); // unwrap is fine here because I checked } // Labels else if item.ends_with(':') diff --git a/stories/story.ha b/stories/story.ha index 22c20df..9f817eb 100644 --- a/stories/story.ha +++ b/stories/story.ha @@ -2,6 +2,7 @@ @tim change name "Timothy Fineshooter" $x = 3 $x + 1 +$x - 2 label: choice "choice numero uno" { @tim says "super sad" diff --git a/stories/test.zip b/stories/test.zip index b93251a..e13f4ea 100644 Binary files a/stories/test.zip and b/stories/test.zip differ