use shell::variables::Variables;
use types::{Identifier, Value as VString, Array};
#[derive(Debug, PartialEq, Clone)]
pub enum Value {
String(VString),
Array(Array)
}
#[derive(Debug, PartialEq, Clone)]
pub enum Binding {
InvalidKey(Identifier),
ListEntries,
KeyOnly(Identifier),
KeyValue(Identifier, VString),
Math(Identifier, Operator, VString),
}
#[derive(Debug, PartialEq, Clone)]
pub enum Operator {
Add,
Subtract,
Divide,
Multiply,
Exponent,
}
#[allow(dead_code)]
enum Expression {
Arithmetic,
Regular
}
pub fn parse_assignment(arguments: &str) -> Binding {
let mut char_iter = arguments.chars();
let mut key = "".to_owned();
let mut found_key = false;
let mut operator = None;
macro_rules! match_operator {
($op:expr) => {
if char_iter.next() == Some('=') {
operator = Some($op);
found_key = true;
}
}
}
while let Some(character) = char_iter.next() {
match character {
' ' if key.is_empty() => (),
' ' => found_key = true,
'+' => {
match_operator!(Operator::Add);
break
},
'-' => {
match_operator!(Operator::Subtract);
break
},
'*' => {
match_operator!(Operator::Multiply);
break
},
'/' => {
match_operator!(Operator::Divide);
break
},
'^' => {
match_operator!(Operator::Exponent);
break
},
'=' => {
found_key = true;
break
},
_ if !found_key => key.push(character),
_ => ()
}
}
if !found_key && key.is_empty() {
Binding::ListEntries
} else {
let value = char_iter.skip_while(|&x| x == ' ').collect::<VString>();
if value.is_empty() {
Binding::KeyOnly(key.into())
} else if !Variables::is_valid_variable_name(&key) {
Binding::InvalidKey(key.into())
} else {
match operator {
Some(operator) => Binding::Math(key.into(), operator, value),
None => Binding::KeyValue(key.into(), value)
}
}
}
}