Implement basic variable assignment

main
Elnu 2 years ago
parent 7e09389c1e
commit 2735a391b8

70
Cargo.lock generated

@ -18,6 +18,21 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"
[[package]]
name = "addr2line"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]] [[package]]
name = "ahash" name = "ahash"
version = "0.8.3" version = "0.8.3"
@ -50,6 +65,21 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -96,6 +126,15 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "debug-cell"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35ee4fc02f25a0400fb57135bcdde6d58a3025718749375f2f97abc3deb3a4ef"
dependencies = [
"backtrace",
]
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.10.7" version = "0.10.7"
@ -199,6 +238,12 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "gimli"
version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
[[package]] [[package]]
name = "glu-sys" name = "glu-sys"
version = "0.1.4" version = "0.1.4"
@ -286,6 +331,15 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "miniz_oxide"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]] [[package]]
name = "nohash-hasher" name = "nohash-hasher"
version = "0.2.0" version = "0.2.0"
@ -301,6 +355,15 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "object"
version = "0.30.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.2" version = "1.17.2"
@ -431,6 +494,7 @@ checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
name = "renrs" name = "renrs"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"debug-cell",
"pest", "pest",
"pest_derive", "pest_derive",
"regex", "regex",
@ -453,6 +517,12 @@ dependencies = [
"sfml", "sfml",
] ]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.37.19" version = "0.37.19"

@ -1,4 +1,10 @@
# Control testing # Control testing
$ x = "3"
"Bob will be here in [x] seconds."
$ x = "2"
"Bob will be here in [x] seconds."
$ x = "1"
"Bob will be here in [x] seconds."
"Bob" "I will not say anything, [foo]" "Bob" "I will not say anything, [foo]"
define foo = "bar" define foo = "bar"
if False: if False:

@ -7,6 +7,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
debug-cell = "0.1.1"
pest = "2.6.0" pest = "2.6.0"
pest_derive = "2.6.0" pest_derive = "2.6.0"
regex = "1.8.3" regex = "1.8.3"

@ -1,8 +1,9 @@
use std::{cell::RefCell, path::PathBuf, rc::Rc}; use debug_cell::RefCell;
use std::path::PathBuf;
use std::rc::Rc;
pub mod parser; pub mod parser;
use parser::block::CommandBlock; use parser::block::{CommandBlock, CommandContext};
use parser::command::Command;
use parser::event::Event; use parser::event::Event;
use parser::parse_file; use parser::parse_file;
@ -19,7 +20,7 @@ impl State {
pub fn next(&mut self) -> Option<Event> { pub fn next(&mut self) -> Option<Event> {
while let Some(command) = self.next_command() { while let Some(command) = self.next_command() {
let event = command.execute(&self.script); let event = command.execute();
if event.as_ref().map_or(false, |event| event.is_blocking()) { if event.as_ref().map_or(false, |event| event.is_blocking()) {
return event; return event;
} }
@ -27,7 +28,7 @@ impl State {
None None
} }
fn next_command(&mut self) -> Option<Command> { fn next_command(&mut self) -> Option<CommandContext> {
self.script.borrow_mut().next() self.script.borrow_mut().next(&self.script)
} }
} }

@ -1,23 +1,67 @@
use std::{cell::RefCell, collections::HashMap, rc::Rc}; use std::{collections::HashMap, rc::Rc};
use debug_cell::RefCell;
use super::{ use super::{
command::{parse_command, Command}, command::{parse_command, Command},
control::{parse_control, Control}, control::{parse_control, Control},
token::Token, token::Token,
Pair, Rule, Pair, Rule, event::Event,
}; };
#[derive(Debug)]
pub struct CommandBlock { pub struct CommandBlock {
parent: Option<Rc<RefCell<CommandBlock>>>, parent: Option<Rc<RefCell<CommandBlock>>>,
control: Option<Control>, control: Option<Control>,
elements: Vec<BlockElement>, elements: Vec<BlockElement>,
next: Option<usize>, next: Option<usize>,
variables: Option<Rc<RefCell<HashMap<String, Token>>>>, pub variables: Option<Rc<RefCell<HashMap<String, Token>>>>,
}
pub struct CommandContext {
pub context: Rc<RefCell<CommandBlock>>,
pub command: Command,
}
impl CommandContext {
pub fn execute(&self) -> Option<Event> {
use Command::*;
Some(
match &self.command {
Say { name, text } => Event::Say {
name: name.clone(),
text: text.clone(),
},
Define { .. } => panic!("define command should not be executed at runtime!"),
Assign { variable, value } => {
if let Token::Keyword(_) = value {
todo!("assignment variable interpolation isn't implemented");
}
let root = self.context
.borrow()
.get_root(&self.context);
// Don't want to re-borrow if root is self
let root = if Rc::ptr_eq(&self.context, &root) {
&self.context
} else {
&root
};
root
.borrow_mut()
.variables
.as_ref()
.unwrap()
.borrow_mut()
.insert(variable.clone(), value.clone());
return None;
},
Eat { .. } => return None,
}
.process(&self.context),
)
}
} }
impl CommandBlock { impl CommandBlock {
pub fn next(&mut self) -> Option<Command> { pub fn next<'a>(&mut self, self_rc: &Rc<RefCell<Self>>) -> Option<CommandContext> {
let mut next = match self.next { let mut next = match self.next {
Some(next) => next, Some(next) => next,
None => return None, None => return None,
@ -30,13 +74,16 @@ impl CommandBlock {
for element in &mut self.elements[next..] { for element in &mut self.elements[next..] {
match element { match element {
BlockElement::Command(command) => { BlockElement::Command(command) => {
result = Some(command.clone()); result = Some(CommandContext {
context: self_rc.clone(),
command: command.clone(),
});
next += 1; next += 1;
break; break;
} }
BlockElement::Block(block) => match block.borrow_mut().next() { BlockElement::Block(block) => match block.borrow_mut().next(&block) {
Some(command) => { Some(context_command) => {
result = Some(command.clone()); result = Some(context_command);
break; break;
} }
None => { None => {
@ -71,6 +118,14 @@ impl CommandBlock {
None => HashMap::new(), None => HashMap::new(),
} }
} }
pub fn get_root(&self, self_rc: &Rc<RefCell<Self>>) -> Rc<RefCell<Self>> {
if let Some(parent) = &self.parent {
parent.borrow().get_root(&parent)
} else {
self_rc.clone()
}
}
} }
impl Default for CommandBlock { impl Default for CommandBlock {
@ -85,7 +140,6 @@ impl Default for CommandBlock {
} }
} }
#[derive(Debug)]
enum BlockElement { enum BlockElement {
Command(Command), Command(Command),
Block(Rc<RefCell<CommandBlock>>), Block(Rc<RefCell<CommandBlock>>),

@ -1,8 +1,4 @@
use std::{cell::RefCell, rc::Rc};
use super::{ use super::{
block::CommandBlock,
event::Event,
token::Token, token::Token,
utils::{describe_line, parse_line}, utils::{describe_line, parse_line},
Pair, Pair,
@ -14,23 +10,7 @@ pub enum Command {
Say { name: Option<String>, text: String }, Say { name: Option<String>, text: String },
Eat { food: String, politely: bool }, Eat { food: String, politely: bool },
Define { variable: String, value: Token }, Define { variable: String, value: Token },
} Assign { variable: String, value: Token },
impl Command {
pub fn execute(&self, context: &Rc<RefCell<CommandBlock>>) -> Option<Event> {
use Command::*;
Some(
match self {
Say { name, text } => Event::Say {
name: name.clone(),
text: text.clone(),
},
Define { .. } => panic!("define command should not be executed at runtime!"),
Eat { .. } => return None,
}
.process(context),
)
}
} }
pub fn parse_command(pair: Pair) -> Command { pub fn parse_command(pair: Pair) -> Command {
@ -45,20 +25,28 @@ pub fn parse_command(pair: Pair) -> Command {
match line.as_slice() { match line.as_slice() {
[Str(text)] => Say { [Str(text)] => Say {
name: None, name: None,
text: text.to_owned(), text: text.clone(),
}, },
[Str(name), Str(text)] => Say { [Str(name), Str(text)] => Say {
name: Some(name.to_owned()), name: Some(name.clone()),
text: text.to_owned(), text: text.clone(),
}, },
[Keyword(keyword), Keyword(variable), Keyword(equals), value] [Keyword(keyword), Keyword(variable), Keyword(equals), value]
if keyword.eq("define") && equals.eq("=") => if keyword.eq("define") && equals.eq("=") =>
{ {
Define { Define {
variable: variable.to_owned(), variable: variable.clone(),
value: value.clone(), value: value.clone(),
} }
},
[Keyword(keyword), Keyword(variable), Keyword(equals), value]
if keyword.eq("$") && equals.eq("=") =>
{
Assign {
variable: variable.clone(),
value: value.clone(),
} }
},
[Keyword(keyword), Str(food), tail @ ..] if keyword.eq("eat") => Eat { [Keyword(keyword), Str(food), tail @ ..] if keyword.eq("eat") => Eat {
food: food.to_owned(), food: food.to_owned(),
politely: match tail { politely: match tail {

@ -1,4 +1,5 @@
use std::{cell::RefCell, collections::HashMap, rc::Rc}; use std::{collections::HashMap, rc::Rc};
use debug_cell::RefCell;
use regex::Regex; use regex::Regex;
@ -27,7 +28,7 @@ impl Event {
.as_deref() .as_deref()
.map(|name| interpolate_string(&name, &variables)); .map(|name| interpolate_string(&name, &variables));
*text = interpolate_string(&text, &variables); *text = interpolate_string(&text, &variables);
} },
} }
self self
} }

@ -7,7 +7,8 @@ mod utils;
pub type Pair<'a> = pest::iterators::Pair<'a, Rule>; pub type Pair<'a> = pest::iterators::Pair<'a, Rule>;
use std::{cell::RefCell, fs, path::PathBuf, rc::Rc}; use std::{fs, path::PathBuf, rc::Rc};
use debug_cell::RefCell;
pub use pest::Parser; pub use pest::Parser;
use pest_derive::Parser; use pest_derive::Parser;

Loading…
Cancel
Save