Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cc3eca857d | |||
| f6a95f76bd | |||
| 59f32e975b | |||
| 4f7abb5f19 |
Generated
+1
-1
@@ -457,7 +457,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "happening-server"
|
name = "happening-server"
|
||||||
version = "0.0.2"
|
version = "0.0.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"log",
|
"log",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "happening-server"
|
name = "happening-server"
|
||||||
version = "0.0.2"
|
version = "0.0.3"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "GPL-3"
|
license = "GPL-3"
|
||||||
repository = "https://git.javalsai.tuxcord.net/deadvey/happening/"
|
repository = "https://git.javalsai.tuxcord.net/deadvey/happening/"
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ pub fn modify_data // TODO rename
|
|||||||
character,
|
character,
|
||||||
choices,
|
choices,
|
||||||
};
|
};
|
||||||
|
debug!("{new_data:?}");
|
||||||
queue.push_back(new_data);
|
queue.push_back(new_data);
|
||||||
drop(queue);
|
drop(queue);
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-1
@@ -108,9 +108,18 @@ 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 the file
|
||||||
let (tokens, labels) = tokenise::tokenise(&file_contents)
|
let (tokens, labels) = tokenise::tokenise(&file_contents)
|
||||||
.unwrap_or_exit("Unable to tokenise data", 15);
|
.unwrap_or_exit("Unable to tokenise data", 15);
|
||||||
debug!("{tokens:?}\n{labels:?}");
|
// TESTING
|
||||||
|
//debug!("{tokens:?}\n{labels:?}");
|
||||||
|
for (index,token) in tokens.iter().enumerate()
|
||||||
|
{
|
||||||
|
debug!("{index}: {token:?}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the syntactic parser
|
||||||
let characters_clone2 = Arc::clone(&characters);
|
let characters_clone2 = Arc::clone(&characters);
|
||||||
let happening_stack2 = Arc::clone(&happening_stack);
|
let happening_stack2 = Arc::clone(&happening_stack);
|
||||||
// Run the parsing process for the DSL
|
// Run the parsing process for the DSL
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use crate::
|
use crate::
|
||||||
{
|
{
|
||||||
// Internal code
|
// Internal code
|
||||||
@@ -11,6 +10,7 @@ use crate::
|
|||||||
Arc,
|
Arc,
|
||||||
Mutex,
|
Mutex,
|
||||||
VecDeque,
|
VecDeque,
|
||||||
|
HashMap,
|
||||||
info,
|
info,
|
||||||
debug,
|
debug,
|
||||||
warn,
|
warn,
|
||||||
@@ -41,10 +41,11 @@ pub fn token_parse(
|
|||||||
// Get the next token
|
// Get the next token
|
||||||
match tokens.get(index)
|
match tokens.get(index)
|
||||||
{
|
{
|
||||||
|
// Keyword, eg IF, CHOICE or GOTO
|
||||||
Some(tokenise::Token::Keyword(token)) =>
|
Some(tokenise::Token::Keyword(token)) =>
|
||||||
{
|
{
|
||||||
if token.to_lowercase().as_str() == "end" { return Ok(()); }
|
if token.to_lowercase().as_str() == "end" { return Ok(()); }
|
||||||
index = keyword_parse::keyword_parse(tokens, token, index, happening_queue, labels, rx)?;
|
index = keyword_parse::keyword_parse(tokens, token, index, happening_queue, labels, &mut variables, rx)?;
|
||||||
},
|
},
|
||||||
// Ignore closing braces and jump over opening brace blocks
|
// Ignore closing braces and jump over opening brace blocks
|
||||||
Some(tokenise::Token::Bracket((bracket,new_index))) =>
|
Some(tokenise::Token::Bracket((bracket,new_index))) =>
|
||||||
@@ -59,7 +60,7 @@ pub fn token_parse(
|
|||||||
// Handle a character
|
// Handle a character
|
||||||
Some(tokenise::Token::Character(character_name)) =>
|
Some(tokenise::Token::Character(character_name)) =>
|
||||||
{
|
{
|
||||||
index = match character_parse::character_parse(index+1,tokens,character_name.clone(),characters,happening_queue)
|
index = match character_parse::character_parse(index+1,tokens,character_name.clone(),characters,happening_queue,&variables)
|
||||||
{
|
{
|
||||||
Ok(increment) => increment,
|
Ok(increment) => increment,
|
||||||
Err((err,increment)) =>
|
Err((err,increment)) =>
|
||||||
@@ -72,9 +73,9 @@ pub fn token_parse(
|
|||||||
// Identifier
|
// Identifier
|
||||||
Some(tokenise::Token::Identifier(name)) =>
|
Some(tokenise::Token::Identifier(name)) =>
|
||||||
{
|
{
|
||||||
index = match identifier_parse::identifier_parse(index+1,name,tokens,&mut variables)
|
index = match identifier_parse::identifier_parse(index+1,name,tokens,&mut variables,rx,happening_queue)
|
||||||
{
|
{
|
||||||
Ok(increment) => increment,
|
Ok((increment,_)) => increment,
|
||||||
Err((err,increment)) =>
|
Err((err,increment)) =>
|
||||||
{
|
{
|
||||||
warn!("{err}");
|
warn!("{err}");
|
||||||
@@ -82,9 +83,9 @@ pub fn token_parse(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Some(_) =>
|
Some(tok) =>
|
||||||
{
|
{
|
||||||
warn!("Unexpected token");
|
warn!("Unexpected token, at index {index}, expected character, keyword or identifier, got {tok:?}");
|
||||||
index += 1;
|
index += 1;
|
||||||
},
|
},
|
||||||
None => return Err("File unexpectedly reached termination point".to_string()),
|
None => return Err("File unexpectedly reached termination point".to_string()),
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ pub fn character_parse
|
|||||||
character_name: String,
|
character_name: String,
|
||||||
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
|
characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
|
||||||
happening_queue: &Arc<Mutex<VecDeque<api::DataToSend>>>,
|
happening_queue: &Arc<Mutex<VecDeque<api::DataToSend>>>,
|
||||||
|
variables: &HashMap<String, tokenise::Value>,
|
||||||
) -> Result<usize,(String,usize)>
|
) -> Result<usize,(String,usize)>
|
||||||
{
|
{
|
||||||
let mut sum_index: usize = index;
|
let mut sum_index: usize = index;
|
||||||
@@ -45,7 +46,7 @@ pub fn character_parse
|
|||||||
{
|
{
|
||||||
info!("SAYS command with character {character_name}");
|
info!("SAYS command with character {character_name}");
|
||||||
sum_index += 1;
|
sum_index += 1;
|
||||||
let output = tokenise::get_string_token(tokens, sum_index)
|
let output = tokenise::get_string_token(tokens, sum_index, variables)
|
||||||
.map_err(|err| (err, sum_index))?;
|
.map_err(|err| (err, sum_index))?;
|
||||||
debug!("Saying {output}");
|
debug!("Saying {output}");
|
||||||
api::modify_data(happening_queue, "output".to_string(), output, character_name, vec![]);
|
api::modify_data(happening_queue, "output".to_string(), output, character_name, vec![]);
|
||||||
@@ -58,7 +59,7 @@ pub fn character_parse
|
|||||||
let feature = tokenise::get_keyword_token(tokens, sum_index)
|
let feature = tokenise::get_keyword_token(tokens, sum_index)
|
||||||
.map_err(|err| (err, sum_index))?;
|
.map_err(|err| (err, sum_index))?;
|
||||||
sum_index += 1;
|
sum_index += 1;
|
||||||
let string = tokenise::get_string_token(tokens, sum_index)
|
let string = tokenise::get_string_token(tokens, sum_index,variables)
|
||||||
.map_err(|err| (err, sum_index))?;
|
.map_err(|err| (err, 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);
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
use crate::
|
use crate::
|
||||||
{
|
{
|
||||||
// Internal code
|
// Internal code
|
||||||
character,
|
|
||||||
tokenise,
|
tokenise,
|
||||||
UnwrapOrExit,
|
api,
|
||||||
parsing,
|
|
||||||
//Libs
|
//Libs
|
||||||
HashMap,
|
HashMap,
|
||||||
|
Arc,
|
||||||
|
Mutex,
|
||||||
VecDeque,
|
VecDeque,
|
||||||
info,
|
|
||||||
warn,
|
warn,
|
||||||
debug,
|
debug,
|
||||||
|
mpsc::Receiver,
|
||||||
};
|
};
|
||||||
|
use super::keyword_parse;
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
pub fn identifier_parse
|
pub fn identifier_parse
|
||||||
@@ -20,53 +21,146 @@ pub fn identifier_parse
|
|||||||
identifier: &String,
|
identifier: &String,
|
||||||
tokens: &[tokenise::Token],
|
tokens: &[tokenise::Token],
|
||||||
variables: &mut HashMap<String, tokenise::Value>,
|
variables: &mut HashMap<String, tokenise::Value>,
|
||||||
) -> Result<usize,(String,usize)>
|
rx: &Receiver<(usize,String)>,
|
||||||
|
happening_queue: &Arc<Mutex<VecDeque<api::DataToSend>>>,
|
||||||
|
) -> Result<(usize,bool),(String,usize)>
|
||||||
{
|
{
|
||||||
let mut sum_index: usize = index;
|
let mut sum_index: usize = index;
|
||||||
if ! variables.contains_key(identifier)
|
let current = variables
|
||||||
{
|
.entry(identifier.clone())
|
||||||
variables.insert(identifier.to_string(), tokenise::Value::Null);
|
.or_insert(tokenise::Value::Null)
|
||||||
}
|
.clone();
|
||||||
let operator = tokenise::get_operator_token(tokens, sum_index)
|
let operator = tokenise::get_operator_token(tokens, sum_index)
|
||||||
.map_err(|err| (err, sum_index))?;
|
.map_err(|err| (err, sum_index))?;
|
||||||
sum_index += 1;
|
sum_index += 1;
|
||||||
let value = tokenise::get_value_token(tokens, sum_index)
|
let result: bool = match tokenise::get_value_token(tokens, sum_index)
|
||||||
.map_err(|err| (err, sum_index))?;
|
{
|
||||||
|
// An value that can be directly assigned to or compared against the variable
|
||||||
|
Ok(value) =>
|
||||||
|
{
|
||||||
|
sum_index += 1;
|
||||||
|
operator_match(¤t,value,operator,identifier,variables)
|
||||||
|
},
|
||||||
|
// Another thing like a choice or an input
|
||||||
|
Err(_) =>
|
||||||
|
{
|
||||||
|
if operator != tokenise::Operator::Assignment // Only assignment is valid here
|
||||||
|
{
|
||||||
|
return Err((format!("Unexpected operator: {operator:?} at index {}",sum_index-1),sum_index + 1))
|
||||||
|
};
|
||||||
|
let keyword = tokenise::get_keyword_token(tokens,sum_index)
|
||||||
|
.map_err(|err| (err,sum_index))?;
|
||||||
|
match keyword.to_lowercase().as_str()
|
||||||
|
{
|
||||||
|
"choice" =>
|
||||||
|
{
|
||||||
|
let choice: String;
|
||||||
|
(sum_index, choice) = keyword_parse::choice_parse(tokens, index+1, happening_queue,rx,variables)
|
||||||
|
.map_err(|err| (err,sum_index+1))?;
|
||||||
|
variables.insert(identifier.to_owned(), tokenise::Value::String(choice));
|
||||||
|
},
|
||||||
|
"input" =>
|
||||||
|
{
|
||||||
|
api::modify_data(happening_queue, "input".to_string(), String::new(), String::new(), Vec::new());
|
||||||
|
let input = match rx.recv()
|
||||||
|
{
|
||||||
|
Ok((_,input)) => input,
|
||||||
|
Err(err) =>
|
||||||
|
{
|
||||||
|
warn!("Error receiving input from client, defaulting to choice \"\" {err}");
|
||||||
|
"".to_string()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
variables.insert(identifier.to_owned(), tokenise::Value::String(input));
|
||||||
|
},
|
||||||
|
_ =>
|
||||||
|
{
|
||||||
|
warn!("Unexpected keyword {keyword}");
|
||||||
|
},
|
||||||
|
}
|
||||||
|
false
|
||||||
|
},
|
||||||
|
};
|
||||||
|
debug!("{variables:?}");
|
||||||
|
Ok((sum_index,result))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn operator_match
|
||||||
|
(
|
||||||
|
current: &tokenise::Value,
|
||||||
|
value: tokenise::Value,
|
||||||
|
operator: tokenise::Operator,
|
||||||
|
identifier: &String,
|
||||||
|
variables: &mut HashMap<String, tokenise::Value>
|
||||||
|
)
|
||||||
|
-> bool
|
||||||
|
{
|
||||||
|
// Operator match box
|
||||||
match operator
|
match operator
|
||||||
{
|
{
|
||||||
// Changing a value
|
// Changing a value
|
||||||
tokenise::Operator::Assignment =>
|
tokenise::Operator::Assignment =>
|
||||||
{
|
{
|
||||||
variables.insert(identifier.to_string(), value);
|
variables.insert(identifier.to_owned(), value);
|
||||||
} ,
|
} ,
|
||||||
tokenise::Operator::Add =>
|
tokenise::Operator::Add =>
|
||||||
{
|
{
|
||||||
let current = variables.get(identifier).unwrap();
|
|
||||||
let result: tokenise::Value = match (value.clone(), current)
|
let result: tokenise::Value = match (value.clone(), current)
|
||||||
{
|
{
|
||||||
(tokenise::Value::Integer(int1),tokenise::Value::Integer(int2)) => tokenise::Value::Integer(int1 + int2),
|
(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}")),
|
(tokenise::Value::String(str1),tokenise::Value::String(str2)) => tokenise::Value::String(format!("{str1}{str2}")),
|
||||||
_ => value.clone(), // otherwise invalid
|
_ => value, // otherwise invalid
|
||||||
|
|
||||||
};
|
};
|
||||||
variables.insert(identifier.to_string(), result);
|
variables.insert(identifier.to_owned(), result);
|
||||||
},
|
},
|
||||||
tokenise::Operator::Sub =>
|
tokenise::Operator::Sub =>
|
||||||
{
|
{
|
||||||
let current = variables.get(identifier).unwrap();
|
|
||||||
let result: tokenise::Value = match (value.clone(), current)
|
let result: tokenise::Value = match (value.clone(), current)
|
||||||
{
|
{
|
||||||
(tokenise::Value::Integer(int1),tokenise::Value::Integer(int2)) => tokenise::Value::Integer(int2 - int1),
|
(tokenise::Value::Integer(int1),tokenise::Value::Integer(int2)) => tokenise::Value::Integer(int2 - int1),
|
||||||
_ => value.clone(), // otherwise invalid
|
_ => value, // otherwise invalid
|
||||||
|
|
||||||
};
|
};
|
||||||
// TODO comparisons :DDD
|
variables.insert(identifier.to_owned(), result);
|
||||||
variables.insert(identifier.to_string(), result);
|
|
||||||
},
|
},
|
||||||
_ => (),
|
// Comparisons, return a boolean
|
||||||
|
tokenise::Operator::Comparison(comp) =>
|
||||||
|
{
|
||||||
|
let result = match (current, &value)
|
||||||
|
{
|
||||||
|
// Integer
|
||||||
|
(tokenise::Value::Integer(current), tokenise::Value::Integer(comparing)) =>
|
||||||
|
{
|
||||||
|
match comp
|
||||||
|
{
|
||||||
|
tokenise::Comparison::Equate => current == comparing,
|
||||||
|
tokenise::Comparison::Greater => current > comparing,
|
||||||
|
tokenise::Comparison::Less => current < comparing,
|
||||||
|
tokenise::Comparison::GreaterOrEqual => current >= comparing,
|
||||||
|
tokenise::Comparison::LessOrEqual => current <= comparing,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// String
|
||||||
|
(tokenise::Value::String(current), tokenise::Value::String(comparing)) =>
|
||||||
|
{
|
||||||
|
match comp
|
||||||
|
{
|
||||||
|
tokenise::Comparison::Equate => current == comparing,
|
||||||
|
tokenise::Comparison::Greater => current > comparing,
|
||||||
|
tokenise::Comparison::Less => current < comparing,
|
||||||
|
tokenise::Comparison::GreaterOrEqual => current >= comparing,
|
||||||
|
tokenise::Comparison::LessOrEqual => current <= comparing,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
warn!("Invalid comparison of {current:?} and {value:?}, evaluating false");
|
||||||
|
false
|
||||||
|
},
|
||||||
|
};
|
||||||
|
debug!("Comparison {current:?} comp {value:?} evaluates to {result}");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
debug!("{variables:?}");
|
true
|
||||||
sum_index += 1;
|
|
||||||
Ok(sum_index)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use crate::
|
|||||||
info,
|
info,
|
||||||
mpsc::Receiver,
|
mpsc::Receiver,
|
||||||
};
|
};
|
||||||
|
use super::identifier_parse;
|
||||||
|
|
||||||
pub fn keyword_parse(
|
pub fn keyword_parse(
|
||||||
tokens: &[tokenise::Token],
|
tokens: &[tokenise::Token],
|
||||||
@@ -19,6 +20,7 @@ pub fn keyword_parse(
|
|||||||
mut index: usize,
|
mut index: usize,
|
||||||
happening_queue: &Arc<Mutex<VecDeque<api::DataToSend>>>,
|
happening_queue: &Arc<Mutex<VecDeque<api::DataToSend>>>,
|
||||||
labels: &HashMap<String, usize>,
|
labels: &HashMap<String, usize>,
|
||||||
|
variables: &mut HashMap<String, tokenise::Value>,
|
||||||
rx: &Receiver<(usize,String)>,
|
rx: &Receiver<(usize,String)>,
|
||||||
)
|
)
|
||||||
-> Result<usize, String>
|
-> Result<usize, String>
|
||||||
@@ -28,18 +30,54 @@ pub fn keyword_parse(
|
|||||||
{
|
{
|
||||||
"choice" =>
|
"choice" =>
|
||||||
{
|
{
|
||||||
let choice_indeces = choice_parse(tokens, index, happening_queue)?;
|
(index,_) = choice_parse(tokens, index, happening_queue, rx,variables)?;
|
||||||
debug!("{choice_indeces:?}");
|
},
|
||||||
let choice = match rx.recv()
|
"if" =>
|
||||||
|
{
|
||||||
|
// TODO can this go in a function?
|
||||||
|
let mut keyword = "if".to_string();
|
||||||
|
while keyword == "if" || keyword == "elif" || keyword == "else" // TODO less beefy??
|
||||||
{
|
{
|
||||||
Ok((choice,_)) => choice_indeces[choice],
|
index += 1;
|
||||||
Err(err) =>
|
let mut result: bool = true;
|
||||||
|
if keyword != "else"
|
||||||
{
|
{
|
||||||
warn!("Error receiving choice from client, defaulting to choice 0 {err}");
|
let identifier = tokenise::get_identifier_token(tokens, index)?;
|
||||||
0
|
(index,result) = match identifier_parse::identifier_parse(index+1, &identifier, tokens, variables,rx,happening_queue)
|
||||||
|
{
|
||||||
|
Ok((increment, result)) => (increment,result),
|
||||||
|
Err((err,increment)) =>
|
||||||
|
{
|
||||||
|
warn!("{err}");
|
||||||
|
(increment,false)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
if result { index += 1; break; }
|
||||||
index = choice;
|
index = tokenise::get_closing_index(tokens,index)?;
|
||||||
|
index += 1;
|
||||||
|
keyword = match tokenise::get_keyword_token(tokens,index)
|
||||||
|
{
|
||||||
|
Ok(keyword) => keyword,
|
||||||
|
Err(_) => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"else" =>
|
||||||
|
{
|
||||||
|
index += 1;
|
||||||
|
index = tokenise::get_closing_index(tokens, index)?;
|
||||||
|
},
|
||||||
|
"elif" =>
|
||||||
|
{
|
||||||
|
loop
|
||||||
|
{
|
||||||
|
index += 1;
|
||||||
|
let Ok(new_index) = tokenise::get_closing_index(tokens, index)
|
||||||
|
else { continue; };
|
||||||
|
index = new_index;
|
||||||
|
break
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"or" =>
|
"or" =>
|
||||||
{
|
{
|
||||||
@@ -70,8 +108,15 @@ pub fn keyword_parse(
|
|||||||
Ok(index)
|
Ok(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn choice_parse(tokens: &[tokenise::Token], mut index: usize, happening_queue: &Arc<Mutex<VecDeque<api::DataToSend>>>,)
|
pub fn choice_parse
|
||||||
-> Result<Vec<usize>, String>
|
(
|
||||||
|
tokens: &[tokenise::Token],
|
||||||
|
mut index: usize,
|
||||||
|
happening_queue: &Arc<Mutex<VecDeque<api::DataToSend>>>,
|
||||||
|
rx: &Receiver<(usize,String)>,
|
||||||
|
variables: &HashMap<String,tokenise::Value>,
|
||||||
|
)
|
||||||
|
-> Result<(usize,String), String>
|
||||||
{
|
{
|
||||||
let mut next_token: String = "or".to_string();
|
let mut next_token: String = "or".to_string();
|
||||||
let mut choices: Vec<String> = Vec::new();
|
let mut choices: Vec<String> = Vec::new();
|
||||||
@@ -81,7 +126,7 @@ fn choice_parse(tokens: &[tokenise::Token], mut index: usize, happening_queue: &
|
|||||||
index += 1;
|
index += 1;
|
||||||
choices.push
|
choices.push
|
||||||
(
|
(
|
||||||
tokenise::get_string_token(tokens, index)?
|
tokenise::get_string_token(tokens, index,variables)?
|
||||||
);
|
);
|
||||||
index += 1;
|
index += 1;
|
||||||
choice_indeces.push(index+1);
|
choice_indeces.push(index+1);
|
||||||
@@ -96,6 +141,16 @@ fn choice_parse(tokens: &[tokenise::Token], mut index: usize, happening_queue: &
|
|||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
api::modify_data(happening_queue, "choice".to_string(), String::new(), String::new(), choices);
|
api::modify_data(happening_queue, "choice".to_string(), String::new(), String::new(), choices.clone());
|
||||||
Ok(choice_indeces)
|
debug!("{choice_indeces:?}");
|
||||||
|
let choice = match rx.recv()
|
||||||
|
{
|
||||||
|
Ok((choice,_)) => choice,
|
||||||
|
Err(err) =>
|
||||||
|
{
|
||||||
|
warn!("Error receiving choice from client, defaulting to choice 0 {err}");
|
||||||
|
0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok((choice_indeces[choice],choices[choice].clone()))
|
||||||
}
|
}
|
||||||
|
|||||||
+75
-42
@@ -13,7 +13,7 @@ pub enum Token
|
|||||||
Bracket((Bracket,usize)), // Stores the index of the matching deliminator
|
Bracket((Bracket,usize)), // Stores the index of the matching deliminator
|
||||||
Character(String),
|
Character(String),
|
||||||
}
|
}
|
||||||
#[derive(Debug,Clone)]
|
#[derive(Debug,Clone,PartialEq,Eq)]
|
||||||
pub enum Value
|
pub enum Value
|
||||||
{
|
{
|
||||||
String(String),
|
String(String),
|
||||||
@@ -28,43 +28,35 @@ pub enum Bracket
|
|||||||
Closing,
|
Closing,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone,PartialEq)]
|
||||||
pub enum Operator
|
pub enum Operator
|
||||||
{
|
{
|
||||||
// Changing a value
|
// Changing a value
|
||||||
Assignment,
|
Assignment,
|
||||||
Add,
|
Add,
|
||||||
Sub,
|
Sub,
|
||||||
// Comparing a value
|
Comparison(Comparison),
|
||||||
Comparison,
|
}
|
||||||
|
|
||||||
|
// Comparing a value
|
||||||
|
#[derive(Debug,Clone,PartialEq)]
|
||||||
|
pub enum Comparison
|
||||||
|
{
|
||||||
|
Equate,
|
||||||
Greater,
|
Greater,
|
||||||
Less,
|
Less,
|
||||||
GreaterOrEqual,
|
GreaterOrEqual,
|
||||||
LessOrEqual,
|
LessOrEqual,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO error reporting for all of these
|
||||||
pub fn get_operator_token(tokens: &[Token], index: usize)
|
pub fn get_operator_token(tokens: &[Token], index: usize)
|
||||||
-> Result<Operator, String>
|
-> Result<Operator, String>
|
||||||
{
|
{
|
||||||
match tokens.get(index) {
|
match tokens.get(index) {
|
||||||
Some(Token::Operator(op)) => Ok(op.clone()),
|
Some(Token::Operator(op)) => Ok(op.clone()),
|
||||||
Some(_) => Err("Unexpected token".to_string()),
|
Some(tok) => Err(format!("Unexpected token at index {index}, expected operator, got {tok:?}")),
|
||||||
None => Err("File unexpectedly reached termination point".to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn get_string_token(tokens: &[Token], index: usize)
|
|
||||||
-> Result<String, String>
|
|
||||||
{
|
|
||||||
match tokens.get(index) {
|
|
||||||
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()),
|
None => Err("File unexpectedly reached termination point".to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,7 +65,7 @@ pub fn get_keyword_token(tokens: &[Token], index: usize)
|
|||||||
{
|
{
|
||||||
match tokens.get(index) {
|
match tokens.get(index) {
|
||||||
Some(Token::Keyword(s)) => Ok(s.clone()),
|
Some(Token::Keyword(s)) => Ok(s.clone()),
|
||||||
Some(_) => Err("Unexpected token".to_string()),
|
Some(tok) => Err(format!("Unexpected token at index {index}, expected keyword, got {tok:?}")),
|
||||||
None => Err("File unexpectedly reached termination point".to_string()),
|
None => Err("File unexpectedly reached termination point".to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +74,7 @@ pub fn get_closing_index(tokens: &[Token], index: usize)
|
|||||||
{
|
{
|
||||||
match tokens.get(index) {
|
match tokens.get(index) {
|
||||||
Some(Token::Bracket((_, index))) => Ok(*index), // TODO check for closing
|
Some(Token::Bracket((_, index))) => Ok(*index), // TODO check for closing
|
||||||
Some(_) => Err("Unexpected token".to_string()),
|
Some(tok) => Err(format!("Unexpected token at index {index}, expected opening brace, got {tok:?}")),
|
||||||
None => Err("File unexpectedly reached termination point".to_string()),
|
None => Err("File unexpectedly reached termination point".to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,7 +83,44 @@ pub fn get_value_token(tokens: &[Token], index: usize)
|
|||||||
{
|
{
|
||||||
match tokens.get(index) {
|
match tokens.get(index) {
|
||||||
Some(Token::Value(val)) => Ok(val.clone()),
|
Some(Token::Value(val)) => Ok(val.clone()),
|
||||||
Some(_) => Err("Unexpected token".to_string()),
|
Some(tok) => Err(format!("Unexpected token at index {index}, expected value (int, string or boolean), got {tok:?}")),
|
||||||
|
None => Err("File unexpectedly reached termination point".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn get_identifier_token(tokens: &[Token], index: usize)
|
||||||
|
-> Result<String, String>
|
||||||
|
{
|
||||||
|
match tokens.get(index) {
|
||||||
|
Some(Token::Identifier(s)) => Ok(s.clone()),
|
||||||
|
Some(tok) => Err(format!("Unexpected token at index {index}, expected identifier, got {tok:?}")),
|
||||||
|
None => Err("File unexpectedly reached termination point".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn get_string_token(tokens: &[Token], index: usize, variables: &HashMap<String, Value>)
|
||||||
|
-> Result<String, String>
|
||||||
|
{
|
||||||
|
match tokens.get(index) {
|
||||||
|
// Either get string directly
|
||||||
|
Some(Token::Value(val)) =>
|
||||||
|
{
|
||||||
|
match val
|
||||||
|
{
|
||||||
|
Value::String(s) => Ok(s.clone()),
|
||||||
|
_ => Err("Unexpected value type".to_string()),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Or get the string that the identifier references
|
||||||
|
Some(Token::Identifier(iden)) =>
|
||||||
|
{
|
||||||
|
let val = variables.get(iden)
|
||||||
|
.ok_or(format!("Variable {iden} not initialised"))?;
|
||||||
|
match val
|
||||||
|
{
|
||||||
|
Value::String(s) => Ok(s.clone()),
|
||||||
|
_ => Err("Unexpected value type".to_string()),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Some(tok) => Err(format!("Unexpected token at index {index}, expected string value, got {tok:?}")),
|
||||||
None => Err("File unexpectedly reached termination point".to_string()),
|
None => Err("File unexpectedly reached termination point".to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,22 +147,18 @@ pub fn tokenise(file_contents: &str)
|
|||||||
"=" => Some(Operator::Assignment),
|
"=" => Some(Operator::Assignment),
|
||||||
"+" => Some(Operator::Add),
|
"+" => Some(Operator::Add),
|
||||||
"-" => Some(Operator::Sub),
|
"-" => Some(Operator::Sub),
|
||||||
"==" => Some(Operator::Comparison),
|
"==" => Some(Operator::Comparison(Comparison::Equate)),
|
||||||
">" => Some(Operator::Greater),
|
">" => Some(Operator::Comparison(Comparison::Greater)),
|
||||||
"<" => Some(Operator::Less),
|
"<" => Some(Operator::Comparison(Comparison::Less)),
|
||||||
">=" => Some(Operator::GreaterOrEqual),
|
">=" => Some(Operator::Comparison(Comparison::GreaterOrEqual)),
|
||||||
"<=" => Some(Operator::LessOrEqual),
|
"<=" => Some(Operator::Comparison(Comparison::LessOrEqual)),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
match op
|
if let Some(op) = op
|
||||||
{
|
{
|
||||||
Some(op) =>
|
tokenised_data.push(Token::Operator(op));
|
||||||
{
|
index += 1;
|
||||||
tokenised_data.push(Token::Operator(op));
|
continue // skip the rest of this loop
|
||||||
index += 1;
|
|
||||||
continue // skip the rest of this loop
|
|
||||||
},
|
|
||||||
None => (),
|
|
||||||
}
|
}
|
||||||
// Characters
|
// Characters
|
||||||
if item.starts_with('@')
|
if item.starts_with('@')
|
||||||
@@ -151,18 +176,26 @@ pub fn tokenise(file_contents: &str)
|
|||||||
item = new_item;
|
item = new_item;
|
||||||
tokenised_data.push(Token::Value(Value::String(item)));
|
tokenised_data.push(Token::Value(Value::String(item)));
|
||||||
}
|
}
|
||||||
|
else if let Ok(value) = item.parse::<i64>()
|
||||||
|
{
|
||||||
|
tokenised_data.push(Token::Value(Value::Integer(value))); // unwrap is fine here because I checked
|
||||||
|
}
|
||||||
|
else if item == "true"
|
||||||
|
{
|
||||||
|
tokenised_data.push(Token::Value(Value::Bool(true)));
|
||||||
|
}
|
||||||
|
else if item == "false"
|
||||||
|
{
|
||||||
|
tokenised_data.push(Token::Value(Value::Bool(false)));
|
||||||
|
}
|
||||||
// variable/identifier
|
// variable/identifier
|
||||||
else if item.starts_with("$")
|
else if item.starts_with('$')
|
||||||
{
|
{
|
||||||
let mut chars = item.chars();
|
let mut chars = item.chars();
|
||||||
chars.next();
|
chars.next();
|
||||||
tokenised_data.push(Token::Identifier(chars.as_str().to_string()));
|
tokenised_data.push(Token::Identifier(chars.as_str().to_string()));
|
||||||
}
|
}
|
||||||
// Integer
|
// Integer
|
||||||
else if item.parse::<i64>().is_ok()
|
|
||||||
{
|
|
||||||
tokenised_data.push(Token::Value(Value::Integer(item.parse::<i64>().unwrap()))); // unwrap is fine here because I checked
|
|
||||||
}
|
|
||||||
// Labels
|
// Labels
|
||||||
else if item.ends_with(':')
|
else if item.ends_with(':')
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"pronoun_deppos": "His",
|
"pronoun_deppos": "His",
|
||||||
"pronoun_indpos": "His",
|
"pronoun_indpos": "His",
|
||||||
"pronoun_reflex": "Himself",
|
"pronoun_reflex": "Himself",
|
||||||
"head_shape": "",
|
"head_shape": "normal-male",
|
||||||
"hair_style": "",
|
"hair_style": "",
|
||||||
"torso_shape": "",
|
"torso_shape": "",
|
||||||
"arm_shape": "",
|
"arm_shape": "",
|
||||||
|
|||||||
+14
-4
@@ -1,10 +1,20 @@
|
|||||||
@tim says "hello world, it's a good day"
|
$name = input
|
||||||
@tim change name "Timothy Fineshooter"
|
@tim says "hello"
|
||||||
|
@tim says $name
|
||||||
$x = 3
|
$x = 3
|
||||||
$x + 1
|
$x + 1
|
||||||
$x - 2
|
if $x == 4 {
|
||||||
|
@tim says "5"
|
||||||
|
}
|
||||||
|
elif $x < 5 {
|
||||||
|
|
||||||
|
@tim says "<5"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
@tim says "whar"
|
||||||
|
}
|
||||||
label:
|
label:
|
||||||
choice "choice numero uno" {
|
$choice_string = choice "choice numero uno" {
|
||||||
@tim says "super sad"
|
@tim says "super sad"
|
||||||
}
|
}
|
||||||
or "choice numero duo" {
|
or "choice numero duo" {
|
||||||
|
|||||||
Binary file not shown.
@@ -44,6 +44,12 @@ def choice(choices):
|
|||||||
print("Invalid choice, defaulting to 0")
|
print("Invalid choice, defaulting to 0")
|
||||||
requests.post(api_url, json=choice);
|
requests.post(api_url, json=choice);
|
||||||
|
|
||||||
|
def get_input():
|
||||||
|
api_url = "http://localhost:20264/input"
|
||||||
|
input_string = input()
|
||||||
|
requests.post(api_url, json=input_string);
|
||||||
|
|
||||||
|
|
||||||
# Character outputs text to the user
|
# Character outputs text to the user
|
||||||
def output(character, text):
|
def output(character, text):
|
||||||
print(character["name"], "says")
|
print(character["name"], "says")
|
||||||
|
|||||||
Reference in New Issue
Block a user