Permalink
Browse files

Add support for braced array variables (#310)

* Added support for braced arrays

* VBRACE flag now set when parsing braced array

* Extend parser::statements::braced_variables test
  • Loading branch information...
huntergoldstein authored and mmstick committed Jun 19, 2017
1 parent 2f12c1b commit b002e7d6727b6fcf7a612d3fab935cb835745f24
Showing with 46 additions and 7 deletions.
  1. +44 −5 src/parser/shell_expand/words.rs
  2. +2 −2 src/parser/statements.rs
@@ -579,6 +579,43 @@ impl<'a> WordIterator<'a> {
WordToken::ArrayVariable(&self.data[start..], self.flags & DQUOTE != 0, Select::All)
}
fn braced_array_variable<I>(&mut self, iterator : &mut I) -> WordToken<'a>
where I : Iterator<Item=u8>
{
let start = self.read;
//self.read += 1;
while let Some(character) = iterator.next() {
match character {
b'[' => {
let result = WordToken::ArrayVariable (
&self.data[start..self.read],
self.flags & DQUOTE != 0,
self.read_selection(iterator)
);
self.read += 1;
if let Some(b'}') = iterator.next() {
return result;
}
panic!("ion: fatal with syntax validation error: unterminated braced array expression");
},
b'}' => {
let output = &self.data[start..self.read];
self.read += 1;
return WordToken::ArrayVariable(output, self.flags & DQUOTE != 0, Select::All);
}
// Only alphanumerical and underscores are allowed in variable names
0...47 | 58...64 | 91...94 | 96 | 123...127 => {
return WordToken::ArrayVariable(&self.data[start..self.read],
self.flags & DQUOTE != 0,
Select::All);
},
_ => (),
}
self.read += 1;
}
WordToken::ArrayVariable(&self.data[start..], self.flags & DQUOTE != 0, Select::All)
}
/// Contains the logic for parsing subshell syntax.
fn process<I>(&mut self, iterator: &mut I) -> WordToken<'a>
where I: Iterator<Item = u8>
@@ -876,10 +913,10 @@ impl<'a> Iterator for WordIterator<'a> {
Some(WordToken::Normal(&self.data[start..self.read],glob))
}
},
// Some(b'{') => {
// self.read += 2;
// return Some(self.braced_variable(&mut iterator));
// }
Some(b'{') => {
self.read += 2;
return Some(self.braced_array_variable(&mut iterator));
},
_ => {
self.read += 1;
return Some(self.array_variable(&mut iterator));
@@ -1053,11 +1090,13 @@ mod tests {
#[test]
fn array_variables() {
let input = "@array @array[0]";
let input = "@array @array[0] @{array[1..]}";
let expected = vec![
WordToken::ArrayVariable("array", false, Select::All),
WordToken::Whitespace(" "),
WordToken::ArrayVariable("array", false, Select::Index(Index::new(0))),
WordToken::Whitespace(" "),
WordToken::ArrayVariable("array", false, Select::Range(Range::from(Index::new(1))))
];
compare(input, expected);
}
View
@@ -119,7 +119,7 @@ impl<'a> Iterator for StatementSplitter<'a> {
self.flags |= COMM_1 + VARIAB;
continue
},
b'{' if self.flags & COMM_1 != 0 => self.flags |= VBRACE,
b'{' if self.flags & (COMM_1 + COMM_2) != 0 => self.flags |= VBRACE,
b'{' if self.flags & (SQUOTE + DQUOTE) == 0 => self.brace_level += 1,
b'}' if self.flags & VBRACE != 0 => self.flags ^= VBRACE,
b'}' if self.flags & (SQUOTE + DQUOTE) == 0 => {
@@ -329,7 +329,7 @@ fn nested_array_process() {
#[test]
fn braced_variables() {
let command = "echo ${foo}bar ${bar}baz ${baz}quux";
let command = "echo ${foo}bar ${bar}baz ${baz}quux @{zardoz}wibble";
let results = StatementSplitter::new(command).collect::<Vec<Result<&str, StatementError>>>();
assert_eq!(results.len(), 1);
assert_eq!(results, vec![Ok(command)]);

0 comments on commit b002e7d

Please sign in to comment.