csml_interpreter/parser/
tools.rs

1use crate::data::{ast::*, tokens::*};
2use nom::{
3    bytes::complete::take_while1,
4    error::{ContextError, ErrorKind, ParseError},
5    *,
6};
7
8////////////////////////////////////////////////////////////////////////////////
9// PRIVATE FUNCTION
10////////////////////////////////////////////////////////////////////////////////
11
12fn position<'a, E: ParseError<Span<'a>> + ContextError<Span<'a>>, T>(s: T) -> IResult<T, T, E>
13where
14    T: InputIter + InputTake,
15    E: nom::error::ParseError<T>,
16{
17    nom::bytes::complete::take(0usize)(s)
18}
19
20fn set_escape(s: &str, index: usize, escape: &mut bool) {
21    if let Some(c) = s.chars().nth(index) {
22        if c == '\\' {
23            return match escape {
24                true => {
25                    *escape = false;
26                }
27                false => {
28                    *escape = true;
29                }
30            };
31        }
32
33        *escape = false;
34    }
35}
36
37fn set_substring(s: &str, index: usize, escape: bool, expand: bool, substring: &mut bool) {
38    if let Some(c) = s.chars().nth(index) {
39        if c == '"' && escape && expand {
40            match substring {
41                true => {
42                    *substring = false;
43                }
44                false => {
45                    *substring = true;
46                }
47            }
48        }
49    }
50}
51
52fn set_open_expand(s: &str, index: usize, escape: bool, substring: bool, expand: &mut bool) {
53    if let Some(c) = s.chars().nth(index) {
54        if c == '{' && !escape && !substring {
55            if let Some(c) = s.chars().nth(index + 1) {
56                if c == '{' && !escape {
57                    *expand = true;
58                }
59            }
60        }
61    }
62}
63
64fn set_close_expand(s: &str, index: usize, escape: bool, substring: bool, expand: &mut bool) {
65    if let Some(c) = s.chars().nth(index) {
66        if c == '}' && !escape && !substring {
67            if let Some(c) = s.chars().nth(index + 1) {
68                if c == '}' && !escape {
69                    *expand = false;
70                }
71            }
72        }
73    }
74}
75
76////////////////////////////////////////////////////////////////////////////////
77// PUBLIC FUNCTIONS
78////////////////////////////////////////////////////////////////////////////////
79
80pub fn get_interval<'a, E>(s: Span<'a>) -> IResult<Span<'a>, Interval, E>
81where
82    E: ParseError<Span<'a>> + ContextError<Span<'a>>,
83{
84    let (s, pos) = position(s)?;
85    Ok((s, Interval::new_as_span(pos)))
86}
87
88pub fn get_range_interval(vector_interval: &[Interval]) -> Interval {
89    let mut start = Interval::new_as_u32(0, 0, 0, None, None);
90    let mut end = Interval::new_as_u32(0, 0, 0, None, None);
91
92    for (index, interval) in vector_interval.iter().enumerate() {
93        if index == 0 {
94            start = *interval;
95        }
96
97        end = *interval;
98    }
99
100    start.add_end(end);
101    start
102}
103
104// generate range error
105pub fn parse_error<'a, O, E, F>(
106    start: Span<'a>,
107    span: Span<'a>,
108    mut func: F,
109) -> IResult<Span<'a>, O, E>
110where
111    E: ParseError<Span<'a>> + ContextError<Span<'a>>,
112    F: FnMut(Span<'a>) -> IResult<Span<'a>, O, E>,
113{
114    match func(span) {
115        Ok(value) => Ok(value),
116        Err(Err::Error(e)) => Err(Err::Error(e)),
117        Err(Err::Failure(e)) => Err(Err::Failure(E::append(start, ErrorKind::Tag, e))),
118        Err(Err::Incomplete(needed)) => Err(Err::Incomplete(needed)),
119    }
120}
121
122pub fn get_string<'a, E>(s: Span<'a>) -> IResult<Span<'a>, String, E>
123where
124    E: ParseError<Span<'a>> + ContextError<Span<'a>>,
125{
126    let (rest, string) =
127        take_while1(|c: char| c == '-' || c == '_' || c == '\\' || c.is_alphanumeric())(s)?;
128
129    Ok((rest, (*string.fragment()).to_string()))
130}
131
132pub fn get_tag<I, E: ParseError<I>>(
133    var: String,
134    tag: &str,
135) -> impl FnMut(I) -> IResult<I, (), E> + '_ {
136    move |input: I| {
137        if var == tag {
138            Ok((input, ()))
139        } else {
140            Err(Err::Error(E::from_error_kind(input, ErrorKind::Tag)))
141        }
142    }
143}
144
145pub fn get_distance_brace(s: &Span, key: char) -> Option<usize> {
146    let mut escape: bool = false;
147    let mut expand: bool = false;
148    let mut substring: bool = false;
149    let mut distance = 0;
150
151    for (i, c) in s.chars().enumerate() {
152        if c == key && !escape && !substring {
153            if let Some(c) = s.chars().nth(i + 1) {
154                if c == key {
155                    return Some(distance);
156                }
157            }
158        }
159
160        distance += c.len_utf8();
161
162        set_open_expand(s.fragment(), i, escape, substring, &mut expand);
163        set_close_expand(s.fragment(), i, escape, substring, &mut expand);
164        set_substring(s.fragment(), i, escape, expand, &mut substring);
165        set_escape(s.fragment(), i, &mut escape);
166    }
167
168    None
169}