Scripting bug fixes and more tests

This commit is contained in:
2025-03-16 03:22:17 -04:00
parent 92d7766765
commit 51d735073f
21 changed files with 4846 additions and 823 deletions

View File

@@ -280,6 +280,20 @@ impl<'t> ParseStream<'t> {
None
}
}
/// Catches a Sep token in cases where separators are optional
///
/// e.g. both `if foo; then bar; fi` and
/// ```bash
/// if foo; then
/// bar
/// fi
/// ```
/// are valid syntax
fn catch_separator(&mut self, node_tks: &mut Vec<Tk<'t>>) {
if *self.next_tk_class() == TkRule::Sep {
node_tks.push(self.next_tk().unwrap());
}
}
fn next_tk_is_some(&self) -> bool {
self.tokens.first().is_some_and(|tk| tk.class != TkRule::EOI)
}
@@ -374,7 +388,6 @@ impl<'t> ParseStream<'t> {
&node_tks.get_span().unwrap()
));
};
cond.tokens.debug_tokens();
node_tks.extend(cond.tokens.clone());
if !self.check_keyword("then") || !self.next_tk_is_some() {
@@ -384,10 +397,10 @@ impl<'t> ParseStream<'t> {
));
}
node_tks.push(self.next_tk().unwrap());
self.catch_separator(&mut node_tks);
let mut body_blocks = vec![];
while let Some(body_block) = self.parse_block(true)? {
body_block.tokens.debug_tokens();
node_tks.extend(body_block.tokens.clone());
body_blocks.push(body_block);
}
@@ -399,18 +412,18 @@ impl<'t> ParseStream<'t> {
};
let cond_node = CondNode { cond: Box::new(cond), body: body_blocks };
cond_nodes.push(cond_node);
flog!(DEBUG, cond_nodes.len());
flog!(DEBUG, !self.check_keyword("elif") || !self.next_tk_is_some());
if !self.check_keyword("elif") || !self.next_tk_is_some() {
break
} else {
node_tks.push(self.next_tk().unwrap());
self.catch_separator(&mut node_tks);
}
}
if self.check_keyword("else") {
node_tks.push(self.next_tk().unwrap());
self.catch_separator(&mut node_tks);
while let Some(block) = self.parse_block(true)? {
else_block.push(block)
}
@@ -429,6 +442,7 @@ impl<'t> ParseStream<'t> {
));
}
node_tks.push(self.next_tk().unwrap());
self.catch_separator(&mut node_tks);
let node = Node {
class: NdRule::IfNode { cond_nodes, else_block },
@@ -436,7 +450,6 @@ impl<'t> ParseStream<'t> {
redirs: vec![],
tokens: node_tks
};
flog!(DEBUG, node);
Ok(Some(node))
}
fn parse_loop(&mut self) -> ShResult<Option<Node<'t>>> {
@@ -454,6 +467,7 @@ impl<'t> ParseStream<'t> {
.parse() // LoopKind implements FromStr
.unwrap();
node_tks.push(loop_tk);
self.catch_separator(&mut node_tks);
let Some(cond) = self.parse_block(true)? else {
return Err(parse_err_full(
@@ -470,6 +484,7 @@ impl<'t> ParseStream<'t> {
))
}
node_tks.push(self.next_tk().unwrap());
self.catch_separator(&mut node_tks);
let mut body = vec![];
while let Some(block) = self.parse_block(true)? {
@@ -490,6 +505,7 @@ impl<'t> ParseStream<'t> {
))
}
node_tks.push(self.next_tk().unwrap());
self.catch_separator(&mut node_tks);
cond_node = CondNode { cond: Box::new(cond), body };
let loop_node = Node {
@@ -498,7 +514,6 @@ impl<'t> ParseStream<'t> {
redirs: vec![],
tokens: node_tks
};
flog!(DEBUG, loop_node);
Ok(Some(loop_node))
}
fn parse_pipeline(&mut self) -> ShResult<Option<Node<'t>>> {
@@ -756,12 +771,14 @@ impl<'t> Iterator for ParseStream<'t> {
if self.flags.contains(ParseFlags::ERROR) {
return None
}
if let Some(tk) = self.tokens.first() {
if tk.class == TkRule::EOI {
while let Some(tk) = self.tokens.first() {
if let TkRule::EOI = tk.class {
return None
}
if tk.class == TkRule::SOI {
if let TkRule::SOI | TkRule::Sep = tk.class {
self.next_tk();
} else {
break
}
}
match self.parse_cmd_list() {