Construct operators as an enum
This commit is contained in:
parent
5eaca1898f
commit
95eeeb6ec7
1 changed files with 56 additions and 31 deletions
87
src/lib.rs
87
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<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),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue