diff --git a/src/lib.rs b/src/lib.rs index abd9e39..c1d06e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,34 @@ use std::collections::HashMap; +#[derive(Debug, PartialEq, Clone)] +pub enum Operator { + SetVariable, + Increment, + Decrement, + Print, + NewLabel, + UnconditionalJump, + JumpIfLessThan, + JumpIfGreaterThan, + JumpIfEqualTo, + ArithmeticAdd, + ArithmeticSubtract, + ArithmeticMultiply, + ArithmeticDivide, + TakeInput, + Comment, + StringConcatenation, + ExplicitExit, + TypeCheck, + StackPush, + Return, + VariableClone, + VariableDrop, +} + #[derive(Debug)] pub struct Statement { - pub operator: String, + pub operator: Operator, pub arguments: Vec, } @@ -14,7 +40,7 @@ pub struct Program { pub fn parse(data: &str) -> Result { let mut program_begun = false; - let mut operator: Option = None; + let mut operator: Option = None; let mut arguments: Vec = vec![]; let mut expected_arguments: i32 = -1; let mut argument_builder: String = "".to_string(); @@ -29,10 +55,9 @@ pub fn parse(data: &str) -> Result { program_begun = true; } else if program_begun { if operator.is_none() { - let potential_argument_length = operator_to_arglength(char.clone()); + let (operator, potential_argument_length) = operator_to_arglength(char.clone()); if potential_argument_length.is_none() { return Err(format!("Invalid operator {} at statement {}.", char, statements.len())); } expected_arguments = potential_argument_length.unwrap(); - operator = Some(char.to_string()); } else if expected_arguments > 0 { if inside_string { if char == '"' && !string_escape { @@ -58,7 +83,7 @@ pub fn parse(data: &str) -> Result { arguments.push(argument_builder); argument_builder = "".to_string(); if expected_arguments != 0 { - return Err(format!("Invalid amount of arguments for operator {} at {}.", operator.unwrap(), statements.len())); + return Err(format!("Invalid amount of arguments for operator {:?} at {}.", operator.unwrap(), statements.len())); } } else if char == '"' { if argument_builder.len() != 0 { return Err(format!("Cannot start string where argument already exists at {}.", statements.len())); } @@ -72,7 +97,7 @@ pub fn parse(data: &str) -> Result { if operator.is_some() && char == ':' && !inside_string { let new_statement = Statement { operator: operator.clone().unwrap(), arguments: arguments.clone() }; statements.push(new_statement); - if operator.clone().unwrap() == "@" { + if operator.clone().unwrap() == Operator::NewLabel { labels.insert(statements[statements.len()-1].arguments[0].clone(), statements.len()-1); } operator = None; @@ -88,7 +113,7 @@ pub fn parse(data: &str) -> Result { } if expected_arguments != 0 { - return Err(format!("Invalid amount of arguments for operator {} at {}.", operator.unwrap(), statements.len())); + return Err(format!("Invalid amount of arguments for operator {:?} at {}.", operator.unwrap(), statements.len())); } let new_statement = Statement { operator: operator.unwrap().clone(), arguments: arguments.clone() }; statements.push(new_statement); @@ -98,30 +123,30 @@ pub fn parse(data: &str) -> Result { Ok(program) } -fn operator_to_arglength(operator: char) -> Option { +fn operator_to_arglength(operator: char) -> (Option, Option) { match operator { - '>' => Some(2), - '?' => Some(1), - '!' => Some(1), - '~' => Some(0), - '<' => Some(1), - '^' => Some(1), - 'v' => Some(1), - '@' => Some(1), - '+' => Some(3), - '-' => Some(3), - '=' => Some(3), - '*' => Some(3), - 'a' => Some(3), - 's' => Some(3), - 'm' => Some(3), - 'd' => Some(3), - '0' => Some(1), - '&' => Some(2), - '$' => Some(1), - '%' => Some(2), - '#' => Some(0), - '|' => Some(0), - _ => None, + '>' => (Some(Operator::SetVariable), Some(2)), + '?' => (Some(Operator::TakeInput), Some(1)), + '!' => (Some(Operator::Print), Some(1)), + '~' => (Some(Operator::ExplicitExit), Some(0)), + '<' => (Some(Operator::UnconditionalJump), Some(1)), + '^' => (Some(Operator::Increment), Some(1)), + 'v' => (Some(Operator::Decrement), Some(1)), + '@' => (Some(Operator::NewLabel), Some(1)), + '+' => (Some(Operator::JumpIfGreaterThan), Some(3)), + '-' => (Some(Operator::JumpIfLessThan), Some(3)), + '=' => (Some(Operator::JumpIfEqualTo), Some(3)), + '*' => (Some(Operator::StringConcatenation), Some(3)), + 'a' => (Some(Operator::ArithmeticAdd), Some(3)), + 's' => (Some(Operator::ArithmeticSubtract), Some(3)), + 'm' => (Some(Operator::ArithmeticMultiply), Some(3)), + 'd' => (Some(Operator::ArithmeticDivide), Some(3)), + '0' => (Some(Operator::Comment), Some(1)), + '&' => (Some(Operator::TypeCheck), Some(2)), + '$' => (Some(Operator::VariableDrop), Some(1)), + '%' => (Some(Operator::VariableClone), Some(2)), + '#' => (Some(Operator::StackPush), Some(0)), + '|' => (Some(Operator::Return), Some(0)), + _ => (None, None), } }