1use crate::*;
2
3pub(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#[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#[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
413pub(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}