use super::*;
impl<'a> Parser<'a> {
pub(super) fn scan_shell_path_like_bareword_end(
&mut self,
start_index: usize,
) -> Option<usize> {
if !matches!(
self.token_at(start_index).kind,
TokenKind::Ident | TokenKind::Pipe | TokenKind::Star | TokenKind::Colon
) {
return None;
}
let mut end_index = start_index;
let mut index = start_index + 1;
let mut expecting_segment_start = false;
match self.token_at(start_index).kind {
TokenKind::Pipe | TokenKind::Colon => {
end_index = start_index;
expecting_segment_start = true;
}
TokenKind::Ident | TokenKind::Star => {
while matches!(
self.kind_at(index),
Some(TokenKind::Ident | TokenKind::Star)
) && self.tokens_are_adjacent(end_index, index)
{
end_index = index;
index += 1;
}
while matches!(
(self.kind_at(index), self.kind_at(index + 1)),
(
Some(TokenKind::Colon),
Some(TokenKind::Ident | TokenKind::Star)
)
) && self.tokens_are_adjacent(end_index, index)
&& self.tokens_are_adjacent(index, index + 1)
{
end_index = index + 1;
index += 2;
while matches!(
self.kind_at(index),
Some(TokenKind::Ident | TokenKind::Star)
) && self.tokens_are_adjacent(end_index, index)
{
end_index = index;
index += 1;
}
}
}
_ => return None,
}
loop {
if expecting_segment_start {
let mut consumed_atom = false;
while matches!(
self.kind_at(index),
Some(TokenKind::Ident | TokenKind::Star)
) && self.tokens_are_adjacent(end_index, index)
{
end_index = index;
index += 1;
consumed_atom = true;
}
if !consumed_atom {
return None;
}
while matches!(
(self.kind_at(index), self.kind_at(index + 1)),
(
Some(TokenKind::Colon),
Some(TokenKind::Ident | TokenKind::Star)
)
) && self.tokens_are_adjacent(end_index, index)
&& self.tokens_are_adjacent(index, index + 1)
{
end_index = index + 1;
index += 2;
while matches!(
self.kind_at(index),
Some(TokenKind::Ident | TokenKind::Star)
) && self.tokens_are_adjacent(end_index, index)
{
end_index = index;
index += 1;
}
}
expecting_segment_start = false;
continue;
}
if matches!(self.kind_at(index), Some(TokenKind::Pipe))
&& self.tokens_are_adjacent(end_index, index)
{
end_index = index;
index += 1;
expecting_segment_start = true;
continue;
}
if matches!(
(self.kind_at(index), self.kind_at(index + 1)),
(Some(TokenKind::Dot), Some(TokenKind::Ident))
) && self.tokens_are_adjacent(end_index, index)
&& self.tokens_are_adjacent(index, index + 1)
{
end_index = index + 1;
index += 2;
continue;
}
if self.tokens_are_adjacent(end_index, index)
&& let Some(suffix_end) = self.bareword_bracket_suffix_end(index)
{
end_index = suffix_end;
index = suffix_end + 1;
continue;
}
while matches!(
self.kind_at(index),
Some(TokenKind::Ident | TokenKind::Star)
) && self.tokens_are_adjacent(end_index, index)
{
end_index = index;
index += 1;
}
break;
}
if expecting_segment_start {
return None;
}
Some(end_index)
}
pub(super) fn scan_path_like_bareword_end(&mut self, start_index: usize) -> Option<usize> {
if !matches!(
self.token_at(start_index).kind,
TokenKind::Ident | TokenKind::Pipe | TokenKind::Star | TokenKind::Colon
) {
return None;
}
let mut end_index = start_index;
let mut index = start_index + 1;
let mut expecting_segment_start = false;
match self.token_at(start_index).kind {
TokenKind::Pipe | TokenKind::Colon => {
end_index = start_index;
expecting_segment_start = true;
}
TokenKind::Ident | TokenKind::Star => {
while matches!(
self.kind_at(index),
Some(TokenKind::Ident | TokenKind::Star)
) && self.tokens_are_adjacent(end_index, index)
{
end_index = index;
index += 1;
}
while matches!(
(self.kind_at(index), self.kind_at(index + 1)),
(
Some(TokenKind::Colon),
Some(TokenKind::Ident | TokenKind::Star)
)
) && self.tokens_are_adjacent(end_index, index)
&& self.tokens_are_adjacent(index, index + 1)
{
end_index = index + 1;
index += 2;
while matches!(
self.kind_at(index),
Some(TokenKind::Ident | TokenKind::Star)
) && self.tokens_are_adjacent(end_index, index)
{
end_index = index;
index += 1;
}
}
}
_ => return None,
}
loop {
if expecting_segment_start {
let mut consumed_atom = false;
while matches!(
self.kind_at(index),
Some(TokenKind::Ident | TokenKind::Star)
) && self.tokens_are_adjacent(end_index, index)
{
end_index = index;
index += 1;
consumed_atom = true;
}
if !consumed_atom {
return (self.token_at(end_index).kind == TokenKind::Pipe).then_some(end_index);
}
while matches!(
(self.kind_at(index), self.kind_at(index + 1)),
(
Some(TokenKind::Colon),
Some(TokenKind::Ident | TokenKind::Star)
)
) && self.tokens_are_adjacent(end_index, index)
&& self.tokens_are_adjacent(index, index + 1)
{
end_index = index + 1;
index += 2;
while matches!(
self.kind_at(index),
Some(TokenKind::Ident | TokenKind::Star)
) && self.tokens_are_adjacent(end_index, index)
{
end_index = index;
index += 1;
}
}
expecting_segment_start = false;
continue;
}
if matches!(self.kind_at(index), Some(TokenKind::Pipe))
&& self.tokens_are_adjacent(end_index, index)
{
end_index = index;
index += 1;
expecting_segment_start = true;
continue;
}
if matches!(
(self.kind_at(index), self.kind_at(index + 1)),
(Some(TokenKind::Dot), Some(TokenKind::Ident))
) && self.tokens_are_adjacent(end_index, index)
&& self.tokens_are_adjacent(index, index + 1)
{
end_index = index + 1;
index += 2;
continue;
}
if self.tokens_are_adjacent(end_index, index)
&& let Some(suffix_end) = self.bareword_bracket_suffix_end(index)
{
end_index = suffix_end;
index = suffix_end + 1;
continue;
}
while matches!(
self.kind_at(index),
Some(TokenKind::Ident | TokenKind::Star)
) && self.tokens_are_adjacent(end_index, index)
{
end_index = index;
index += 1;
}
break;
}
if expecting_segment_start {
return None;
}
Some(end_index)
}
pub(super) fn bareword_bracket_suffix_end(&mut self, start_index: usize) -> Option<usize> {
if self.token_at(start_index).kind != TokenKind::LBracket {
return None;
}
match (
self.kind_at(start_index + 1),
self.kind_at(start_index + 2),
self.kind_at(start_index + 3),
) {
(Some(TokenKind::IntLiteral), Some(TokenKind::RBracket), _) => Some(start_index + 2),
(Some(TokenKind::Dollar), Some(TokenKind::Ident), Some(TokenKind::RBracket)) => {
Some(start_index + 3)
}
_ => None,
}
}
}