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