sv_parser_parser/
utils.rs

1use crate::*;
2
3// -----------------------------------------------------------------------------
4
5pub(crate) fn ws<'a, O, F>(
6    mut f: F,
7) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, (O, Vec<WhiteSpace>)>
8where
9    F: FnMut(Span<'a>) -> IResult<Span<'a>, O>,
10{
11    move |s: Span<'a>| {
12        let (s, x) = f(s)?;
13        let (s, y) = many0(white_space)(s)?;
14        Ok((s, (x, y)))
15    }
16}
17
18pub(crate) fn no_ws<'a, O, F>(
19    mut f: F,
20) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, (O, Vec<WhiteSpace>)>
21where
22    F: FnMut(Span<'a>) -> IResult<Span<'a>, O>,
23{
24    move |s: Span<'a>| {
25        let (s, x) = f(s)?;
26        Ok((s, (x, vec![])))
27    }
28}
29
30#[cfg(not(feature = "trace"))]
31pub(crate) fn symbol<'a>(t: &'a str) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Symbol> {
32    move |s: Span<'a>| {
33        let (s, x) = map(ws(map(tag(t), into_locate)), |x| Symbol { nodes: x })(s)?;
34        Ok((s, x))
35    }
36}
37
38#[cfg(feature = "trace")]
39pub(crate) fn symbol<'a>(t: &'a str) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Symbol> {
40    move |s: Span<'a>| {
41        let (depth, s) = nom_tracable::forward_trace(s, &format!("symbol(\"{}\")", t));
42        let body = || {
43            let (s, x) = map(ws(map(tag(t), into_locate)), |x| Symbol { nodes: x })(s)?;
44            Ok((s, x))
45        };
46        let ret = body();
47        nom_tracable::backward_trace(ret, &format!("symbol(\"{}\")", t), depth)
48    }
49}
50
51#[cfg(not(feature = "trace"))]
52pub(crate) fn symbol_exact<'a>(t: &'a str) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Symbol> {
53    move |s: Span<'a>| {
54        let (s, x) = map(no_ws(map(tag(t), into_locate)), |x| Symbol { nodes: x })(s)?;
55        Ok((s, x))
56    }
57}
58
59#[cfg(feature = "trace")]
60pub(crate) fn symbol_exact<'a>(t: &'a str) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Symbol> {
61    move |s: Span<'a>| {
62        let (depth, s) = nom_tracable::forward_trace(s, &format!("symbol(\"{}\")", t));
63        let body = || {
64            let (s, x) = map(no_ws(map(tag(t), into_locate)), |x| Symbol { nodes: x })(s)?;
65            Ok((s, x))
66        };
67        let ret = body();
68        nom_tracable::backward_trace(ret, &format!("symbol(\"{}\")", t), depth)
69    }
70}
71
72#[cfg(not(feature = "trace"))]
73pub(crate) fn keyword<'a>(t: &'a str) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Keyword> {
74    move |s: Span<'a>| {
75        let (s, x) = map(
76            ws(alt((
77                all_consuming(map(tag(t), into_locate)),
78                terminated(map(tag(t), into_locate), peek(none_of(AZ09_))),
79            ))),
80            |x| Keyword { nodes: x },
81        )(s)?;
82        Ok((s, x))
83    }
84}
85
86#[cfg(feature = "trace")]
87pub(crate) fn keyword<'a>(t: &'a str) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Keyword> {
88    move |s: Span<'a>| {
89        let (depth, s) = nom_tracable::forward_trace(s, &format!("keyword(\"{}\")", t));
90        let body = || {
91            let (s, x) = map(
92                ws(alt((
93                    all_consuming(map(tag(t), into_locate)),
94                    terminated(map(tag(t), into_locate), peek(none_of(AZ09_))),
95                ))),
96                |x| Keyword { nodes: x },
97            )(s)?;
98            Ok((s, x))
99        };
100        let ret = body();
101        nom_tracable::backward_trace(ret, &format!("keyword(\"{}\")", t), depth)
102    }
103}
104
105#[cfg(not(feature = "trace"))]
106pub(crate) fn paren<'a, O, F>(mut f: F) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Paren<O>>
107where
108    F: FnMut(Span<'a>) -> IResult<Span<'a>, O>,
109{
110    move |s: Span<'a>| {
111        let (s, a) = symbol("(")(s)?;
112        let (s, b) = f(s)?;
113        let (s, c) = symbol(")")(s)?;
114        Ok((s, Paren { nodes: (a, b, c) }))
115    }
116}
117
118#[cfg(feature = "trace")]
119pub(crate) fn paren<'a, O, F>(mut f: F) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Paren<O>>
120where
121    F: FnMut(Span<'a>) -> IResult<Span<'a>, O>,
122{
123    move |s: Span<'a>| {
124        let (depth, s) = nom_tracable::forward_trace(s, "paren");
125        let mut body = || {
126            let (s, a) = symbol("(")(s)?;
127            let (s, b) = f(s)?;
128            let (s, c) = symbol(")")(s)?;
129            Ok((s, Paren { nodes: (a, b, c) }))
130        };
131        let ret = body();
132        nom_tracable::backward_trace(ret, "paren", depth)
133    }
134}
135
136#[cfg(not(feature = "trace"))]
137pub(crate) fn paren_exact<'a, O, F>(mut f: F) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Paren<O>>
138where
139    F: FnMut(Span<'a>) -> IResult<Span<'a>, O>,
140{
141    move |s: Span<'a>| {
142        let (s, a) = symbol("(")(s)?;
143        let (s, b) = f(s)?;
144        let (s, c) = symbol_exact(")")(s)?;
145        Ok((s, Paren { nodes: (a, b, c) }))
146    }
147}
148
149#[cfg(feature = "trace")]
150pub(crate) fn paren_exact<'a, O, F>(mut f: F) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Paren<O>>
151where
152    F: FnMut(Span<'a>) -> IResult<Span<'a>, O>,
153{
154    move |s: Span<'a>| {
155        let (depth, s) = nom_tracable::forward_trace(s, "paren");
156        let mut body = || {
157            let (s, a) = symbol("(")(s)?;
158            let (s, b) = f(s)?;
159            let (s, c) = symbol_exact(")")(s)?;
160            Ok((s, Paren { nodes: (a, b, c) }))
161        };
162        let ret = body();
163        nom_tracable::backward_trace(ret, "paren", depth)
164    }
165}
166
167#[cfg(not(feature = "trace"))]
168pub(crate) fn bracket<'a, O, F>(mut f: F) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Bracket<O>>
169where
170    F: FnMut(Span<'a>) -> IResult<Span<'a>, O>,
171{
172    move |s: Span<'a>| {
173        let (s, a) = symbol("[")(s)?;
174        let (s, b) = f(s)?;
175        let (s, c) = symbol("]")(s)?;
176        Ok((s, Bracket { nodes: (a, b, c) }))
177    }
178}
179
180#[cfg(feature = "trace")]
181pub(crate) fn bracket<'a, O, F>(mut f: F) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Bracket<O>>
182where
183    F: FnMut(Span<'a>) -> IResult<Span<'a>, O>,
184{
185    move |s: Span<'a>| {
186        let (depth, s) = nom_tracable::forward_trace(s, "bracket");
187        let mut body = || {
188            let (s, a) = symbol("[")(s)?;
189            let (s, b) = f(s)?;
190            let (s, c) = symbol("]")(s)?;
191            Ok((s, Bracket { nodes: (a, b, c) }))
192        };
193        let ret = body();
194        nom_tracable::backward_trace(ret, "bracket", depth)
195    }
196}
197
198#[cfg(not(feature = "trace"))]
199pub(crate) fn brace<'a, O, F>(mut f: F) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Brace<O>>
200where
201    F: FnMut(Span<'a>) -> IResult<Span<'a>, O>,
202{
203    move |s: Span<'a>| {
204        let (s, a) = symbol("{")(s)?;
205        let (s, b) = f(s)?;
206        let (s, c) = symbol("}")(s)?;
207        Ok((s, Brace { nodes: (a, b, c) }))
208    }
209}
210
211#[cfg(feature = "trace")]
212pub(crate) fn brace<'a, O, F>(mut f: F) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, Brace<O>>
213where
214    F: FnMut(Span<'a>) -> IResult<Span<'a>, O>,
215{
216    move |s: Span<'a>| {
217        let (depth, s) = nom_tracable::forward_trace(s, "brace");
218        let mut body = || {
219            let (s, a) = symbol("{")(s)?;
220            let (s, b) = f(s)?;
221            let (s, c) = symbol("}")(s)?;
222            Ok((s, Brace { nodes: (a, b, c) }))
223        };
224        let ret = body();
225        nom_tracable::backward_trace(ret, "brace", depth)
226    }
227}
228
229#[cfg(not(feature = "trace"))]
230pub(crate) fn apostrophe_brace<'a, O, F>(
231    mut f: F,
232) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, ApostropheBrace<O>>
233where
234    F: FnMut(Span<'a>) -> IResult<Span<'a>, O>,
235{
236    move |s: Span<'a>| {
237        let (s, a) = symbol("'{")(s)?;
238        let (s, b) = f(s)?;
239        let (s, c) = symbol("}")(s)?;
240        Ok((s, ApostropheBrace { nodes: (a, b, c) }))
241    }
242}
243
244#[cfg(feature = "trace")]
245pub(crate) fn apostrophe_brace<'a, O, F>(
246    mut f: F,
247) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, ApostropheBrace<O>>
248where
249    F: FnMut(Span<'a>) -> IResult<Span<'a>, O>,
250{
251    move |s: Span<'a>| {
252        let (depth, s) = nom_tracable::forward_trace(s, "apostrophe_brace");
253        let mut body = || {
254            let (s, a) = symbol("'{")(s)?;
255            let (s, b) = f(s)?;
256            let (s, c) = symbol("}")(s)?;
257            Ok((s, ApostropheBrace { nodes: (a, b, c) }))
258        };
259        let ret = body();
260        nom_tracable::backward_trace(ret, "apostrophe_brace", depth)
261    }
262}
263
264pub(crate) fn list<'a, O1, O2, F, G>(
265    mut f: F,
266    mut g: G,
267) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, List<O1, O2>>
268where
269    F: FnMut(Span<'a>) -> IResult<Span<'a>, O1>,
270    G: FnMut(Span<'a>) -> IResult<Span<'a>, O2>,
271{
272    move |s: Span<'a>| {
273        let (s, a) = g(s)?;
274        let mut s = s;
275        let mut ret = Vec::new();
276        while let Ok((t, b)) = f(s) {
277            if let Ok((u, c)) = g(t) {
278                s = u;
279                ret.push((b, c));
280            } else {
281                break;
282            }
283        }
284        Ok((s, List { nodes: (a, ret) }))
285    }
286}
287
288pub(crate) fn triple<'a, O1, O2, O3, F, G, H>(
289    mut f: F,
290    mut g: G,
291    mut h: H,
292) -> impl FnMut(Span<'a>) -> IResult<Span<'a>, (O1, O2, O3)>
293where
294    F: FnMut(Span<'a>) -> IResult<Span<'a>, O1>,
295    G: FnMut(Span<'a>) -> IResult<Span<'a>, O2>,
296    H: FnMut(Span<'a>) -> IResult<Span<'a>, O3>,
297{
298    move |s: Span<'a>| {
299        let (s, x) = f(s)?;
300        let (s, y) = g(s)?;
301        let (s, z) = h(s)?;
302        Ok((s, (x, y, z)))
303    }
304}
305
306// -----------------------------------------------------------------------------
307
308#[tracable_parser]
309#[packrat_parser]
310pub(crate) fn white_space(s: Span) -> IResult<Span, WhiteSpace> {
311    if in_directive() {
312        map(multispace1, |x: Span| {
313            WhiteSpace::Space(Box::new(into_locate(x)))
314        })(s)
315    } else {
316        alt((
317            map(space1, |x: Span| {
318                WhiteSpace::Space(Box::new(into_locate(x)))
319            }),
320            map(multispace1, |x: Span| {
321                WhiteSpace::Newline(Box::new(into_locate(x)))
322            }),
323            map(preceded(peek(char('/')), comment), |x| {
324                WhiteSpace::Comment(Box::new(x))
325            }),
326            map(
327                preceded(peek(char('`')), compiler_directive_without_resetall),
328                |x| WhiteSpace::CompilerDirective(Box::new(x)),
329            ),
330        ))(s)
331    }
332}
333
334thread_local!(
335    static IN_DIRECTIVE: core::cell::RefCell<Vec<()>> = {
336        core::cell::RefCell::new(Vec::new())
337    }
338);
339
340pub(crate) fn in_directive() -> bool {
341    IN_DIRECTIVE.with(|x| x.borrow().last().is_some())
342}
343
344pub(crate) fn begin_directive() {
345    IN_DIRECTIVE.with(|x| x.borrow_mut().push(()));
346}
347
348pub(crate) fn end_directive() {
349    IN_DIRECTIVE.with(|x| x.borrow_mut().pop());
350}
351
352pub(crate) fn clear_directive() {
353    IN_DIRECTIVE.with(|x| x.borrow_mut().clear());
354}
355
356// -----------------------------------------------------------------------------
357
358#[derive(Clone, Copy, Debug)]
359pub(crate) enum Version {
360    Ieee1364_1995,
361    Ieee1364_2001,
362    Ieee1364_2001Noconfig,
363    Ieee1364_2005,
364    Ieee1800_2005,
365    Ieee1800_2009,
366    Ieee1800_2012,
367    Ieee1800_2017,
368    Directive,
369}
370
371thread_local!(
372    static CURRENT_VERSION: core::cell::RefCell<Vec<Version>> = {
373        core::cell::RefCell::new(Vec::new())
374    }
375);
376
377pub(crate) fn begin_keywords(version: &str) {
378    CURRENT_VERSION.with(|current_version| match version {
379        "1364-1995" => current_version.borrow_mut().push(Version::Ieee1364_1995),
380        "1364-2001" => current_version.borrow_mut().push(Version::Ieee1364_2001),
381        "1364-2001-noconfig" => current_version
382            .borrow_mut()
383            .push(Version::Ieee1364_2001Noconfig),
384        "1364-2005" => current_version.borrow_mut().push(Version::Ieee1364_2005),
385        "1800-2005" => current_version.borrow_mut().push(Version::Ieee1800_2005),
386        "1800-2009" => current_version.borrow_mut().push(Version::Ieee1800_2009),
387        "1800-2012" => current_version.borrow_mut().push(Version::Ieee1800_2012),
388        "1800-2017" => current_version.borrow_mut().push(Version::Ieee1800_2017),
389        "directive" => current_version.borrow_mut().push(Version::Directive),
390        _ => (),
391    });
392}
393
394pub(crate) fn end_keywords() {
395    CURRENT_VERSION.with(|current_version| {
396        current_version.borrow_mut().pop();
397    });
398}
399
400pub(crate) fn current_version() -> Option<Version> {
401    CURRENT_VERSION.with(|current_version| match current_version.borrow().last() {
402        Some(x) => Some(*x),
403        None => None,
404    })
405}
406
407pub(crate) fn clear_version() {
408    CURRENT_VERSION.with(|current_version| {
409        current_version.borrow_mut().clear();
410    });
411}
412
413// -----------------------------------------------------------------------------
414
415pub(crate) fn concat<'a>(a: Span<'a>, b: Span<'a>) -> Option<Span<'a>> {
416    let c = unsafe { str_concat::concat(a.fragment(), b.fragment()) };
417    if let Ok(c) = c {
418        let ret = unsafe {
419            Span::new_from_raw_offset(a.location_offset(), a.location_line(), c, a.extra)
420        };
421        Some(ret)
422    } else {
423        None
424    }
425}
426
427pub(crate) fn is_keyword(s: &Span) -> bool {
428    let keywords = match current_version() {
429        Some(Version::Ieee1364_1995) => KEYWORDS_1364_1995,
430        Some(Version::Ieee1364_2001) => KEYWORDS_1364_2001,
431        Some(Version::Ieee1364_2001Noconfig) => KEYWORDS_1364_2001_NOCONFIG,
432        Some(Version::Ieee1364_2005) => KEYWORDS_1364_2005,
433        Some(Version::Ieee1800_2005) => KEYWORDS_1800_2005,
434        Some(Version::Ieee1800_2009) => KEYWORDS_1800_2009,
435        Some(Version::Ieee1800_2012) => KEYWORDS_1800_2012,
436        Some(Version::Ieee1800_2017) => KEYWORDS_1800_2017,
437        Some(Version::Directive) => KEYWORDS_DIRECTIVE,
438        None => KEYWORDS_1800_2017,
439    };
440    for k in keywords {
441        if s.fragment() == k {
442            return true;
443        }
444    }
445    false
446}
447
448pub(crate) fn into_locate(s: Span) -> Locate {
449    Locate {
450        offset: s.location_offset(),
451        line: s.location_line(),
452        len: s.fragment().len(),
453    }
454}