Add support for real comparison operators

This commit is contained in:
Jonathan Turner
2019-05-17 18:27:31 -07:00
parent 52716d0c24
commit 76c295995d
3 changed files with 106 additions and 41 deletions

View File

@ -14,6 +14,45 @@ pub enum Item {
Bare(String),
Int(i64),
Boolean(bool),
Operator(Operator),
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Operator {
Equal,
NotEqual,
LessThan,
GreaterThan,
LessThanOrEqual,
GreaterThanOrEqual,
}
impl Operator {
pub fn print(&self) -> String {
match *self {
Operator::Equal => "==".to_string(),
Operator::NotEqual => "!=".to_string(),
Operator::LessThan => "<".to_string(),
Operator::GreaterThan => ">".to_string(),
Operator::LessThanOrEqual => "<=".to_string(),
Operator::GreaterThanOrEqual => ">=".to_string(),
}
}
}
impl FromStr for Operator {
type Err = ();
fn from_str(input: &str) -> Result<Self, <Self as std::str::FromStr>::Err> {
match input {
"==" => Ok(Operator::Equal),
"!=" => Ok(Operator::NotEqual),
"<" => Ok(Operator::LessThan),
">" => Ok(Operator::GreaterThan),
"<=" => Ok(Operator::LessThanOrEqual),
">=" => Ok(Operator::GreaterThanOrEqual),
_ => Err(()),
}
}
}
impl Item {
@ -23,6 +62,7 @@ impl Item {
Item::Bare(s) => Value::Primitive(Primitive::String(s.clone())),
Item::Int(i) => Value::Primitive(Primitive::Int(*i)),
Item::Boolean(b) => Value::Primitive(Primitive::Boolean(*b)),
Item::Operator(o) => Value::Primitive(Primitive::Operator(o.clone())),
}
}
}
@ -33,6 +73,7 @@ crate fn print_items(items: &[Item]) -> String {
Item::Quoted(s) => format!("{:?}", s),
Item::Int(i) => format!("{:?}", i),
Item::Boolean(b) => format!("{:?}", b),
Item::Operator(o) => o.print(),
});
itertools::join(formatted, " ")
@ -45,6 +86,10 @@ impl Item {
Item::Bare(s) => Ok(s),
Item::Boolean(i) => Err(ShellError::string(format!("{} is not a valid command", i))),
Item::Int(i) => Err(ShellError::string(format!("{} is not a valid command", i))),
Item::Operator(x) => Err(ShellError::string(format!(
"{:?} is not a valid command",
x
))),
}
}
}
@ -62,6 +107,18 @@ fn unquoted(s: &str) -> IResult<&str, Item> {
is_not(" |")(s).map(|(a, b)| (a, Item::Bare(b.to_string())))
}
fn operator(s: &str) -> IResult<&str, Item> {
alt((
tag("=="),
tag("!="),
tag("<"),
tag(">"),
tag("<="),
tag(">="),
))(s)
.map(|(a, b)| (a, Item::Operator(FromStr::from_str(b).unwrap())))
}
fn int(s: &str) -> IResult<&str, Item> {
is_a("1234567890")(s).map(|(a, b)| (a, Item::Int(FromStr::from_str(b).unwrap())))
}
@ -72,7 +129,7 @@ fn boolean(s: &str) -> IResult<&str, Item> {
}
fn command_token(s: &str) -> IResult<&str, Item> {
alt((boolean, int, quoted, unquoted))(s)
alt((boolean, int, operator, quoted, unquoted))(s)
}
fn command_args(s: &str) -> IResult<&str, Vec<Item>> {