aboutsummaryrefslogtreecommitdiffstats
path: root/src/parse
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/mod.rs158
-rw-r--r--src/parse/test.rs8
2 files changed, 86 insertions, 80 deletions
diff --git a/src/parse/mod.rs b/src/parse/mod.rs
index 1e88337..f418600 100644
--- a/src/parse/mod.rs
+++ b/src/parse/mod.rs
@@ -730,14 +730,11 @@ impl Parse for ExpString {
}
}
- let x = b.peek();
+ let x = b.adv();
if x == b'\\' {
- b.adv();
add_char(p, parse_escape_code(b)?);
} else if x == b'$' && !delim.is_strict() {
- b.adv();
-
if !b.has() {
add_char(p, b'$');
continue;
@@ -745,98 +742,99 @@ impl Parse for ExpString {
let x = b.peek();
- if x == b'?' || x == b'!' {
- b.adv();
- p.push(StringPart::Var(Var::new(VarName { name: vec![x] })))
- } else if is_var_begin(x) {
+ if is_var_begin(x) {
let v = VarName::parse(b)?;
p.push(StringPart::Var(Var::new(v)));
- } else if x == b'{' {
- b.adv();
- let v = VarName::parse(b)?;
- let mut default = None;
+ continue;
+ }
+
+ b.adv();
+
+ match x {
+ b'?' | b'!' => p.push(StringPart::Var(Var::new(VarName { name: vec![x] }))),
+ b'{' => {
+ let v = VarName::parse(b)?;
+ let mut default = None;
- if !b.has() {
- if !b.is_completion() {
- return Err(ParseError::Eof);
- }
- } else if b.peek() == b':' {
- b.adv();
if !b.has() {
- return Err(ParseError::Eof);
- }
- if b.peek() == b'-' {
+ if !b.is_completion() {
+ return Err(ParseError::Eof);
+ }
+ } else if b.peek() == b':' {
b.adv();
- default = Some(ExpString::parse(b)?);
- } else {
- todo!(": in var expansion")
+ if !b.has() {
+ return Err(ParseError::Eof);
+ }
+ if b.peek() == b'-' {
+ b.adv();
+ default = Some(ExpString::parse(b)?);
+ } else {
+ todo!(": in var expansion")
+ }
}
- }
- if !b.has() {
- if !b.is_completion() {
- return Err(ParseError::Eof);
+ if !b.has() {
+ if !b.is_completion() {
+ return Err(ParseError::Eof);
+ }
+ } else if b.peek() != b'}' {
+ return Err(ParseError::Expected('}'));
}
- } else if b.peek() != b'}' {
- return Err(ParseError::Expected('}'));
- }
- let already_complete = b.has();
+ let already_complete = b.has();
- if already_complete {
- b.adv();
- }
+ if already_complete {
+ b.adv();
+ }
- p.push(StringPart::Var(Var {
- name: v,
- default,
- already_complete,
- }));
- } else if x == b'(' {
- b.adv();
- let cmd = Ast::parse(b)?;
- b.spaces();
-
- if b.is_empty() && !b.is_completion() {
- return Err(ParseError::Expected(')'));
+ p.push(StringPart::Var(Var {
+ name: v,
+ default,
+ already_complete,
+ }));
}
+ b'(' => {
+ let cmd = Ast::parse(b)?;
+ b.spaces();
- if b.has() && b.peek() == b')' {
- b.adv();
- p.push(StringPart::Cmd(CmdInterp {
- cmd,
- already_complete: true,
- }));
- } else if b.is_completion() {
- p.push(StringPart::Cmd(CmdInterp {
- cmd,
- already_complete: false,
- }))
- } else {
- return Err(ParseError::Expected(')'));
+ if b.is_empty() && !b.is_completion() {
+ return Err(ParseError::Expected(')'));
+ }
+
+ if b.has() && b.peek() == b')' {
+ b.adv();
+ p.push(StringPart::Cmd(CmdInterp {
+ cmd,
+ already_complete: true,
+ }));
+ } else if b.is_completion() {
+ p.push(StringPart::Cmd(CmdInterp {
+ cmd,
+ already_complete: false,
+ }))
+ } else {
+ return Err(ParseError::Expected(')'));
+ }
+ }
+ x => {
+ add_char(p, b'$');
+ add_char(p, x);
}
- } else {
- // doesn't seem to be a variable or expansion, just add $ back into the string
- add_char(p, b'$');
}
+ } else if delim.is_none()
+ && x == b'~'
+ && p.is_empty()
+ && (!b.has() || b.peek().is_ascii_whitespace() || b.peek() == b'/')
+ {
+ p.push(StringPart::Var(Var {
+ name: VarName {
+ name: b"HOME".to_vec(),
+ },
+ default: None,
+ already_complete: true,
+ }));
} else {
- b.adv();
-
- if delim.is_none()
- && x == b'~'
- && p.is_empty()
- && (!b.has() || b.peek().is_ascii_whitespace() || b.peek() == b'/')
- {
- p.push(StringPart::Var(Var {
- name: VarName {
- name: b"HOME".to_vec(),
- },
- default: None,
- already_complete: true,
- }));
- } else {
- add_char(p, x);
- }
+ add_char(p, x);
}
}
}
diff --git a/src/parse/test.rs b/src/parse/test.rs
index 3513c3f..3058730 100644
--- a/src/parse/test.rs
+++ b/src/parse/test.rs
@@ -321,3 +321,11 @@ fn exit_code_2() {
pipes([cmd([estr(b"echo"), str([var(b"?")])])])
)
}
+
+#[test]
+fn dollar_non_var() {
+ parse_test!(
+ parse(b"echo $_"),
+ pipes([cmd([estr(b"echo"), estr(b"$_")]),])
+ )
+}