Implemented case statements
This commit is contained in:
104
src/expand.rs
104
src/expand.rs
@@ -546,97 +546,25 @@ pub fn expand_prompt(raw: &str) -> ShResult<String> {
|
|||||||
|
|
||||||
/// Expand aliases in the given input string
|
/// Expand aliases in the given input string
|
||||||
pub fn expand_aliases(input: String, mut already_expanded: HashSet<String>) -> String {
|
pub fn expand_aliases(input: String, mut already_expanded: HashSet<String>) -> String {
|
||||||
let mut result = String::new();
|
let mut result = input.clone();
|
||||||
let mut cur_word = String::new();
|
let tokens: Vec<_> = LexStream::new(Rc::new(input), LexFlags::empty()).collect();
|
||||||
let mut chars = input.chars().peekable();
|
let mut expanded_this_iter: Vec<String> = vec![];
|
||||||
let mut is_cmd = true;
|
|
||||||
|
|
||||||
let mut expanded_this_iter = HashSet::new();
|
for token_result in tokens.into_iter().rev() {
|
||||||
while let Some(ch) = chars.next() {
|
let Ok(tk) = token_result else { continue };
|
||||||
match ch {
|
|
||||||
';' | '\n' => {
|
if !tk.flags.contains(TkFlags::IS_CMD) { continue }
|
||||||
if is_cmd {
|
|
||||||
if !is_keyword(&cur_word) {
|
let raw_tk = tk.span.as_str().to_string();
|
||||||
if !already_expanded.contains(&cur_word) {
|
|
||||||
if let Some(alias) = read_logic(|l| l.get_alias(&cur_word)) {
|
if already_expanded.contains(&raw_tk) { continue }
|
||||||
result.push_str(&alias);
|
|
||||||
expanded_this_iter.insert(cur_word.clone());
|
if let Some(alias) = read_logic(|l| l.get_alias(&raw_tk)) {
|
||||||
cur_word.clear();
|
result.replace_range(tk.span.range(), &alias);
|
||||||
} else {
|
expanded_this_iter.push(raw_tk);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if expanded_this_iter.is_empty() {
|
if expanded_this_iter.is_empty() {
|
||||||
return result
|
return result
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use std::collections::HashSet;
|
|||||||
|
|
||||||
use expand::expand_aliases;
|
use expand::expand_aliases;
|
||||||
use libsh::error::ShResult;
|
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 procio::IoFrame;
|
||||||
use signal::sig_setup;
|
use signal::sig_setup;
|
||||||
use state::{source_rc, write_logic, write_meta};
|
use state::{source_rc, write_logic, write_meta};
|
||||||
|
|||||||
@@ -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 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 {
|
pub enum AssignBehavior {
|
||||||
Export,
|
Export,
|
||||||
@@ -62,6 +62,7 @@ impl Dispatcher {
|
|||||||
NdRule::Pipeline {..} => self.exec_pipeline(node)?,
|
NdRule::Pipeline {..} => self.exec_pipeline(node)?,
|
||||||
NdRule::IfNode {..} => self.exec_if(node)?,
|
NdRule::IfNode {..} => self.exec_if(node)?,
|
||||||
NdRule::LoopNode {..} => self.exec_loop(node)?,
|
NdRule::LoopNode {..} => self.exec_loop(node)?,
|
||||||
|
NdRule::CaseNode {..} => self.exec_case(node)?,
|
||||||
NdRule::BraceGrp {..} => self.exec_brc_grp(node)?,
|
NdRule::BraceGrp {..} => self.exec_brc_grp(node)?,
|
||||||
NdRule::FuncDef {..} => self.exec_func_def(node)?,
|
NdRule::FuncDef {..} => self.exec_func_def(node)?,
|
||||||
NdRule::Command {..} => self.dispatch_cmd(node)?,
|
NdRule::Command {..} => self.dispatch_cmd(node)?,
|
||||||
@@ -181,6 +182,39 @@ impl Dispatcher {
|
|||||||
|
|
||||||
Ok(())
|
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<()> {
|
pub fn exec_loop(&mut self, loop_stmt: Node) -> ShResult<()> {
|
||||||
let NdRule::LoopNode { kind, cond_node } = loop_stmt.class else {
|
let NdRule::LoopNode { kind, cond_node } = loop_stmt.class else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
|
|||||||
@@ -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;
|
use bitflags::bitflags;
|
||||||
|
|
||||||
@@ -76,6 +76,7 @@ pub enum TkRule {
|
|||||||
Bg,
|
Bg,
|
||||||
Sep,
|
Sep,
|
||||||
Redir,
|
Redir,
|
||||||
|
CasePattern,
|
||||||
BraceGrpStart,
|
BraceGrpStart,
|
||||||
BraceGrpEnd,
|
BraceGrpEnd,
|
||||||
Expanded { exp: Vec<String> },
|
Expanded { exp: Vec<String> },
|
||||||
@@ -110,6 +111,13 @@ impl Tk {
|
|||||||
pub fn source(&self) -> Rc<String> {
|
pub fn source(&self) -> Rc<String> {
|
||||||
self.span.source.clone()
|
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 {
|
impl Display for Tk {
|
||||||
@@ -143,6 +151,7 @@ pub struct LexStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct LexFlags: u32 {
|
pub struct LexFlags: u32 {
|
||||||
/// Return comment tokens
|
/// Return comment tokens
|
||||||
const LEX_COMMENTS = 0b00000001;
|
const LEX_COMMENTS = 0b00000001;
|
||||||
@@ -158,7 +167,9 @@ bitflags! {
|
|||||||
const FRESH = 0b00010000;
|
const FRESH = 0b00010000;
|
||||||
/// The lexer has no more tokens to produce
|
/// The lexer has no more tokens to produce
|
||||||
const STALE = 0b00100000;
|
const STALE = 0b00100000;
|
||||||
|
/// The lexer's cursor is in a brace group
|
||||||
const IN_BRC_GRP = 0b01000000;
|
const IN_BRC_GRP = 0b01000000;
|
||||||
|
const EXPECTING_IN = 0b10000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,6 +311,15 @@ impl LexStream {
|
|||||||
let mut pos = self.cursor;
|
let mut pos = self.cursor;
|
||||||
let mut chars = slice.chars();
|
let mut chars = slice.chars();
|
||||||
let mut quote_pos = None;
|
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() {
|
while let Some(ch) = chars.next() {
|
||||||
match ch {
|
match ch {
|
||||||
_ if self.flags.contains(LexFlags::RAW) => {
|
_ 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) {
|
if self.flags.contains(LexFlags::NEXT_IS_CMD) {
|
||||||
flog!(DEBUG,&new_tk.span.as_str());
|
|
||||||
if is_keyword(&new_tk.span.as_str()) {
|
if is_keyword(&new_tk.span.as_str()) {
|
||||||
flog!(DEBUG,"is keyword");
|
if matches!(new_tk.span.as_str(), "case" | "select" | "for") {
|
||||||
new_tk.flags |= TkFlags::KEYWORD;
|
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()) {
|
} else if is_assignment(&new_tk.span.as_str()) {
|
||||||
new_tk.flags |= TkFlags::ASSIGN;
|
new_tk.flags |= TkFlags::ASSIGN;
|
||||||
} else {
|
} else {
|
||||||
new_tk.flags |= TkFlags::IS_CMD;
|
if self.flags.contains(LexFlags::EXPECTING_IN) {
|
||||||
flog!(TRACE, new_tk.span.as_str());
|
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()) {
|
if BUILTINS.contains(&new_tk.span.as_str()) {
|
||||||
new_tk.flags |= TkFlags::BUILTIN;
|
new_tk.flags |= TkFlags::BUILTIN;
|
||||||
}
|
}
|
||||||
flog!(TRACE, new_tk.flags);
|
|
||||||
self.set_next_is_cmd(false);
|
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;
|
self.cursor = pos;
|
||||||
Ok(new_tk)
|
Ok(new_tk)
|
||||||
@@ -557,3 +594,18 @@ pub fn is_keyword(slice: &str) -> bool {
|
|||||||
KEYWORDS.contains(&slice) ||
|
KEYWORDS.contains(&slice) ||
|
||||||
(slice.ends_with("()") && !slice.ends_with("\\()"))
|
(slice.ends_with("()") && !slice.ends_with("\\()"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn case_pat_lookahead(mut chars: Chars) -> Option<usize> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -385,9 +385,16 @@ impl ParseStream {
|
|||||||
fn next_tk_is_some(&self) -> bool {
|
fn next_tk_is_some(&self) -> bool {
|
||||||
self.tokens.first().is_some_and(|tk| tk.class != TkRule::EOI)
|
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 {
|
fn check_keyword(&self, kw: &str) -> bool {
|
||||||
self.tokens.first().is_some_and(|tk| {
|
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 {
|
fn check_redir(&self) -> bool {
|
||||||
@@ -441,6 +448,7 @@ impl ParseStream {
|
|||||||
fn parse_block(&mut self, check_pipelines: bool) -> ShResult<Option<Node>> {
|
fn parse_block(&mut self, check_pipelines: bool) -> ShResult<Option<Node>> {
|
||||||
try_match!(self.parse_func_def()?);
|
try_match!(self.parse_func_def()?);
|
||||||
try_match!(self.parse_brc_grp(false /* from_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_loop()?);
|
||||||
try_match!(self.parse_if()?);
|
try_match!(self.parse_if()?);
|
||||||
if check_pipelines {
|
if check_pipelines {
|
||||||
@@ -556,6 +564,73 @@ impl ParseStream {
|
|||||||
};
|
};
|
||||||
Ok(Some(node))
|
Ok(Some(node))
|
||||||
}
|
}
|
||||||
|
fn parse_case(&mut self) -> ShResult<Option<Node>> {
|
||||||
|
// Needs a pattern token
|
||||||
|
// Followed by any number of CaseNodes
|
||||||
|
let mut node_tks: Vec<Tk> = vec![];
|
||||||
|
let pattern: Tk;
|
||||||
|
let mut case_blocks: Vec<CaseNode> = vec![];
|
||||||
|
let mut redirs: Vec<Redir> = 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<Option<Node>> {
|
fn parse_if(&mut self) -> ShResult<Option<Node>> {
|
||||||
// Needs at last one 'if-then',
|
// Needs at last one 'if-then',
|
||||||
// Any number of 'elif-then',
|
// Any number of 'elif-then',
|
||||||
@@ -563,7 +638,7 @@ impl ParseStream {
|
|||||||
let mut node_tks: Vec<Tk> = vec![];
|
let mut node_tks: Vec<Tk> = vec![];
|
||||||
let mut cond_nodes: Vec<CondNode> = vec![];
|
let mut cond_nodes: Vec<CondNode> = vec![];
|
||||||
let mut else_block: Vec<Node> = vec![];
|
let mut else_block: Vec<Node> = vec![];
|
||||||
let mut redirs = vec![];
|
let mut redirs: Vec<Redir> = vec![];
|
||||||
|
|
||||||
if !self.check_keyword("if") || !self.next_tk_is_some() {
|
if !self.check_keyword("if") || !self.next_tk_is_some() {
|
||||||
return Ok(None)
|
return Ok(None)
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ impl Highlighter for FernReadline {
|
|||||||
|
|
||||||
impl Validator for FernReadline {
|
impl Validator for FernReadline {
|
||||||
fn validate(&self, ctx: &mut rustyline::validate::ValidationContext) -> rustyline::Result<rustyline::validate::ValidationResult> {
|
fn validate(&self, ctx: &mut rustyline::validate::ValidationContext) -> rustyline::Result<rustyline::validate::ValidationResult> {
|
||||||
return Ok(ValidationResult::Valid(None));
|
|
||||||
let mut tokens = vec![];
|
let mut tokens = vec![];
|
||||||
let tk_stream = LexStream::new(Rc::new(ctx.input().to_string()), LexFlags::empty());
|
let tk_stream = LexStream::new(Rc::new(ctx.input().to_string()), LexFlags::empty());
|
||||||
for tk in tk_stream {
|
for tk in tk_stream {
|
||||||
|
|||||||
@@ -42,3 +42,11 @@ fn lex_multiline() {
|
|||||||
|
|
||||||
insta::assert_debug_snapshot!(tokens)
|
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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -138,3 +138,49 @@ done";
|
|||||||
|
|
||||||
insta::assert_debug_snapshot!(nodes)
|
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)
|
||||||
|
}
|
||||||
|
|||||||
186
src/tests/snapshots/fern__tests__lexer__lex_case.snap
Normal file
186
src/tests/snapshots/fern__tests__lexer__lex_case.snap
Normal file
@@ -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,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -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,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
1211
src/tests/snapshots/fern__tests__parser__parse_case_nested.snap
Normal file
1211
src/tests/snapshots/fern__tests__parser__parse_case_nested.snap
Normal file
File diff suppressed because it is too large
Load Diff
575
src/tests/snapshots/fern__tests__parser__parse_case_simple.snap
Normal file
575
src/tests/snapshots/fern__tests__parser__parse_case_simple.snap
Normal file
@@ -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,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user