diff options
author | Jesse Luehrs <doy@tozt.net> | 2022-01-08 19:02:28 -0500 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2022-01-08 19:02:28 -0500 |
commit | 96b45b2d3dd1ff0ee9312150f2a642058df7668b (patch) | |
tree | ea7689b74153853cad7ed169fceabef07a979274 | |
parent | 21f67c732a4af18b3a42b9fd34f4b1f4ec7a258d (diff) | |
download | nbsh-96b45b2d3dd1ff0ee9312150f2a642058df7668b.tar.gz nbsh-96b45b2d3dd1ff0ee9312150f2a642058df7668b.zip |
fix for loop parsing
-rw-r--r-- | src/parse/ast.rs | 22 | ||||
-rw-r--r-- | src/shell.pest | 3 |
2 files changed, 17 insertions, 8 deletions
diff --git a/src/parse/ast.rs b/src/parse/ast.rs index f33734b..d71f6a3 100644 --- a/src/parse/ast.rs +++ b/src/parse/ast.rs @@ -48,7 +48,7 @@ pub enum Command { Pipeline(Pipeline), If(Pipeline), While(Pipeline), - For(String, Pipeline), + For(String, Vec<Word>), End, } @@ -71,10 +71,11 @@ impl Command { let mut inner = ty.into_inner(); let var = inner.next().unwrap(); assert!(matches!(var.as_rule(), Rule::bareword)); - Self::For( - var.as_str().to_string(), - Pipeline::build_ast(inner.next().unwrap()), - ) + let list = inner.next().unwrap(); + assert!(matches!(list.as_rule(), Rule::list)); + let vals = + list.into_inner().map(Word::build_ast).collect(); + Self::For(var.as_str().to_string(), vals) } Rule::control_end => Self::End, _ => unreachable!(), @@ -174,12 +175,19 @@ impl Exe { } #[derive(Debug, Clone, PartialEq, Eq)] -struct Word { +pub struct Word { parts: Vec<WordPart>, } impl Word { - fn eval(self, env: &Env) -> String { + fn build_ast(pair: pest::iterators::Pair<Rule>) -> Self { + assert!(matches!(pair.as_rule(), Rule::word)); + Self { + parts: pair.into_inner().map(WordPart::build_ast).collect(), + } + } + + pub fn eval(self, env: &Env) -> String { self.parts .into_iter() .map(|part| part.eval(env)) diff --git a/src/shell.pest b/src/shell.pest index 8c0e79c..4c5f728 100644 --- a/src/shell.pest +++ b/src/shell.pest @@ -27,11 +27,12 @@ word = ${ } exe = ${ word ~ (w ~ word)* } +list = ${ word ~ (w ~ word)* } pipeline = ${ exe ~ (w? ~ "|" ~ w? ~ exe)* } control_if = ${ "if" ~ w ~ pipeline } control_while = ${ "while" ~ w ~ pipeline } -control_for = ${ "for" ~ w ~ bareword ~ w ~ "in" ~ w ~ pipeline } +control_for = ${ "for" ~ w ~ bareword ~ w ~ "in" ~ w ~ list } control_end = ${ "end" } control = ${ control_if | control_while | control_for | control_end } |