Skip to main content

nu_parser/
parse_helpers.rs

1use nu_protocol::{Span, Spanned, ast::*, engine::StateWorkingSet};
2
3pub(crate) const PERCENT_FORCED_BUILTIN_PARSER_INFO: &str = "percent_forced_builtin";
4
5/// three dots b"..."
6pub(crate) const SPREAD_OPERATOR: &[u8; 3] = b"...";
7
8/// three dots "..."
9pub(crate) const SPREAD_OPERATOR_STR: &str = "...";
10
11#[inline]
12fn extract_spread_value(
13    delim: u8,
14    Spanned { item, mut span }: Spanned<&[u8]>,
15) -> Option<Spanned<&[u8]>> {
16    let item = item.strip_prefix(SPREAD_OPERATOR)?;
17    span.start += SPREAD_OPERATOR.len();
18    match item {
19        [b'$' | b'(', ..] => Some(Spanned { item, span }),
20        [head, ..] if *head == delim => Some(Spanned { item, span }),
21        _ => None,
22    }
23}
24
25pub(crate) fn extract_spread_list(spanned: Spanned<&[u8]>) -> Option<Spanned<&[u8]>> {
26    extract_spread_value(b'[', spanned)
27}
28
29pub(crate) fn extract_spread_record(spanned: Spanned<&[u8]>) -> Option<Spanned<&[u8]>> {
30    extract_spread_value(b'{', spanned)
31}
32
33pub fn garbage(working_set: &mut StateWorkingSet, span: Span) -> Expression {
34    Expression::garbage(working_set, span)
35}
36
37pub fn garbage_pipeline(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline {
38    Pipeline::from_vec(vec![garbage(working_set, Span::concat(spans))])
39}
40
41fn is_identifier_byte(b: &u8) -> bool {
42    !b".[({+-*^%/=!<>&|".contains(b)
43}
44
45fn is_identifier(bytes: &[u8]) -> bool {
46    bytes.iter().all(is_identifier_byte)
47}
48
49pub fn is_variable(bytes: &[u8]) -> bool {
50    match bytes {
51        [b'$', var @ ..] | var if !var.is_empty() => is_identifier(var),
52        _ => false,
53    }
54}
55
56#[rustfmt::skip]
57pub fn trim_quotes(bytes: &[u8]) -> &[u8] {
58    match bytes {
59          [b'\'', trimmed @ .., b'\'']
60        | [ b'"', trimmed @ ..,  b'"']
61        | [ b'`', trimmed @ ..,  b'`'] => trimmed,
62        not_trimmed => not_trimmed,
63    }
64}
65
66#[rustfmt::skip]
67pub fn trim_quotes_str(s: &str) -> &str {
68    match s.as_bytes() {
69          [b'\'', .., b'\'']
70        | [ b'"', ..,  b'"']
71        | [ b'`', ..,  b'`'] => &s[1..(s.len() - 1)],
72        _ => s,
73    }
74}