generated from ElnuDev/rust-project
Implement basic variable assignment
This commit is contained in:
parent
7e09389c1e
commit
2735a391b8
8 changed files with 167 additions and 45 deletions
70
Cargo.lock
generated
70
Cargo.lock
generated
|
@ -18,6 +18,21 @@ version = "0.1.8"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "ahash"
|
||||
version = "0.8.3"
|
||||
|
@ -50,6 +65,21 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
|
@ -96,6 +126,15 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "debug-cell"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35ee4fc02f25a0400fb57135bcdde6d58a3025718749375f2f97abc3deb3a4ef"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
|
@ -199,6 +238,12 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.27.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
||||
|
||||
[[package]]
|
||||
name = "glu-sys"
|
||||
version = "0.1.4"
|
||||
|
@ -286,6 +331,15 @@ version = "2.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "nohash-hasher"
|
||||
version = "0.2.0"
|
||||
|
@ -301,6 +355,15 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.30.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.2"
|
||||
|
@ -431,6 +494,7 @@ checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
|
|||
name = "renrs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"debug-cell",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
"regex",
|
||||
|
@ -453,6 +517,12 @@ dependencies = [
|
|||
"sfml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.19"
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
# 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]"
|
||||
define foo = "bar"
|
||||
if False:
|
||||
|
|
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
debug-cell = "0.1.1"
|
||||
pest = "2.6.0"
|
||||
pest_derive = "2.6.0"
|
||||
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;
|
||||
use parser::block::CommandBlock;
|
||||
use parser::command::Command;
|
||||
use parser::block::{CommandBlock, CommandContext};
|
||||
use parser::event::Event;
|
||||
use parser::parse_file;
|
||||
|
||||
|
@ -19,7 +20,7 @@ impl State {
|
|||
|
||||
pub fn next(&mut self) -> Option<Event> {
|
||||
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()) {
|
||||
return event;
|
||||
}
|
||||
|
@ -27,7 +28,7 @@ impl State {
|
|||
None
|
||||
}
|
||||
|
||||
fn next_command(&mut self) -> Option<Command> {
|
||||
self.script.borrow_mut().next()
|
||||
fn next_command(&mut self) -> Option<CommandContext> {
|
||||
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::{
|
||||
command::{parse_command, Command},
|
||||
control::{parse_control, Control},
|
||||
token::Token,
|
||||
Pair, Rule,
|
||||
Pair, Rule, event::Event,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CommandBlock {
|
||||
parent: Option<Rc<RefCell<CommandBlock>>>,
|
||||
control: Option<Control>,
|
||||
elements: Vec<BlockElement>,
|
||||
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 {
|
||||
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 {
|
||||
Some(next) => next,
|
||||
None => return None,
|
||||
|
@ -30,13 +74,16 @@ impl CommandBlock {
|
|||
for element in &mut self.elements[next..] {
|
||||
match element {
|
||||
BlockElement::Command(command) => {
|
||||
result = Some(command.clone());
|
||||
result = Some(CommandContext {
|
||||
context: self_rc.clone(),
|
||||
command: command.clone(),
|
||||
});
|
||||
next += 1;
|
||||
break;
|
||||
}
|
||||
BlockElement::Block(block) => match block.borrow_mut().next() {
|
||||
Some(command) => {
|
||||
result = Some(command.clone());
|
||||
BlockElement::Block(block) => match block.borrow_mut().next(&block) {
|
||||
Some(context_command) => {
|
||||
result = Some(context_command);
|
||||
break;
|
||||
}
|
||||
None => {
|
||||
|
@ -71,6 +118,14 @@ impl CommandBlock {
|
|||
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 {
|
||||
|
@ -85,7 +140,6 @@ impl Default for CommandBlock {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum BlockElement {
|
||||
Command(Command),
|
||||
Block(Rc<RefCell<CommandBlock>>),
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use super::{
|
||||
block::CommandBlock,
|
||||
event::Event,
|
||||
token::Token,
|
||||
utils::{describe_line, parse_line},
|
||||
Pair,
|
||||
|
@ -14,23 +10,7 @@ pub enum Command {
|
|||
Say { name: Option<String>, text: String },
|
||||
Eat { food: String, politely: bool },
|
||||
Define { 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),
|
||||
)
|
||||
}
|
||||
Assign { variable: String, value: Token },
|
||||
}
|
||||
|
||||
pub fn parse_command(pair: Pair) -> Command {
|
||||
|
@ -45,20 +25,28 @@ pub fn parse_command(pair: Pair) -> Command {
|
|||
match line.as_slice() {
|
||||
[Str(text)] => Say {
|
||||
name: None,
|
||||
text: text.to_owned(),
|
||||
text: text.clone(),
|
||||
},
|
||||
[Str(name), Str(text)] => Say {
|
||||
name: Some(name.to_owned()),
|
||||
text: text.to_owned(),
|
||||
name: Some(name.clone()),
|
||||
text: text.clone(),
|
||||
},
|
||||
[Keyword(keyword), Keyword(variable), Keyword(equals), value]
|
||||
if keyword.eq("define") && equals.eq("=") =>
|
||||
{
|
||||
Define {
|
||||
variable: variable.to_owned(),
|
||||
variable: variable.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 {
|
||||
food: food.to_owned(),
|
||||
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;
|
||||
|
||||
|
@ -27,7 +28,7 @@ impl Event {
|
|||
.as_deref()
|
||||
.map(|name| interpolate_string(&name, &variables));
|
||||
*text = interpolate_string(&text, &variables);
|
||||
}
|
||||
},
|
||||
}
|
||||
self
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ mod utils;
|
|||
|
||||
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;
|
||||
use pest_derive::Parser;
|
||||
|
|
Loading…
Add table
Reference in a new issue