summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-12-22 21:42:39 -0500
committerJesse Luehrs <doy@tozt.net>2021-12-22 21:42:39 -0500
commita9c21f23f004cc41fdba52da365bedf5cab8adfc (patch)
tree5993f7cc4991e8d067aad2319ce358965dfbdad9
parent612b5a82ccffe18510eb6608e53b98c0da7c4212 (diff)
downloadnbsh-a9c21f23f004cc41fdba52da365bedf5cab8adfc.tar.gz
nbsh-a9c21f23f004cc41fdba52da365bedf5cab8adfc.zip
parse quoted strings
-rw-r--r--src/parse.rs26
-rw-r--r--src/shell.pest15
2 files changed, 27 insertions, 14 deletions
diff --git a/src/parse.rs b/src/parse.rs
index 4ddffba..03b865c 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -11,17 +11,19 @@ pub struct Word {
}
impl Word {
- fn new(word: &str) -> Self {
- Self {
- word: word.to_string(),
- interpolate: true,
- }
- }
-
- fn literal(word: &str) -> Self {
+ fn build_ast(pair: pest::iterators::Pair<Rule>) -> Self {
+ assert!(matches!(pair.as_rule(), Rule::word));
+ let word = pair.into_inner().next().unwrap();
+ assert!(matches!(
+ word.as_rule(),
+ Rule::bareword | Rule::single_string | Rule::double_string
+ ));
Self {
- word: word.to_string(),
- interpolate: false,
+ word: word.as_str().to_string(),
+ interpolate: matches!(
+ word.as_rule(),
+ Rule::bareword | Rule::double_string
+ ),
}
}
}
@@ -36,8 +38,8 @@ impl Exe {
fn build_ast(pair: pest::iterators::Pair<Rule>) -> Self {
assert!(matches!(pair.as_rule(), Rule::exe));
let mut iter = pair.into_inner();
- let exe = Word::new(iter.next().unwrap().as_str());
- let args = iter.map(|word| Word::new(word.as_str())).collect();
+ let exe = Word::build_ast(iter.next().unwrap());
+ let args = iter.map(Word::build_ast).collect();
Self { exe, args }
}
diff --git a/src/shell.pest b/src/shell.pest
index 49a84b4..7744873 100644
--- a/src/shell.pest
+++ b/src/shell.pest
@@ -1,5 +1,16 @@
-char = @{ !("|" | ";" | WHITESPACE) ~ ANY }
-word = @{ char+ }
+bareword_char = @{ !("|" | ";" | "\"" | "'" | WHITESPACE | COMMENT) ~ ANY }
+single_string_char = @{ "\\'" | (!"'" ~ ANY) }
+double_string_char = @{ "\\\"" | (!"\"" ~ ANY) }
+
+bareword = @{ bareword_char+ }
+single_string = @{ single_string_char+ }
+double_string = @{ double_string_char+ }
+
+word = {
+ bareword |
+ "'" ~ single_string ~ "'" |
+ "\"" ~ double_string ~ "\""
+}
exe = { word+ }
pipeline = { exe ~ ("|" ~ exe)* }