summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-01-17 01:19:08 -0500
committerJesse Luehrs <doy@tozt.net>2022-01-17 01:23:08 -0500
commit9b1595b795121d233cd0cf32537661839e318914 (patch)
tree26edb4376ed189373e8a4f3b3d41da6c27d23bf4
parent1327c2a7ba3b81fe69e4126270b2cfe24c8aa4ee (diff)
downloadnbsh-9b1595b795121d233cd0cf32537661839e318914.tar.gz
nbsh-9b1595b795121d233cd0cf32537661839e318914.zip
basic subshell implementation
-rw-r--r--src/parse/ast.rs31
-rw-r--r--src/runner/mod.rs4
-rw-r--r--src/shell.pest6
3 files changed, 38 insertions, 3 deletions
diff --git a/src/parse/ast.rs b/src/parse/ast.rs
index bac40c8..9d74331 100644
--- a/src/parse/ast.rs
+++ b/src/parse/ast.rs
@@ -141,7 +141,36 @@ impl Exe {
}
fn build_ast(pair: pest::iterators::Pair<Rule>) -> Self {
- assert!(matches!(pair.as_rule(), Rule::exe));
+ assert!(matches!(pair.as_rule(), Rule::subshell | Rule::exe));
+ if matches!(pair.as_rule(), Rule::subshell) {
+ return Self {
+ exe: Word {
+ parts: vec![WordPart::SingleQuoted(
+ std::env::current_exe()
+ .unwrap()
+ .to_str()
+ .unwrap()
+ .to_string(),
+ )],
+ },
+ args: vec![
+ Word {
+ parts: vec![WordPart::SingleQuoted("-c".to_string())],
+ },
+ Word {
+ parts: vec![WordPart::SingleQuoted(
+ pair.as_str()
+ .strip_prefix('(')
+ .unwrap()
+ .strip_suffix(')')
+ .unwrap()
+ .to_string(),
+ )],
+ },
+ ],
+ redirects: vec![],
+ };
+ }
let mut iter = pair.into_inner();
let exe = match WordOrRedirect::build_ast(iter.next().unwrap()) {
WordOrRedirect::Word(word) => word,
diff --git a/src/runner/mod.rs b/src/runner/mod.rs
index 98894b3..63af51b 100644
--- a/src/runner/mod.rs
+++ b/src/runner/mod.rs
@@ -158,7 +158,11 @@ async fn run_commands(
*should = !list.is_empty();
if *should {
let val = list.remove(0);
+ // XXX i really need to just pick one location and
+ // stick with it instead of trying to keep these
+ // in sync
env.set_var(var, &val);
+ std::env::set_var(var, &val);
}
} else {
unreachable!();
diff --git a/src/shell.pest b/src/shell.pest
index 8a51070..fdfb1b1 100644
--- a/src/shell.pest
+++ b/src/shell.pest
@@ -3,7 +3,8 @@ escape_char = @{ "\\" ~ ANY }
bareword_char = @{
escape_char |
- !("|" | ";" | "\"" | "'" | "$" | "{" | WHITESPACE | COMMENT) ~ ANY
+ !("|" | ";" | "\"" | "'" | "$" | "{" | "(" | ")" | WHITESPACE | COMMENT)
+ ~ ANY
}
single_string_char = @{ basic_escape_char | (!"'" ~ ANY) }
double_string_char = @{ escape_char | (!("\"" | "$") ~ ANY) }
@@ -44,8 +45,9 @@ word = ${ word_part+ }
word_or_redirect = ${ redir_prefix? ~ word }
exe = ${ word_or_redirect ~ (w ~ word_or_redirect)* }
+subshell = ${ "(" ~ w? ~ commands ~ w? ~ ")" }
list = ${ word ~ (w ~ word)* }
-pipeline = ${ exe ~ (w? ~ "|" ~ w? ~ exe)* }
+pipeline = ${ (subshell | exe) ~ (w? ~ "|" ~ w? ~ (subshell | exe))* }
control_if = ${ "if" ~ w ~ pipeline }
control_while = ${ "while" ~ w ~ pipeline }