diff --git a/examples/fibonacci.ion b/examples/fibonacci.ion index 94cee368a22e6a32b448aa2d14ae94a472ca3c93..4274a7019eb74ccf669b00b96c0427ffaeaf8201 100644 --- a/examples/fibonacci.ion +++ b/examples/fibonacci.ion @@ -7,6 +7,8 @@ fn fib n let temp = $output let output += $previous let previous = $temp + # This also works, but has a higher performance penalty: + # let output previous = $((output + previous)) $output end echo $output end diff --git a/src/parser/pipelines.rs b/src/parser/pipelines.rs index bc59a02372b2e6a5e5a8721618c3eeccc721c3c5..d2107f8598f108ecb096a28fad70d29146549484 100644 --- a/src/parser/pipelines.rs +++ b/src/parser/pipelines.rs @@ -73,10 +73,11 @@ impl<'a> Collector<'a> { // not sure of a better solution let mut array_level = 0; let mut proc_level = 0; + let mut brace_level = 0; let mut start = None; let mut end = None; - macro_rules! is_toplevel { () => (array_level == 0 && proc_level == 0) } + macro_rules! is_toplevel { () => (array_level + proc_level + brace_level == 0) } // Skip over any leading whitespace while let Some(&(_, b)) = bytes.peek() { @@ -93,6 +94,8 @@ impl<'a> Collector<'a> { b')' => { proc_level -= 1; bytes.next(); } b'[' => { array_level += 1; bytes.next(); } b']' => { array_level -= 1; bytes.next(); } + b'{' => { brace_level += 1; bytes.next(); } + b'}' => { brace_level -= 1; bytes.next();} // This is a tricky one: we only end the argment if `^` is followed by a // redirection character b'^' => if is_toplevel!() { @@ -142,6 +145,9 @@ impl<'a> Collector<'a> { if array_level > 0 { return Err("ion: syntax error: unmatched left bracket"); } + if brace_level > 0 { + return Err("ion: syntax error: unmatched left brace"); + } if proc_level < 0 { return Err("ion: syntax error: extra right paren(s)"); } @@ -344,6 +350,17 @@ mod tests { } } + #[test] + fn braces() { + if let Statement::Pipeline(pipeline) = parse("echo {a b} {a {b c}}") { + let jobs = pipeline.jobs; + assert_eq!("{a b}", jobs[0].args[1]); + assert_eq!("{a {b c}}", jobs[0].args[2]); + } else { + assert!(false); + } + } + #[test] fn methods() { if let Statement::Pipeline(pipeline) = parse("echo @split(var, ', ') $join(array, ',')") {