summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-01-08 00:28:37 -0500
committerJesse Luehrs <doy@tozt.net>2022-01-08 00:28:37 -0500
commit489fd0db1bf7f1de31a043e315179e83b77921aa (patch)
treea4862b8f8572234305eae3a1128860a7a1d5117c
parent9dd1d992bd2344d8824e69d8f47c9009a6caf021 (diff)
downloadnbsh-489fd0db1bf7f1de31a043e315179e83b77921aa.tar.gz
nbsh-489fd0db1bf7f1de31a043e315179e83b77921aa.zip
add basic variable parsing
-rw-r--r--src/parse/ast.rs34
-rw-r--r--src/shell.pest18
2 files changed, 38 insertions, 14 deletions
diff --git a/src/parse/ast.rs b/src/parse/ast.rs
index 28593bb..71cb9af 100644
--- a/src/parse/ast.rs
+++ b/src/parse/ast.rs
@@ -142,6 +142,7 @@ struct Word {
word: String,
interpolate: bool,
quoted: bool,
+ var: bool,
}
impl Word {
@@ -150,22 +151,33 @@ impl Word {
matches!(rule, Rule::bareword | Rule::double_string);
let quoted =
matches!(rule, Rule::single_string | Rule::double_string);
- let mut word_str = s.to_string();
- if interpolate {
- word_str = strip_escape(&word_str);
+ let var = matches!(rule, Rule::var);
+ let word_str = if var {
+ let inner = s.strip_prefix('$').unwrap();
+ inner
+ .strip_prefix('{')
+ .map_or(inner, |inner| inner.strip_suffix('}').unwrap())
+ .to_string()
+ } else if interpolate {
+ strip_escape(s)
} else {
- word_str = strip_basic_escape(&word_str);
- }
+ strip_basic_escape(s)
+ };
Self {
word: word_str,
interpolate,
quoted,
+ var,
}
}
fn eval(self, _env: &Env) -> String {
- // TODO
- self.word
+ if self.var {
+ // TODO
+ format!("'value-of-${{{}}}'", self.word)
+ } else {
+ self.word
+ }
}
}
@@ -247,7 +259,10 @@ impl WordOrRedirect {
}
assert!(matches!(
word.as_rule(),
- Rule::bareword | Rule::single_string | Rule::double_string
+ Rule::var
+ | Rule::bareword
+ | Rule::single_string
+ | Rule::double_string
));
let word = Word::parse(word.as_str(), word.as_rule());
if let Some(prefix) = prefix {
@@ -381,6 +396,7 @@ macro_rules! w {
word: $word.to_string(),
interpolate: true,
quoted: false,
+ var: false,
}
};
($word:expr, $interpolate:expr) => {
@@ -388,6 +404,7 @@ macro_rules! w {
word: $word.to_string(),
interpolate: $interpolate,
quoted: false,
+ var: false,
}
};
($word:expr, $interpolate:expr, $quoted:expr) => {
@@ -395,6 +412,7 @@ macro_rules! w {
word: $word.to_string(),
interpolate: $interpolate,
quoted: $quoted,
+ var: false,
}
};
}
diff --git a/src/shell.pest b/src/shell.pest
index ffb0f42..b1bcae5 100644
--- a/src/shell.pest
+++ b/src/shell.pest
@@ -3,11 +3,17 @@ 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) }
+var = @{
+ ("$" ~ XID_START ~ XID_CONTINUE*) |
+ ("$" ~ ("?" | "$" | "*" | ASCII_DIGIT)) |
+ ("${" ~ (!"}" ~ ANY)+ ~ "}")
+}
+
redir_prefix = @{ ASCII_DIGIT* ~ (">>" | ">" | "<") ~ WHITESPACE* }
bareword = @{ bareword_char+ }
single_string = @{ single_string_char+ }
@@ -15,17 +21,17 @@ double_string = @{ double_string_char+ }
word = ${
redir_prefix? ~
- (bareword |
+ (var | bareword |
"'" ~ single_string ~ "'" |
"\"" ~ double_string ~ "\"")
}
exe = ${ word ~ (w ~ word)* }
-pipeline = ${ exe ~ (w ~ "|" ~ w ~ exe)* }
-commands = ${ pipeline ~ (w ~ ";" ~ w ~ pipeline)* }
+pipeline = ${ exe ~ (w? ~ "|" ~ w? ~ exe)* }
+commands = ${ pipeline ~ (w? ~ ";" ~ w? ~ pipeline)* }
-line = ${ SOI ~ w ~ commands ~ w ~ EOI }
+line = ${ SOI ~ w? ~ commands ~ w? ~ EOI }
-w = _{ (WHITESPACE | COMMENT)* }
+w = _{ (WHITESPACE | COMMENT)+ }
WHITESPACE = _{ (" " | "\t" | "\n") }
COMMENT = _{ "#" ~ ANY* }