Construct operators as an enum

This commit is contained in:
abbie 2024-08-21 21:49:11 +01:00
parent 5eaca1898f
commit 95eeeb6ec7
Signed by: threeoh6000
GPG key ID: 801FE4AD456E922C

View file

@ -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<String>,
}
@ -14,7 +40,7 @@ pub struct Program {
pub fn parse(data: &str) -> Result<Program, String> {
let mut program_begun = false;
let mut operator: Option<String> = None;
let mut operator: Option<Operator> = None;
let mut arguments: Vec<String> = 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, String> {
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<Program, String> {
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<Program, String> {
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<Program, 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()));
}
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<Program, String> {
Ok(program)
}
fn operator_to_arglength(operator: char) -> Option<i32> {
fn operator_to_arglength(operator: char) -> (Option<Operator>, Option<i32>) {
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),
}
}