diff --git a/renrs/src/parser/block.rs b/renrs/src/parser/block.rs index 3ff889d..0f14df5 100644 --- a/renrs/src/parser/block.rs +++ b/renrs/src/parser/block.rs @@ -2,7 +2,7 @@ use debug_cell::RefCell; use std::{collections::HashMap, rc::Rc}; use super::{ - command::{parse_command, Command}, + command::{parse_command, Command, AssignType}, control::{parse_control, Control}, event::Event, token::Token, @@ -25,41 +25,50 @@ pub struct CommandContext { impl CommandContext { pub fn execute(&self) -> Option { use Command::*; + use AssignType::*; 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() - .borrow_mut() - .insert(variable.clone(), value.clone()); - return None; - }, - Let { variable, value } => { - if let Token::Keyword(_) = value { - todo!("assignment variable interpolation isn't implemented"); - } - self.context - .borrow() - .variables - .borrow_mut() - .insert(variable.clone(), value.clone()); - return None; + Command::Assign { assign_type, variable, value } => match assign_type { + Define => panic!("define command should not be executed at runtime!"), + GlobalAssign => { + 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() + .borrow_mut() + .insert(variable.clone(), value.clone()); + return None; + }, + Let => { + if let Token::Keyword(_) = value { + todo!("assignment variable interpolation isn't implemented"); + } + self.context + .borrow() + .variables + .borrow_mut() + .insert(variable.clone(), value.clone()); + return None; + }, + Assign => { + if let Token::Keyword(_) = value { + todo!("assignment variable interpolation isn't implemented"); + } + todo!("local variable assignment isn't implemented") + }, } Eat { .. } => return None, } @@ -178,7 +187,7 @@ pub fn parse_block( continue; } Rule::Line => BlockElement::Command(match parse_command(pair) { - Command::Define { variable, value } => { + Command::Assign { variable, value, assign_type: AssignType::Define } => { let mut value = value; if let Token::Keyword(keyword) = value { value = definitions diff --git a/renrs/src/parser/command.rs b/renrs/src/parser/command.rs index 4026d45..99c886e 100644 --- a/renrs/src/parser/command.rs +++ b/renrs/src/parser/command.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use super::{ token::Token, utils::{describe_line, parse_line}, @@ -7,11 +9,41 @@ use super::{ #[derive(Debug, Clone)] #[allow(dead_code)] pub enum Command { - Say { name: Option, text: String }, - Eat { food: String, politely: bool }, - Define { variable: String, value: Token }, - Assign { variable: String, value: Token }, - Let { variable: String, value: Token }, + Say { + name: Option, + text: String, + }, + Eat { + food: String, + politely: bool, + }, + Assign { + assign_type: AssignType, + variable: String, + value: Token, + }, +} + +#[derive(Debug, Clone)] +pub enum AssignType { + Define, + GlobalAssign, + Let, + Assign, +} + +impl FromStr for AssignType { + type Err = (); + + fn from_str(s: &str) -> Result { + use AssignType::*; + Ok(match s { + "define" => Define, + "$" => GlobalAssign, + "let" => Let, + _ => return Err(()), + }) + } } pub fn parse_command(pair: Pair) -> Command { @@ -32,26 +64,15 @@ pub fn parse_command(pair: Pair) -> Command { name: Some(name.clone()), text: text.clone(), }, + // https://github.com/rust-lang/rust/issues/51114 [Keyword(keyword), Keyword(variable), Keyword(equals), value] - if keyword.eq("define") && equals.eq("=") => - { - Define { - variable: variable.clone(), - value: value.clone(), - } - } - [Keyword(keyword), Keyword(variable), Keyword(equals), value] - if keyword.eq("$") && equals.eq("=") => + if equals.eq("=") => { Assign { - variable: variable.clone(), - value: value.clone(), - } - } - [Keyword(keyword), Keyword(variable), Keyword(equals), value] - if keyword.eq("let") && equals.eq("=") => - { - Let { + assign_type: match keyword.parse() { + Ok(assign_type) => assign_type, + Err(_) => unknown!(), + }, variable: variable.clone(), value: value.clone(), } diff --git a/renrs/src/parser/token.rs b/renrs/src/parser/token.rs index 32660f5..ee58af4 100644 --- a/renrs/src/parser/token.rs +++ b/renrs/src/parser/token.rs @@ -78,6 +78,6 @@ pub fn parse_token(pair: Pair) -> Token { }), Rule::Number => Token::Number(pair.as_str().parse().unwrap()), Rule::Keyword => Token::Keyword(pair.as_str().to_owned()), - __ => unreachable!(), + _ => unreachable!(), } }