1#![doc = include_str!("../examples/basic.rs")]
7mod children;
10mod error;
11
12pub use nom::combinator::map;
13
14pub use children::Children;
15pub use error::*;
16use nom::Parser;
17use rowan::SyntaxNode;
18
19pub trait RowanNomLanguage: rowan::Language {
20 fn is_trivia(_kind: Self::Kind) -> bool {
22 false
23 }
24
25 fn get_error_kind() -> Self::Kind;
26}
27
28use RowanNomLanguage as Language;
30
31type RichToken<'src, Lang> = (<Lang as rowan::Language>::Kind, &'src str);
32
33pub struct Input<'slice, 'src, Lang: Language> {
37 src_pos: usize,
38 trivia_tokens: &'slice [RichToken<'src, Lang>],
39 trivia_tokens_text_len: usize,
40 tokens: &'slice [RichToken<'src, Lang>],
41}
42
43fn split_slice_predicate<T>(slice: &[T], predicate: impl FnMut(&T) -> bool) -> (&[T], &[T]) {
44 let non_trivia_idx = slice.iter().position(predicate).unwrap_or(slice.len());
45
46 slice.split_at(non_trivia_idx)
47}
48
49impl<'slice, 'src, Lang: Language> Input<'slice, 'src, Lang> {
50 pub fn src_pos(&self) -> usize {
51 self.src_pos
52 }
53
54 fn next(
55 &self,
56 ) -> Option<(
57 Self,
58 (
59 &'slice [RichToken<'src, Lang>],
60 &'slice RichToken<'src, Lang>,
61 ),
62 )> {
63 match self.tokens {
64 [] => None,
65 [first, rest @ ..] => {
66 let relevant_tokens = (self.trivia_tokens, first);
67
68 let input = Input {
69 src_pos: self.src_pos + self.trivia_tokens_text_len + first.1.len(),
70 trivia_tokens: &[],
71 trivia_tokens_text_len: 0,
72 tokens: rest,
73 }
74 .advance_trivia();
75
76 Some((input, relevant_tokens))
77 }
78 }
79 }
80
81 fn next_trivia(&self) -> Option<(Self, &'slice RichToken<'src, Lang>)> {
82 if let [token, rest @ ..] = self.trivia_tokens {
83 let token_len = token.1.len();
84
85 Some((
86 Input {
87 src_pos: self.src_pos + token_len,
88 trivia_tokens: rest,
89 trivia_tokens_text_len: self.trivia_tokens_text_len - token_len,
90 tokens: self.tokens,
91 },
92 token,
93 ))
94 } else {
95 None
96 }
97 }
98
99 fn next_raw(&mut self) {
100 if let Some(trivia) = self.trivia_tokens.first() {
101 let text_len = trivia.1.len();
102 self.src_pos += text_len;
103 self.trivia_tokens_text_len -= text_len;
104 self.trivia_tokens = &self.trivia_tokens[1..];
105 } else if let Some(token) = self.tokens.first() {
106 self.src_pos += token.1.len();
107 self.tokens = &self.tokens[1..];
108 } else {
109 panic!("empty input");
110 }
111 }
112
113 fn advance_trivia(self) -> Self {
114 let (trivia_tokens, rest_tokens) =
115 split_slice_predicate(self.tokens, |(t, _)| !Lang::is_trivia(*t));
116
117 let trivia_tokens_text_len = trivia_tokens.iter().map(|(_, s)| s.len()).sum();
118
119 Self {
120 src_pos: self.src_pos,
121 trivia_tokens,
122 trivia_tokens_text_len,
123 tokens: rest_tokens,
124 }
125 }
126}
127
128impl<'slice, 'src, Lang: Language> Clone for Input<'slice, 'src, Lang> {
129 fn clone(&self) -> Self {
130 Self {
131 src_pos: self.src_pos,
132 trivia_tokens: self.trivia_tokens,
133 trivia_tokens_text_len: self.trivia_tokens_text_len,
134 tokens: self.tokens,
135 }
136 }
137}
138
139impl<'slice, 'src, Lang: Language> From<&'slice [RichToken<'src, Lang>]>
140 for Input<'slice, 'src, Lang>
141{
142 fn from(tokens: &'slice [RichToken<'src, Lang>]) -> Self {
143 Self {
144 src_pos: 0,
145 trivia_tokens: &[],
146 trivia_tokens_text_len: 0,
147 tokens,
148 }
149 .advance_trivia()
150 }
151}
152
153pub type IResult<'slice, 'src, Lang, E, IE = E> =
154 nom::IResult<Input<'slice, 'src, Lang>, Children<Lang, E>, IE>;
155pub type RootIResult<'slice, 'src, Lang, E, IE = E> =
156 nom::IResult<Input<'slice, 'src, Lang>, (SyntaxNode<Lang>, Vec<E>), IE>;
157
158pub fn success<'slice, 'src: 'slice, Lang: Language, E, IE>(
162 input: Input<'slice, 'src, Lang>,
163) -> IResult<'slice, 'src, Lang, E, IE> {
164 Ok((input, Children::empty()))
165}
166
167pub fn eof<'slice, 'src: 'slice, Lang: Language, E, IE: RowanNomError<Lang>>(
170 input: Input<'slice, 'src, Lang>,
171) -> IResult<'slice, 'src, Lang, E, IE> {
172 if let Some((_, (_trivia, unexpected_token))) = input.next() {
173 let start = input.src_pos;
174 let range = start..start + unexpected_token.1.len();
175 Err(nom::Err::Error(IE::from_expected_eof(range)))
176 } else {
177 let trivia_tokens = input.trivia_tokens.iter();
178
179 let input = Input {
180 src_pos: input.src_pos + input.trivia_tokens_text_len,
181 trivia_tokens: &[],
182 trivia_tokens_text_len: 0,
183 tokens: &[],
184 };
185
186 Ok((input, trivia_tokens.collect()))
187 }
188}
189
190pub fn t_any<'slice, 'src: 'slice, Lang: Language, E, IE: RowanNomError<Lang>>(
192 input: Input<'slice, 'src, Lang>,
193) -> IResult<'slice, 'src, Lang, E, IE> {
194 if let Some((new_input, (trivia, current_token))) = input.next() {
195 Ok((
196 new_input,
197 trivia
198 .iter()
199 .chain(std::iter::once(current_token))
200 .collect(),
201 ))
202 } else {
203 Err(nom::Err::Error(IE::from_unexpected_eof(input.src_pos)))
204 }
205}
206
207pub fn t<'slice, 'src: 'slice, Lang: Language, E, IE: RowanNomError<Lang>>(
211 token: Lang::Kind,
212) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE> + Clone + Copy {
213 debug_assert!(
214 !Lang::is_trivia(token),
215 "this parser will always fail with trivia tokens, please use `t_raw`"
216 );
217
218 move |input| {
219 let input_src_pos = input.src_pos;
220
221 if let Some((new_input, (trivia, current_token))) = input.next() {
222 if current_token.0 == token {
223 Ok((
224 new_input,
225 trivia
226 .iter()
227 .chain(std::iter::once(current_token))
228 .collect(),
229 ))
230 } else {
231 let range = input_src_pos..input_src_pos + current_token.1.len();
232 Err(nom::Err::Error(IE::from_unexpected_token(
233 range,
234 token,
235 current_token.0,
236 )))
237 }
238 } else {
239 Err(nom::Err::Error(IE::from_unexpected_eof(input.src_pos)))
240 }
241 }
242}
243
244pub fn t_raw<'slice, 'src: 'slice, Lang: Language, E, IE: RowanNomError<Lang>>(
250 token: Lang::Kind,
251) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE> + Clone + Copy {
252 let is_trivia = Lang::is_trivia(token);
253
254 move |input| {
255 let input_src_pos = input.src_pos;
256
257 if is_trivia {
258 if let Some((new_input, current_token)) = input.next_trivia() {
259 if current_token.0 == token {
260 Ok((new_input, std::iter::once(current_token).collect()))
261 } else {
262 let range = input_src_pos..input_src_pos + current_token.1.len();
263 Err(nom::Err::Error(IE::from_unexpected_token(
264 range,
265 token,
266 current_token.0,
267 )))
268 }
269 } else {
270 Err(nom::Err::Error(IE::from_unexpected_eof(input_src_pos)))
271 }
272 } else {
273 t(token)(input)
274 }
275 }
276}
277
278pub fn peek<'slice, 'src: 'slice, Lang: Language, E, IE>(
284 mut parser: impl Parser<Input<'slice, 'src, Lang>, Children<Lang, E>, IE>,
285) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE>
286where
287 Lang::Kind: 'static,
288{
289 move |input| {
290 let (_, _) = parser.parse(input.clone())?;
291 Ok((input, Children::empty()))
292 }
293}
294
295pub fn peek_neg<'slice, 'src: 'slice, Lang: Language, E, IE: RowanNomError<Lang>>(
300 mut parser: impl Parser<Input<'slice, 'src, Lang>, Children<Lang, E>, IE>,
301) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE>
302where
303 Lang::Kind: 'static,
304{
305 move |input| match parser.parse(input.clone()) {
306 Ok(_) => Err(nom::Err::Error(IE::from_message("neg_peek"))),
307 Err(_) => Ok((input, Children::empty())),
308 }
309}
310
311pub fn fallible_with<'slice, 'src: 'slice, Lang: Language, E, IE>(
312 mut parser: impl Parser<Input<'slice, 'src, Lang>, Children<Lang, E>, IE>,
313 mut convert: impl FnMut(IE) -> E,
314) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE>
315where
316 Lang::Kind: 'static,
317{
318 move |input| {
319 let conv = &mut convert;
320 parser.parse(input.clone()).or_else(move |e| match e {
321 nom::Err::Error(e) => Ok((input, Children::from_err(conv(e)))),
322 other => Err(other),
323 })
324 }
325}
326
327pub fn expect<'slice, 'src: 'slice, Lang: Language, E: RowanNomError<Lang>>(
332 mut parser: impl Parser<Input<'slice, 'src, Lang>, Children<Lang, E>, E>,
333 message: &'static str,
334) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, E>
335where
336 Lang::Kind: 'static,
337{
338 move |input| {
339 let src_pos = input.src_pos;
340 parser.parse(input.clone()).or_else(move |e| match e {
341 nom::Err::Error(_) => Ok((
342 input,
343 Children::from_err(E::from_expected(src_pos, message)),
344 )),
345 other => Err(other),
346 })
347 }
348}
349
350pub fn fallible<'slice, 'src: 'slice, Lang: Language, E, IE>(
351 parser: impl Parser<Input<'slice, 'src, Lang>, Children<Lang, E>, IE>,
352) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE>
353where
354 Lang::Kind: 'static,
355 E: From<IE>,
356{
357 fallible_with(parser, Into::into)
358}
359
360pub fn node<'slice, 'src: 'slice, Lang: Language, E, IE>(
362 node: Lang::Kind,
363 mut parser: impl Parser<Input<'slice, 'src, Lang>, Children<Lang, E>, IE>,
364) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE>
365where
366 Lang::Kind: 'static,
367{
368 move |input| {
369 parser
370 .parse(input)
371 .map(|(input, c)| (input, c.into_node(node)))
372 }
373}
374
375pub fn root_node<'slice, 'src: 'slice, Lang: Language, E, IE>(
377 node: Lang::Kind,
378 mut parser: impl Parser<Input<'slice, 'src, Lang>, Children<Lang, E>, IE>,
379) -> impl FnMut(Input<'slice, 'src, Lang>) -> RootIResult<'slice, 'src, Lang, E, IE>
380where
381 Lang::Kind: 'static,
382{
383 move |input| {
384 parser
385 .parse(input)
386 .map(|(input, c)| (input, c.into_root_node(node)))
387 }
388}
389
390pub trait Joignable<'slice, 'src, Lang: Language, E, IE> {
391 fn parse(&mut self, input: Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE>;
392}
393
394macro_rules! impl_joignable {
395 ($arg0:ident, $($arg:ident),*) => {
396 #[allow(unused_parens)]
397 impl<'slice, 'src: 'slice, Lang: Language, CE, IE, $arg0, $($arg),*> Joignable<'slice, 'src, Lang, CE, IE> for ($arg0, $($arg,)*)
398 where
399 Lang::Kind: 'static,
400 $arg0: Parser<Input<'slice, 'src, Lang>, Children<Lang, CE>, IE>,
401 $($arg: Parser<Input<'slice, 'src, Lang>, Children<Lang, CE>, IE>),*
402 {
403 fn parse(&mut self, input: Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, CE, IE> {
404 #[allow(non_snake_case)]
405 let ($arg0, $($arg),*) = self;
406
407 #[allow(unused_mut)]
408 let (input, mut children) = $arg0.parse(input)?;
409 $(let (input, children2) = $arg.parse(input)?; children += children2;)*
410
411 Ok((input, children))
412 }
413 }
414 };
415}
416
417impl_joignable!(A,);
418impl_joignable!(A, B);
419impl_joignable!(A, B, C);
420impl_joignable!(A, B, C, D);
421impl_joignable!(A, B, C, D, E);
422impl_joignable!(A, B, C, D, E, F);
423impl_joignable!(A, B, C, D, E, F, G);
424impl_joignable!(A, B, C, D, E, F, G, H);
425impl_joignable!(A, B, C, D, E, F, G, H, I);
426impl_joignable!(A, B, C, D, E, F, G, H, I, J);
427impl_joignable!(A, B, C, D, E, F, G, H, I, J, K);
428impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L);
429impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M);
430impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
431impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
432impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
433impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
434impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
435impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
436impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
437impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
438impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
439impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W);
440impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X);
441impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y);
442impl_joignable!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
443
444pub fn join<'slice, 'src: 'slice, Lang: Language, E, IE>(
446 mut parsers: impl Joignable<'slice, 'src, Lang, E, IE>,
447) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE> {
448 move |input| parsers.parse(input)
449}
450
451pub fn opt<'slice, 'src: 'slice, Lang: Language, E, IE>(
455 mut parser: impl Parser<Input<'slice, 'src, Lang>, Children<Lang, E>, IE>,
456) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE>
457where
458 Lang::Kind: 'static,
459{
460 move |input| match parser.parse(input.clone()) {
461 Ok(ok) => Ok(ok),
462 Err(nom::Err::Error(_)) => Ok((input, Children::empty())),
463 Err(e) => Err(e),
464 }
465}
466
467pub trait Alt<I, O, E> {
468 fn parse(&mut self, input: I) -> nom::IResult<I, O, E>;
469}
470
471macro_rules! impl_alt {
472 ($arg0:ident, $($arg:ident),*) => {
473 #[allow(unused_parens)]
474 impl<II: Clone, OO, EE, $arg0, $($arg),*> Alt<II, OO, EE> for ($arg0, $($arg,)*)
475 where
476 $arg0: Parser<II, OO, EE>,
477 $($arg: Parser<II, OO, EE>),*
478 {
479 fn parse(&mut self, input: II) -> nom::IResult<II, OO, EE> {
480 #[allow(non_snake_case)]
481 let ($arg0, $($arg),*) = self;
482
483 $arg0.parse(input.clone())
484 $(.or_else(|_| $arg.parse(input.clone())))*
485 }
486 }
487 };
488}
489
490impl_alt!(A,);
491impl_alt!(A, B);
492impl_alt!(A, B, C);
493impl_alt!(A, B, C, D);
494impl_alt!(A, B, C, D, E);
495impl_alt!(A, B, C, D, E, F);
496impl_alt!(A, B, C, D, E, F, G);
497impl_alt!(A, B, C, D, E, F, G, H);
498impl_alt!(A, B, C, D, E, F, G, H, I);
499impl_alt!(A, B, C, D, E, F, G, H, I, J);
500impl_alt!(A, B, C, D, E, F, G, H, I, J, K);
501impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L);
502impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M);
503impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
504impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
505impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
506impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
507impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
508impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
509impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
510impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
511impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
512impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W);
513impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X);
514impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y);
515impl_alt!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
516
517pub fn alt<I, O, E>(mut parsers: impl Alt<I, O, E>) -> impl FnMut(I) -> nom::IResult<I, O, E> {
521 move |input| parsers.parse(input)
522}
523
524pub fn many0<'slice, 'src: 'slice, Lang: Language, E, IE>(
527 mut parser: impl Parser<Input<'slice, 'src, Lang>, Children<Lang, E>, E>,
528) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE>
529where
530 Lang::Kind: 'static,
531{
532 move |input| {
533 let (mut input, mut first) = match parser.parse(input.clone()) {
534 Ok(x) => x,
535 Err(_) => return Ok((input, Children::empty())),
536 };
537
538 while let Ok((new_input, new_children)) = parser.parse(input.clone()) {
539 input = new_input;
540 first += new_children;
541 }
542
543 Ok((input, first))
544 }
545}
546
547pub fn fold_many1<'slice, 'src: 'slice, Lang: Language, C, E, IE>(
551 mut init: impl Parser<Input<'slice, 'src, Lang>, Children<Lang, E>, IE>,
552 mut then: impl Parser<Input<'slice, 'src, Lang>, C, IE>,
553 mut merge: impl FnMut(Children<Lang, E>, C) -> Children<Lang, E>,
554) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE>
555where
556 Lang::Kind: 'static,
557{
558 move |input| {
559 let (mut input, mut children) = init.parse(input)?;
560
561 while let Ok((new_input, new_children)) = then.parse(input.clone()) {
562 input = new_input;
563 children = merge(children, new_children);
564 }
565
566 Ok((input, children))
567 }
568}
569
570pub fn fold_many1_right<'slice, 'src: 'slice, Lang: Language, C, E, IE: RowanNomError<Lang>>(
574 mut cont: impl Parser<Input<'slice, 'src, Lang>, C, IE>,
575 mut end: impl Parser<Input<'slice, 'src, Lang>, Children<Lang, E>, IE>,
576 mut merge: impl FnMut(Children<Lang, E>, C) -> Children<Lang, E>,
577) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE>
578where
579 Lang::Kind: 'static,
580{
581 move |mut input| {
582 let mut stack = Vec::new();
583
584 loop {
585 if let Ok((new_input, new_children)) = cont.parse(input.clone()) {
586 input = new_input;
587 stack.push(new_children);
588 } else if let Ok((input, new_children)) = end.parse(input) {
589 let children = stack.into_iter().rfold(new_children, |a, b| merge(a, b));
590 break Ok((input, children));
591 } else {
592 break Err(nom::Err::Error(IE::from_message("couldn't finish fold")));
593 }
594 }
595 }
596}
597
598pub fn fold_many1_right_expr<'slice, 'src: 'slice, Lang: Language, C, E, IE: RowanNomError<Lang>>(
602 mut atom: impl Parser<Input<'slice, 'src, Lang>, Children<Lang, E>, IE>,
603 mut operator: impl Parser<Input<'slice, 'src, Lang>, (Children<Lang, E>, C), IE>,
604 mut merge: impl FnMut(Children<Lang, E>, (Children<Lang, E>, C)) -> Children<Lang, E>,
605) -> impl FnMut(Input<'slice, 'src, Lang>) -> IResult<'slice, 'src, Lang, E, IE>
606where
607 Lang::Kind: 'static,
608{
609 move |mut input| {
610 let mut stack = Vec::new();
611
612 loop {
613 if let Ok((new_input, children)) = atom.parse(input.clone()) {
614 if let Ok((new_input, (new_children, c))) = operator.parse(new_input.clone()) {
615 input = new_input;
616 stack.push((children + new_children, c));
617 } else {
618 let children = stack.into_iter().rfold(children, |a, b| merge(a, b));
619 break Ok((new_input, children));
620 }
621 } else {
622 break Err(nom::Err::Error(IE::from_message("couldn't finish fold")));
623 }
624 }
625 }
626}