diff --git a/src/expand.rs b/src/expand.rs index 29807c2..cf42bf5 100644 --- a/src/expand.rs +++ b/src/expand.rs @@ -546,97 +546,25 @@ pub fn expand_prompt(raw: &str) -> ShResult { /// Expand aliases in the given input string pub fn expand_aliases(input: String, mut already_expanded: HashSet) -> String { - let mut result = String::new(); - let mut cur_word = String::new(); - let mut chars = input.chars().peekable(); - let mut is_cmd = true; + let mut result = input.clone(); + let tokens: Vec<_> = LexStream::new(Rc::new(input), LexFlags::empty()).collect(); + let mut expanded_this_iter: Vec = vec![]; - let mut expanded_this_iter = HashSet::new(); - while let Some(ch) = chars.next() { - match ch { - ';' | '\n' => { - if is_cmd { - if !is_keyword(&cur_word) { - if !already_expanded.contains(&cur_word) { - if let Some(alias) = read_logic(|l| l.get_alias(&cur_word)) { - result.push_str(&alias); - expanded_this_iter.insert(cur_word.clone()); - cur_word.clear(); - } else { - result.push_str(&mem::take(&mut cur_word)); - } - } - } else { - result.push_str(&mem::take(&mut cur_word)); - } - } else { - result.push_str(&mem::take(&mut cur_word)); - } - result.push(ch); - is_cmd = true; - while let Some(next_ch) = chars.peek() { - if is_hard_sep(*next_ch) { - result.push(chars.next().unwrap()); - } else { - break - } - } - } - ' ' | '\t' => { - if is_cmd { - if !is_keyword(&cur_word) { - if let Some(alias) = read_logic(|l| l.get_alias(&cur_word)) { - if !already_expanded.contains(&cur_word) { - result.push_str(&alias); - expanded_this_iter.insert(cur_word.clone()); - cur_word.clear(); - } else { - result.push_str(&mem::take(&mut cur_word)); - } - is_cmd = false; - } else { - result.push_str(&mem::take(&mut cur_word)); - is_cmd = false; - } - } else { - result.push_str(&mem::take(&mut cur_word)); - } - } else { - result.push_str(&mem::take(&mut cur_word)); - } - result.push(ch); - while let Some(next_ch) = chars.peek() { - if is_field_sep(*next_ch) { - result.push(chars.next().unwrap()); - } else { - break - } - } - } - _ => cur_word.push(ch) - } - } - if !cur_word.is_empty() { - if is_cmd { - if !is_keyword(&cur_word) { - if let Some(alias) = read_logic(|l| l.get_alias(&cur_word)) { - if !already_expanded.contains(&cur_word) { - result.push_str(&alias); - expanded_this_iter.insert(cur_word.clone()); - cur_word.clear(); - } else { - result.push_str(&mem::take(&mut cur_word)); - } - } else { - result.push_str(&mem::take(&mut cur_word)); - } - } else { - result.push_str(&mem::take(&mut cur_word)); - } - } else { - result.push_str(&mem::take(&mut cur_word)); + for token_result in tokens.into_iter().rev() { + let Ok(tk) = token_result else { continue }; + + if !tk.flags.contains(TkFlags::IS_CMD) { continue } + + let raw_tk = tk.span.as_str().to_string(); + + if already_expanded.contains(&raw_tk) { continue } + + if let Some(alias) = read_logic(|l| l.get_alias(&raw_tk)) { + result.replace_range(tk.span.range(), &alias); + expanded_this_iter.push(raw_tk); } } + if expanded_this_iter.is_empty() { return result } else { diff --git a/src/fern.rs b/src/fern.rs index 09a17dc..6a96501 100644 --- a/src/fern.rs +++ b/src/fern.rs @@ -14,7 +14,7 @@ use std::collections::HashSet; use expand::expand_aliases; use libsh::error::ShResult; -use parse::{execute::Dispatcher, lex::{LexFlags, LexStream}, Ast, ParseStream, ParsedSrc}; +use parse::{execute::Dispatcher, lex::{LexFlags, LexStream, Tk}, Ast, ParseStream, ParsedSrc}; use procio::IoFrame; use signal::sig_setup; use state::{source_rc, write_logic, write_meta}; diff --git a/src/parse/execute.rs b/src/parse/execute.rs index b93db39..c32c260 100644 --- a/src/parse/execute.rs +++ b/src/parse/execute.rs @@ -3,7 +3,7 @@ use std::collections::VecDeque; use crate::{builtin::{alias::alias, cd::cd, echo::echo, export::export, jobctl::{continue_job, jobs, JobBehavior}, pwd::pwd, shift::shift, source::source}, exec_input, jobs::{dispatch_job, ChildProc, Job, JobBldr, JobStack}, libsh::{error::{ShErr, ShErrKind, ShResult, ShResultExt}, utils::RedirVecUtils}, prelude::*, procio::{IoFrame, IoMode, IoStack}, state::{self, read_logic, read_vars, write_logic, write_vars, ShFunc, VarTab}}; -use super::{lex::{LexFlags, LexStream, Span, Tk, TkFlags, KEYWORDS}, AssignKind, CondNode, ConjunctNode, ConjunctOp, LoopKind, NdFlags, NdRule, Node, ParseStream, ParsedSrc, Redir, RedirType}; +use super::{lex::{LexFlags, LexStream, Span, Tk, TkFlags, KEYWORDS}, AssignKind, CaseNode, CondNode, ConjunctNode, ConjunctOp, LoopKind, NdFlags, NdRule, Node, ParseStream, ParsedSrc, Redir, RedirType}; pub enum AssignBehavior { Export, @@ -62,6 +62,7 @@ impl Dispatcher { NdRule::Pipeline {..} => self.exec_pipeline(node)?, NdRule::IfNode {..} => self.exec_if(node)?, NdRule::LoopNode {..} => self.exec_loop(node)?, + NdRule::CaseNode {..} => self.exec_case(node)?, NdRule::BraceGrp {..} => self.exec_brc_grp(node)?, NdRule::FuncDef {..} => self.exec_func_def(node)?, NdRule::Command {..} => self.dispatch_cmd(node)?, @@ -181,6 +182,39 @@ impl Dispatcher { Ok(()) } + pub fn exec_case(&mut self, case_stmt: Node) -> ShResult<()> { + let NdRule::CaseNode { pattern, case_blocks } = case_stmt.class else { + unreachable!() + }; + + self.io_stack.append_to_frame(case_stmt.redirs); + + flog!(DEBUG,pattern.span.as_str()); + let exp_pattern = pattern.clone().expand(pattern.span.clone(), pattern.flags.clone()); + let pattern_raw = exp_pattern + .get_words() + .first() + .map(|s| s.to_string()) + .unwrap_or_default(); + flog!(DEBUG,exp_pattern); + + for block in case_blocks { + let CaseNode { pattern, body } = block; + let block_pattern_raw = pattern.span.as_str().trim_end_matches(')').trim(); + // Split at '|' to allow for multiple patterns like `foo|bar)` + let block_patterns = block_pattern_raw.split('|'); + + for pattern in block_patterns { + if pattern_raw == pattern || pattern == "*" { + for node in &body { + self.dispatch_node(node.clone())?; + } + } + } + } + + Ok(()) + } pub fn exec_loop(&mut self, loop_stmt: Node) -> ShResult<()> { let NdRule::LoopNode { kind, cond_node } = loop_stmt.class else { unreachable!(); diff --git a/src/parse/lex.rs b/src/parse/lex.rs index 851b7a7..aac8ebe 100644 --- a/src/parse/lex.rs +++ b/src/parse/lex.rs @@ -1,4 +1,4 @@ -use std::{fmt::Display, ops::{Bound, Deref, Range, RangeBounds}}; +use std::{fmt::Display, ops::{Bound, Deref, Range, RangeBounds}, str::Chars}; use bitflags::bitflags; @@ -76,6 +76,7 @@ pub enum TkRule { Bg, Sep, Redir, + CasePattern, BraceGrpStart, BraceGrpEnd, Expanded { exp: Vec }, @@ -110,6 +111,13 @@ impl Tk { pub fn source(&self) -> Rc { self.span.source.clone() } + /// Used to see if a separator is ';;' for case statements + pub fn has_double_semi(&self) -> bool { + let TkRule::Sep = self.class else { + return false; + }; + self.span.as_str().trim() == ";;" + } } impl Display for Tk { @@ -143,6 +151,7 @@ pub struct LexStream { } bitflags! { + #[derive(Debug)] pub struct LexFlags: u32 { /// Return comment tokens const LEX_COMMENTS = 0b00000001; @@ -158,7 +167,9 @@ bitflags! { const FRESH = 0b00010000; /// The lexer has no more tokens to produce const STALE = 0b00100000; + /// The lexer's cursor is in a brace group const IN_BRC_GRP = 0b01000000; + const EXPECTING_IN = 0b10000000; } } @@ -300,6 +311,15 @@ impl LexStream { let mut pos = self.cursor; let mut chars = slice.chars(); let mut quote_pos = None; + + if let Some(count) = case_pat_lookahead(chars.clone()) { + pos += count; + let casepat_tk = self.get_token(self.cursor..pos, TkRule::CasePattern); + self.cursor = pos; + self.set_next_is_cmd(true); + return Ok(casepat_tk) + } + while let Some(ch) = chars.next() { match ch { _ if self.flags.contains(LexFlags::RAW) => { @@ -373,22 +393,39 @@ impl LexStream { ) ); } + // TODO: clean up this mess if self.flags.contains(LexFlags::NEXT_IS_CMD) { - flog!(DEBUG,&new_tk.span.as_str()); if is_keyword(&new_tk.span.as_str()) { - flog!(DEBUG,"is keyword"); - new_tk.flags |= TkFlags::KEYWORD; + if matches!(new_tk.span.as_str(), "case" | "select" | "for") { + self.flags |= LexFlags::EXPECTING_IN; + new_tk.flags |= TkFlags::KEYWORD; + self.set_next_is_cmd(false); + } else { + new_tk.flags |= TkFlags::KEYWORD; + } } else if is_assignment(&new_tk.span.as_str()) { new_tk.flags |= TkFlags::ASSIGN; } else { - new_tk.flags |= TkFlags::IS_CMD; - flog!(TRACE, new_tk.span.as_str()); + if self.flags.contains(LexFlags::EXPECTING_IN) { + if new_tk.span.as_str() != "in" { + new_tk.flags |= TkFlags::IS_CMD; + } else { + new_tk.flags |= TkFlags::KEYWORD; + self.flags &= !LexFlags::EXPECTING_IN; + } + } else { + new_tk.flags |= TkFlags::IS_CMD; + } if BUILTINS.contains(&new_tk.span.as_str()) { new_tk.flags |= TkFlags::BUILTIN; } - flog!(TRACE, new_tk.flags); self.set_next_is_cmd(false); } + } else if self.flags.contains(LexFlags::EXPECTING_IN) { + if new_tk.span.as_str() == "in" { + new_tk.flags |= TkFlags::KEYWORD; + self.flags &= !LexFlags::EXPECTING_IN; + } } self.cursor = pos; Ok(new_tk) @@ -557,3 +594,18 @@ pub fn is_keyword(slice: &str) -> bool { KEYWORDS.contains(&slice) || (slice.ends_with("()") && !slice.ends_with("\\()")) } + +pub fn case_pat_lookahead(mut chars: Chars) -> Option { + let mut pos = 0; + while let Some(ch) = chars.next() { + pos += 1; + match ch { + _ if is_hard_sep(ch) => return None, + '\\' => { chars.next(); } + ')' => return Some(pos), + '(' => return None, + _ => { /* continue */ } + } + } + None +} diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 84fa59b..8c9a7fb 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -385,9 +385,16 @@ impl ParseStream { fn next_tk_is_some(&self) -> bool { self.tokens.first().is_some_and(|tk| tk.class != TkRule::EOI) } + fn check_case_pattern(&self) -> bool { + self.tokens.first().is_some_and(|tk| tk.class == TkRule::CasePattern) + } fn check_keyword(&self, kw: &str) -> bool { self.tokens.first().is_some_and(|tk| { - tk.flags.contains(TkFlags::KEYWORD) && tk.span.as_str() == kw + if kw == "in" { + tk.span.as_str() == "in" + } else { + tk.flags.contains(TkFlags::KEYWORD) && tk.span.as_str() == kw + } }) } fn check_redir(&self) -> bool { @@ -441,6 +448,7 @@ impl ParseStream { fn parse_block(&mut self, check_pipelines: bool) -> ShResult> { try_match!(self.parse_func_def()?); try_match!(self.parse_brc_grp(false /* from_func_def */)?); + try_match!(self.parse_case()?); try_match!(self.parse_loop()?); try_match!(self.parse_if()?); if check_pipelines { @@ -556,6 +564,73 @@ impl ParseStream { }; Ok(Some(node)) } + fn parse_case(&mut self) -> ShResult> { + // Needs a pattern token + // Followed by any number of CaseNodes + let mut node_tks: Vec = vec![]; + let pattern: Tk; + let mut case_blocks: Vec = vec![]; + let mut redirs: Vec = vec![]; + + if !self.check_keyword("case") || !self.next_tk_is_some() { + return Ok(None) + } + node_tks.push(self.next_tk().unwrap()); + + let Some(pat_tk) = self.next_tk() else { + return Err(parse_err_full("Expected a pattern after 'case'", &node_tks.get_span().unwrap())); + }; + + pattern = pat_tk; + node_tks.push(pattern.clone()); + + if !self.check_keyword("in") || !self.next_tk_is_some() { + return Err(parse_err_full("Expected 'in' after case variable name", &node_tks.get_span().unwrap())); + } + node_tks.push(self.next_tk().unwrap()); + + self.catch_separator(&mut node_tks); + + loop { + if !self.check_case_pattern() || !self.next_tk_is_some() { + return Err(parse_err_full("Expected a case pattern here", &node_tks.get_span().unwrap())); + } + let case_pat_tk = self.next_tk().unwrap(); + node_tks.push(case_pat_tk.clone()); + + let mut nodes = vec![]; + while let Some(node) = self.parse_block(true /* check_pipelines */)? { + node_tks.extend(node.tokens.clone()); + let sep = node.tokens.last().unwrap(); + if sep.has_double_semi() { + nodes.push(node); + break + } else { + nodes.push(node); + } + } + + let case_node = CaseNode { pattern: case_pat_tk, body: nodes }; + case_blocks.push(case_node); + + if self.check_keyword("esac") { + node_tks.push(self.next_tk().unwrap()); + break + } + + if !self.next_tk_is_some() { + return Err(parse_err_full("Expected 'esac' after case block", &node_tks.get_span().unwrap())); + } + } + + let node = Node { + class: NdRule::CaseNode { pattern, case_blocks }, + flags: NdFlags::empty(), + redirs, + tokens: node_tks + }; + Ok(Some(node)) + } fn parse_if(&mut self) -> ShResult> { // Needs at last one 'if-then', // Any number of 'elif-then', @@ -563,7 +638,7 @@ impl ParseStream { let mut node_tks: Vec = vec![]; let mut cond_nodes: Vec = vec![]; let mut else_block: Vec = vec![]; - let mut redirs = vec![]; + let mut redirs: Vec = vec![]; if !self.check_keyword("if") || !self.next_tk_is_some() { return Ok(None) diff --git a/src/prompt/readline.rs b/src/prompt/readline.rs index fee404f..9529e75 100644 --- a/src/prompt/readline.rs +++ b/src/prompt/readline.rs @@ -66,7 +66,6 @@ impl Highlighter for FernReadline { impl Validator for FernReadline { fn validate(&self, ctx: &mut rustyline::validate::ValidationContext) -> rustyline::Result { - return Ok(ValidationResult::Valid(None)); let mut tokens = vec![]; let tk_stream = LexStream::new(Rc::new(ctx.input().to_string()), LexFlags::empty()); for tk in tk_stream { diff --git a/src/tests/lexer.rs b/src/tests/lexer.rs index ec5c207..e5dfec3 100644 --- a/src/tests/lexer.rs +++ b/src/tests/lexer.rs @@ -42,3 +42,11 @@ fn lex_multiline() { insta::assert_debug_snapshot!(tokens) } + +#[test] +fn lex_case() { + let input = "case $foo in foo) bar;; bar) foo;; biz) baz;; esac"; + let tokens: Vec<_> = LexStream::new(Rc::new(input.to_string()), LexFlags::empty()).collect(); + + insta::assert_debug_snapshot!(tokens) +} diff --git a/src/tests/parser.rs b/src/tests/parser.rs index 698a733..b325f75 100644 --- a/src/tests/parser.rs +++ b/src/tests/parser.rs @@ -138,3 +138,49 @@ done"; insta::assert_debug_snapshot!(nodes) } +#[test] +fn parse_case_simple() { + let input = "case foo in foo) bar;; bar) foo;; biz) baz;; esac"; + let tk_stream: Vec<_> = LexStream::new(Rc::new(input.to_string()), LexFlags::empty()) + .map(|tk| tk.unwrap()) + .collect(); + let nodes: Vec<_> = ParseStream::new(tk_stream).collect(); + + insta::assert_debug_snapshot!(nodes) +} +#[test] +fn parse_case_multiline() { + let input = "case foo in + foo) bar + ;; + bar) foo + ;; + biz) baz + ;; +esac"; + let tk_stream: Vec<_> = LexStream::new(Rc::new(input.to_string()), LexFlags::empty()) + .map(|tk| tk.unwrap()) + .collect(); + let nodes: Vec<_> = ParseStream::new(tk_stream).collect(); + + insta::assert_debug_snapshot!(nodes) +} +#[test] +fn parse_case_nested() { + let input = "case foo in + foo) if true; then + echo foo + fi + ;; + bar) if false; then + echo bar + fi + ;; +esac"; + let tk_stream: Vec<_> = LexStream::new(Rc::new(input.to_string()), LexFlags::empty()) + .map(|tk| tk.unwrap()) + .collect(); + let nodes: Vec<_> = ParseStream::new(tk_stream).collect(); + + insta::assert_debug_snapshot!(nodes) +} diff --git a/src/tests/snapshots/fern__tests__lexer__lex_case.snap b/src/tests/snapshots/fern__tests__lexer__lex_case.snap new file mode 100644 index 0000000..713bb49 --- /dev/null +++ b/src/tests/snapshots/fern__tests__lexer__lex_case.snap @@ -0,0 +1,186 @@ +--- +source: src/tests/lexer.rs +expression: tokens +--- +[ + Ok( + Tk { + class: SOI, + span: Span { + range: 0..0, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ), + Ok( + Tk { + class: Str, + span: Span { + range: 0..4, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + ), + Ok( + Tk { + class: Str, + span: Span { + range: 5..9, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ), + Ok( + Tk { + class: Str, + span: Span { + range: 10..12, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + ), + Ok( + Tk { + class: CasePattern, + span: Span { + range: 13..17, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ), + Ok( + Tk { + class: Str, + span: Span { + range: 18..21, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + ), + Ok( + Tk { + class: Sep, + span: Span { + range: 21..24, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ), + Ok( + Tk { + class: CasePattern, + span: Span { + range: 24..28, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ), + Ok( + Tk { + class: Str, + span: Span { + range: 29..32, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + ), + Ok( + Tk { + class: Sep, + span: Span { + range: 32..35, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ), + Ok( + Tk { + class: CasePattern, + span: Span { + range: 35..39, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ), + Ok( + Tk { + class: Str, + span: Span { + range: 40..43, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + ), + Ok( + Tk { + class: Sep, + span: Span { + range: 43..46, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ), + Ok( + Tk { + class: Str, + span: Span { + range: 46..50, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + ), + Ok( + Tk { + class: EOI, + span: Span { + range: 50..50, + source: "case $foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ), +] diff --git a/src/tests/snapshots/fern__tests__parser__parse_case_multiline.snap b/src/tests/snapshots/fern__tests__parser__parse_case_multiline.snap new file mode 100644 index 0000000..65849b8 --- /dev/null +++ b/src/tests/snapshots/fern__tests__parser__parse_case_multiline.snap @@ -0,0 +1,595 @@ +--- +source: src/tests/parser.rs +expression: nodes +--- +[ + Ok( + Node { + class: Conjunction { + elements: [ + ConjunctNode { + cmd: Node { + class: CaseNode { + pattern: Tk { + class: Str, + span: Span { + range: 5..8, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + case_blocks: [ + CaseNode { + pattern: Tk { + class: CasePattern, + span: Span { + range: 13..17, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + body: [ + Node { + class: Pipeline { + cmds: [ + Node { + class: Command { + assignments: [], + argv: [ + Tk { + class: Str, + span: Span { + range: 18..21, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 18..21, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 21..27, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + pipe_err: false, + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 18..21, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 21..27, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + }, + CaseNode { + pattern: Tk { + class: CasePattern, + span: Span { + range: 27..31, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + body: [ + Node { + class: Pipeline { + cmds: [ + Node { + class: Command { + assignments: [], + argv: [ + Tk { + class: Str, + span: Span { + range: 32..35, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 32..35, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 35..41, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + pipe_err: false, + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 32..35, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 35..41, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + }, + CaseNode { + pattern: Tk { + class: CasePattern, + span: Span { + range: 41..45, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + body: [ + Node { + class: Pipeline { + cmds: [ + Node { + class: Command { + assignments: [], + argv: [ + Tk { + class: Str, + span: Span { + range: 46..49, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 46..49, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 49..54, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + pipe_err: false, + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 46..49, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 49..54, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 0..4, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Str, + span: Span { + range: 5..8, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 9..11, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 11..13, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 13..17, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 18..21, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 21..27, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 27..31, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 32..35, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 35..41, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 41..45, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 46..49, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 49..54, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 54..58, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + ], + }, + operator: Null, + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 0..4, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Str, + span: Span { + range: 5..8, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 9..11, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 11..13, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 13..17, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 18..21, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 21..27, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 27..31, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 32..35, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 35..41, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 41..45, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 46..49, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 49..54, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 54..58, + source: "case foo in\n\tfoo) bar\n\t;;\n\tbar) foo\n\t;;\n\tbiz) baz\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + ], + }, + ), +] diff --git a/src/tests/snapshots/fern__tests__parser__parse_case_nested.snap b/src/tests/snapshots/fern__tests__parser__parse_case_nested.snap new file mode 100644 index 0000000..38c6622 --- /dev/null +++ b/src/tests/snapshots/fern__tests__parser__parse_case_nested.snap @@ -0,0 +1,1211 @@ +--- +source: src/tests/parser.rs +expression: nodes +--- +[ + Ok( + Node { + class: Conjunction { + elements: [ + ConjunctNode { + cmd: Node { + class: CaseNode { + pattern: Tk { + class: Str, + span: Span { + range: 5..8, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + case_blocks: [ + CaseNode { + pattern: Tk { + class: CasePattern, + span: Span { + range: 13..17, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + body: [ + Node { + class: IfNode { + cond_nodes: [ + CondNode { + cond: Node { + class: Pipeline { + cmds: [ + Node { + class: Command { + assignments: [], + argv: [ + Tk { + class: Str, + span: Span { + range: 21..25, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 21..25, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 25..27, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + pipe_err: false, + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 21..25, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 25..27, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + body: [ + Node { + class: Pipeline { + cmds: [ + Node { + class: Command { + assignments: [], + argv: [ + Tk { + class: Str, + span: Span { + range: 34..38, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD | BUILTIN, + ), + }, + Tk { + class: Str, + span: Span { + range: 39..42, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 34..38, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD | BUILTIN, + ), + }, + Tk { + class: Str, + span: Span { + range: 39..42, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Sep, + span: Span { + range: 42..44, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + pipe_err: false, + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 34..38, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD | BUILTIN, + ), + }, + Tk { + class: Str, + span: Span { + range: 39..42, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Sep, + span: Span { + range: 42..44, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + }, + ], + else_block: [], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 18..20, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Str, + span: Span { + range: 21..25, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 25..27, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 27..31, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 31..34, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 34..38, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD | BUILTIN, + ), + }, + Tk { + class: Str, + span: Span { + range: 39..42, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Sep, + span: Span { + range: 42..44, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 44..46, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 46..52, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + }, + CaseNode { + pattern: Tk { + class: CasePattern, + span: Span { + range: 52..56, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + body: [ + Node { + class: IfNode { + cond_nodes: [ + CondNode { + cond: Node { + class: Pipeline { + cmds: [ + Node { + class: Command { + assignments: [], + argv: [ + Tk { + class: Str, + span: Span { + range: 60..65, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 60..65, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 65..67, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + pipe_err: false, + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 60..65, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 65..67, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + body: [ + Node { + class: Pipeline { + cmds: [ + Node { + class: Command { + assignments: [], + argv: [ + Tk { + class: Str, + span: Span { + range: 74..78, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD | BUILTIN, + ), + }, + Tk { + class: Str, + span: Span { + range: 79..82, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 74..78, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD | BUILTIN, + ), + }, + Tk { + class: Str, + span: Span { + range: 79..82, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Sep, + span: Span { + range: 82..84, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + pipe_err: false, + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 74..78, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD | BUILTIN, + ), + }, + Tk { + class: Str, + span: Span { + range: 79..82, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Sep, + span: Span { + range: 82..84, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + }, + ], + else_block: [], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 57..59, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Str, + span: Span { + range: 60..65, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 65..67, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 67..71, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 71..74, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 74..78, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD | BUILTIN, + ), + }, + Tk { + class: Str, + span: Span { + range: 79..82, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Sep, + span: Span { + range: 82..84, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 84..86, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 86..91, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 0..4, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Str, + span: Span { + range: 5..8, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 9..11, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 11..13, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 13..17, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 18..20, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Str, + span: Span { + range: 21..25, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 25..27, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 27..31, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 31..34, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 34..38, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD | BUILTIN, + ), + }, + Tk { + class: Str, + span: Span { + range: 39..42, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Sep, + span: Span { + range: 42..44, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 44..46, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 46..52, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 52..56, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 57..59, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Str, + span: Span { + range: 60..65, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 65..67, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 67..71, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 71..74, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 74..78, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD | BUILTIN, + ), + }, + Tk { + class: Str, + span: Span { + range: 79..82, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Sep, + span: Span { + range: 82..84, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 84..86, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 86..91, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 91..95, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + ], + }, + operator: Null, + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 0..4, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Str, + span: Span { + range: 5..8, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 9..11, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 11..13, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 13..17, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 18..20, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Str, + span: Span { + range: 21..25, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 25..27, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 27..31, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 31..34, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 34..38, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD | BUILTIN, + ), + }, + Tk { + class: Str, + span: Span { + range: 39..42, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Sep, + span: Span { + range: 42..44, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 44..46, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 46..52, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 52..56, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 57..59, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Str, + span: Span { + range: 60..65, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 65..67, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 67..71, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 71..74, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 74..78, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + IS_CMD | BUILTIN, + ), + }, + Tk { + class: Str, + span: Span { + range: 79..82, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Sep, + span: Span { + range: 82..84, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 84..86, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 86..91, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 91..95, + source: "case foo in\n\tfoo) if true; then\n\t\techo foo\n\tfi\n\t;;\n\tbar) if false; then\n\t\techo bar\n\tfi\n\t;;\nesac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + ], + }, + ), +] diff --git a/src/tests/snapshots/fern__tests__parser__parse_case_simple.snap b/src/tests/snapshots/fern__tests__parser__parse_case_simple.snap new file mode 100644 index 0000000..7549e1e --- /dev/null +++ b/src/tests/snapshots/fern__tests__parser__parse_case_simple.snap @@ -0,0 +1,575 @@ +--- +source: src/tests/parser.rs +expression: nodes +--- +[ + Ok( + Node { + class: Conjunction { + elements: [ + ConjunctNode { + cmd: Node { + class: CaseNode { + pattern: Tk { + class: Str, + span: Span { + range: 5..8, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + case_blocks: [ + CaseNode { + pattern: Tk { + class: CasePattern, + span: Span { + range: 12..16, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + body: [ + Node { + class: Pipeline { + cmds: [ + Node { + class: Command { + assignments: [], + argv: [ + Tk { + class: Str, + span: Span { + range: 17..20, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 17..20, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 20..23, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + pipe_err: false, + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 17..20, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 20..23, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + }, + CaseNode { + pattern: Tk { + class: CasePattern, + span: Span { + range: 23..27, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + body: [ + Node { + class: Pipeline { + cmds: [ + Node { + class: Command { + assignments: [], + argv: [ + Tk { + class: Str, + span: Span { + range: 28..31, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 28..31, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 31..34, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + pipe_err: false, + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 28..31, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 31..34, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + }, + CaseNode { + pattern: Tk { + class: CasePattern, + span: Span { + range: 34..38, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + body: [ + Node { + class: Pipeline { + cmds: [ + Node { + class: Command { + assignments: [], + argv: [ + Tk { + class: Str, + span: Span { + range: 39..42, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 39..42, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 42..45, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + pipe_err: false, + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 39..42, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 42..45, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + ], + }, + ], + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 0..4, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Str, + span: Span { + range: 5..8, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 9..11, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 12..16, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 17..20, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 20..23, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 23..27, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 28..31, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 31..34, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 34..38, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 39..42, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 42..45, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 45..49, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + ], + }, + operator: Null, + }, + ], + }, + flags: NdFlags( + 0x0, + ), + redirs: [], + tokens: [ + Tk { + class: Str, + span: Span { + range: 0..4, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: Str, + span: Span { + range: 5..8, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 9..11, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 12..16, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 17..20, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 20..23, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 23..27, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 28..31, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 31..34, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: CasePattern, + span: Span { + range: 34..38, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 39..42, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + IS_CMD, + ), + }, + Tk { + class: Sep, + span: Span { + range: 42..45, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + 0x0, + ), + }, + Tk { + class: Str, + span: Span { + range: 45..49, + source: "case foo in foo) bar;; bar) foo;; biz) baz;; esac", + }, + flags: TkFlags( + KEYWORD, + ), + }, + ], + }, + ), +]