Compare commits

...

4 Commits

Author SHA1 Message Date
deadvey cc3eca857d strings in variables can now be received by get_string_token
and inputs can be directly assigned to a variable
2026-05-26 20:35:57 +01:00
deadvey f6a95f76bd Added support for assigning variables to the output of a choice 2026-05-26 17:48:36 +01:00
deadvey 59f32e975b clippy lints and moved the operator matchbox to it's own function 2026-05-26 11:54:53 +01:00
deadvey 4f7abb5f19 added support for if elif else statements by returning a boolean
from the identifier syntax parsing
2026-05-26 11:38:14 +01:00
14 changed files with 307 additions and 97 deletions
+1 -1
View File
@@ -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
View File
@@ -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/"
+1
View File
@@ -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
View File
@@ -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
+8 -7
View File
@@ -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()),
+3 -2
View File
@@ -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);
+118 -24
View File
@@ -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(&current,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)
} }
+69 -14
View File
@@ -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()))
} }
View File
+75 -42
View File
@@ -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(':')
{ {
+1 -1
View File
@@ -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
View File
@@ -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" {
BIN
View File
Binary file not shown.
+6
View File
@@ -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")