summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-01-18 00:41:09 -0500
committerJesse Luehrs <doy@tozt.net>2022-01-18 00:41:09 -0500
commitd97f262a67f39ccdb0e29aabe10646068bc2d749 (patch)
treeb22a0b1f3f6052f7617c01e59f6348bfc5c460f3 /src
parent5105fb8752b00da8da7d4f27b41e0f3deae9858a (diff)
downloadnbsh-d97f262a67f39ccdb0e29aabe10646068bc2d749.tar.gz
nbsh-d97f262a67f39ccdb0e29aabe10646068bc2d749.zip
simplify
Diffstat (limited to 'src')
-rw-r--r--src/parse/ast.rs70
-rw-r--r--src/shell.pest11
2 files changed, 28 insertions, 53 deletions
diff --git a/src/parse/ast.rs b/src/parse/ast.rs
index 294afe5..dd5065a 100644
--- a/src/parse/ast.rs
+++ b/src/parse/ast.rs
@@ -181,27 +181,21 @@ impl Exe {
};
}
let mut iter = pair.into_inner();
- let exe = match WordOrRedirect::build_ast(iter.next().unwrap()) {
- WordOrRedirect::Word(word) => word,
- WordOrRedirect::Redirect(_) => todo!(),
+ let exe = iter.next().unwrap();
+ let exe = match exe.as_rule() {
+ Rule::word => Word::build_ast(exe),
+ Rule::redirect => todo!(),
+ _ => unreachable!(),
};
- let (args, redirects): (_, Vec<_>) = iter
- .map(WordOrRedirect::build_ast)
- .partition(|word| matches!(word, WordOrRedirect::Word(_)));
- let args = args
- .into_iter()
- .map(|word| match word {
- WordOrRedirect::Word(word) => word,
- WordOrRedirect::Redirect(_) => unreachable!(),
- })
- .collect();
- let redirects = redirects
- .into_iter()
- .map(|word| match word {
- WordOrRedirect::Word(_) => unreachable!(),
- WordOrRedirect::Redirect(redirect) => redirect,
- })
- .collect();
+ let mut args = vec![];
+ let mut redirects = vec![];
+ for arg in iter {
+ match arg.as_rule() {
+ Rule::word => args.push(Word::build_ast(arg)),
+ Rule::redirect => redirects.push(Redirect::build_ast(arg)),
+ _ => unreachable!(),
+ }
+ }
Self {
exe,
args,
@@ -408,7 +402,12 @@ struct Redirect {
}
impl Redirect {
- fn parse(prefix: &str, to: Word) -> Self {
+ #[allow(clippy::needless_pass_by_value)]
+ fn build_ast(pair: pest::iterators::Pair<Rule>) -> Self {
+ assert!(matches!(pair.as_rule(), Rule::redirect));
+ let mut iter = pair.into_inner();
+
+ let prefix = iter.next().unwrap().as_str();
let (from, dir) = if let Some(from) = prefix.strip_suffix(">>") {
(from, super::Direction::Append)
} else if let Some(from) = prefix.strip_suffix('>') {
@@ -426,6 +425,9 @@ impl Redirect {
} else {
parse_fd(from)
};
+
+ let to = Word::build_ast(iter.next().unwrap());
+
Self { from, to, dir }
}
@@ -460,32 +462,6 @@ impl Redirect {
}
}
-enum WordOrRedirect {
- Word(Word),
- Redirect(Redirect),
-}
-
-impl WordOrRedirect {
- fn build_ast(pair: pest::iterators::Pair<Rule>) -> Self {
- assert!(matches!(pair.as_rule(), Rule::word_or_redirect));
- let mut inner = pair.into_inner().peekable();
- let prefix = if matches!(
- inner.peek().map(pest::iterators::Pair::as_rule),
- Some(Rule::redir_prefix)
- ) {
- Some(inner.next().unwrap().as_str().trim().to_string())
- } else {
- None
- };
- let word = Word::build_ast(inner.next().unwrap());
- if let Some(prefix) = prefix {
- Self::Redirect(Redirect::parse(&prefix, word))
- } else {
- Self::Word(word)
- }
- }
-}
-
fn strip_escape(s: &str) -> String {
let mut new = String::new();
let mut escape = false;
diff --git a/src/shell.pest b/src/shell.pest
index 94f78d2..d2c96b8 100644
--- a/src/shell.pest
+++ b/src/shell.pest
@@ -9,10 +9,6 @@ bareword_char = @{
single_string_char = @{ basic_escape_char | (!"'" ~ ANY) }
double_string_char = @{ escape_char | (!("\"" | "$") ~ ANY) }
-redir_prefix = @{
- ("in" | "out" | "err" | ASCII_DIGIT*) ~ (">>" | ">" | "<") ~ WHITESPACE*
-}
-
var = @{
("$" ~ XID_START ~ XID_CONTINUE*) |
("$" ~ ("?" | "$" | "*" | ASCII_DIGIT)) |
@@ -45,9 +41,12 @@ word_part = ${
}
word = ${ word_part+ }
-word_or_redirect = ${ redir_prefix? ~ word }
+redir_prefix = @{
+ ("in" | "out" | "err" | ASCII_DIGIT*) ~ (">>" | ">" | "<")
+}
+redirect = ${ redir_prefix ~ w? ~ word }
-exe = ${ word_or_redirect ~ (w ~ word_or_redirect)* }
+exe = ${ (redirect | word) ~ (w ~ (redirect | word))* }
subshell = ${ "(" ~ w? ~ commands ~ w? ~ ")" }
list = ${ word ~ (w ~ word)* }
pipeline = ${ (subshell | exe) ~ (w? ~ "|" ~ w? ~ (subshell | exe))* }