Skip to content

Commit

Permalink
Implement Case Bindings Support
Browse files Browse the repository at this point in the history
  • Loading branch information
mmstick committed Aug 28, 2017
1 parent d98caf3 commit 2000f24
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 6 deletions.
18 changes: 18 additions & 0 deletions src/parser/statement/case.rs
@@ -0,0 +1,18 @@
use super::split_pattern;

pub fn parse_case<'a>(data: &'a str) -> (&'a str, Option<&'a str>, Option<&'a str>) {
let (key, conditional) = split_pattern(data, " if ");
let (key, binding) = split_pattern(key, " @ ");
(key.trim(), binding.map(|x| x.trim()), conditional.map(|x| x.trim()))
}

#[cfg(test)]
mod tests {
use super::parse_case;
#[test]
fn case_parsing() {
assert_eq!(("test", Some("test"), Some("exists")), parse_case("test @ test if exists"));
assert_eq!(("test", Some("test"), None), parse_case("test @ test"));
assert_eq!(("test", None, None), parse_case("test"));
}
}
1 change: 1 addition & 0 deletions src/parser/statement/mod.rs
@@ -1,3 +1,4 @@
mod case;
mod functions;
mod parse;
mod splitter;
Expand Down
21 changes: 17 additions & 4 deletions src/parser/statement/parse.rs
@@ -1,3 +1,4 @@
use super::case;
use super::functions::{collect_arguments, parse_function};
use super::super::{ArgumentSplitter, pipelines};
use super::super::pipelines::Pipeline;
Expand Down Expand Up @@ -89,12 +90,24 @@ pub fn parse(code: &str) -> Statement {
};
}
_ if cmd.starts_with("case ") => {
let value = match cmd[5..].trim_left() {
"_" => None,
value @ _ => Some(value.into()),
let (value, binding, conditional) = match cmd[5..].trim_left() {
"_" => (None, None, None),
value @ _ => {
let (value, binding, conditional) = case::parse_case(value);
let binding = binding.map(Into::into);
let conditional = conditional.map(Into::into);
if value == "_" {
(None, binding, conditional)
} else {
(Some(value.into()), binding, conditional)
}
}
};

return Statement::Case(Case {
value: value,
value,
binding,
conditional,
statements: Vec::new(),
});
}
Expand Down
51 changes: 50 additions & 1 deletion src/shell/flow.rs
Expand Up @@ -5,6 +5,7 @@ use super::job_control::JobControl;
use super::status::*;
use parser::{ForExpression, StatementSplitter, expand_string, parse_and_validate};
use parser::pipelines::Pipeline;
use parser::types::checker::{ReturnValue, is_array};
use shell::assignments::VariableStore;
use std::io::{self, Write};
use std::mem;
Expand Down Expand Up @@ -209,19 +210,67 @@ impl<'a> FlowLogic for Shell<'a> {
return true;
}
}
return false;
false
}

let is_array = is_array(&expression);
let value = expand_string(&expression, self, false);
let mut condition = Condition::NoOp;
for case in cases {
let pattern = case.value.map(|v| expand_string(&v, self, false));
match pattern {
None => {
let mut previous_bind = None;
if let Some(ref bind) = case.binding {
if is_array {
previous_bind = self.variables.get_array(bind).map(|x| {
ReturnValue::Vector(x.clone())
});
self.variables.set_array(&bind, value);
} else {
previous_bind = self.variables.get_var(bind).map(|x| ReturnValue::Str(x));
self.variables.set_var(&bind, &value.join(" "));
}
}

condition = self.execute_statements(case.statements);

if let Some(ref bind) = case.binding {
if let Some(value) = previous_bind {
match value {
ReturnValue::Str(value) => self.variables.set_var(bind, &value),
ReturnValue::Vector(values) => self.variables.set_array(bind, values),
}
}
}

break;
}
Some(ref v) if matches(v, &value) => {
let mut previous_bind = None;
if let Some(ref bind) = case.binding {
if is_array {
previous_bind = self.variables.get_array(bind).map(|x| {
ReturnValue::Vector(x.clone())
});
self.variables.set_array(&bind, value);
} else {
previous_bind = self.variables.get_var(bind).map(|x| ReturnValue::Str(x));
self.variables.set_var(&bind, &value.join(" "));
}
}

condition = self.execute_statements(case.statements);

if let Some(ref bind) = case.binding {
if let Some(value) = previous_bind {
match value {
ReturnValue::Str(value) => self.variables.set_var(bind, &value),
ReturnValue::Vector(values) => self.variables.set_array(bind, values),
}
}
}

break;
}
Some(_) => (),
Expand Down
4 changes: 3 additions & 1 deletion src/shell/flow_control.rs
Expand Up @@ -3,7 +3,7 @@ use super::flow::FlowLogic;
use fnv::*;
use parser::pipelines::Pipeline;
use parser::types::checker::{ReturnValue, value_check};
use parser::types::parse::{Primitive, KeyBuf};
use parser::types::parse::{KeyBuf, Primitive};
use types::*;
use types::Identifier;

Expand Down Expand Up @@ -36,6 +36,8 @@ pub struct ElseIf {
#[derive(Debug, PartialEq, Clone)]
pub struct Case {
pub value: Option<String>,
pub binding: Option<String>,
pub conditional: Option<String>,
pub statements: Vec<Statement>,
}

Expand Down

0 comments on commit 2000f24

Please sign in to comment.