summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-01-08 19:02:28 -0500
committerJesse Luehrs <doy@tozt.net>2022-01-08 19:02:28 -0500
commit96b45b2d3dd1ff0ee9312150f2a642058df7668b (patch)
treeea7689b74153853cad7ed169fceabef07a979274
parent21f67c732a4af18b3a42b9fd34f4b1f4ec7a258d (diff)
downloadnbsh-96b45b2d3dd1ff0ee9312150f2a642058df7668b.tar.gz
nbsh-96b45b2d3dd1ff0ee9312150f2a642058df7668b.zip
fix for loop parsing
-rw-r--r--src/parse/ast.rs22
-rw-r--r--src/shell.pest3
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 }