1use crate::core::context::ParserContext;
2use crate::core::parser::Parser;
3use crate::core::pos::Pos;
4use crate::core::presult::PResult;
5use crate::core::presult::PResult::{PErr, POk};
6use crate::core::span::Span;
7use crate::core::state::ParserState;
8use crate::error::error_printer::ErrorLabel;
9use crate::error::error_printer::ErrorLabel::Debug;
10use crate::error::ParseError;
11
12#[inline(always)]
13pub fn single<'arn, 'grm: 'arn, E: ParseError>(
14 f: impl Fn(&char) -> bool,
15) -> impl Parser<'arn, 'grm, (Span, char), E> {
16 move |pos: Pos,
17 state: &mut ParserState<'arn, 'grm, E>,
18 _: ParserContext|
19 -> PResult<(Span, char), E> {
20 match pos.next(state.input) {
21 (pos_new, Some((span, e))) if f(&e) => PResult::new_ok((span, e), pos, pos_new),
23 (pos_new, _) => PResult::new_err(E::new(pos.span_to(pos_new)), pos),
25 }
26 }
27}
28
29#[inline(always)]
30pub fn seq2<'arn, 'grm: 'arn, 'a, O1, O2, E: ParseError>(
31 p1: &'a impl Parser<'arn, 'grm, O1, E>,
32 p2: &'a impl Parser<'arn, 'grm, O2, E>,
33) -> impl Parser<'arn, 'grm, (O1, O2), E> + 'a {
34 move |pos: Pos,
35 state: &mut ParserState<'arn, 'grm, E>,
36 context: ParserContext|
37 -> PResult<(O1, O2), E> {
38 let res1 = p1.parse(pos, state, context);
39 let end_pos = res1.end_pos();
40 res1.merge_seq(p2.parse(end_pos, state, context))
41 }
42}
43
44#[inline(always)]
45pub fn choice2<'arn, 'grm: 'arn, 'a, O, E: ParseError>(
46 p1: &'a impl Parser<'arn, 'grm, O, E>,
47 p2: &'a impl Parser<'arn, 'grm, O, E>,
48) -> impl Parser<'arn, 'grm, O, E> + 'a {
49 move |pos: Pos,
50 state: &mut ParserState<'arn, 'grm, E>,
51 context: ParserContext|
52 -> PResult<O, E> {
53 p1.parse(pos, state, context)
54 .merge_choice(p2.parse(pos, state, context))
55 }
56}
57
58#[inline(always)]
59pub fn repeat_delim<'arn, 'grm: 'arn, OP, OD, E: ParseError<L = ErrorLabel<'grm>>>(
60 item: impl Parser<'arn, 'grm, OP, E>,
61 delimiter: impl Parser<'arn, 'grm, OD, E>,
62 min: usize,
63 max: Option<usize>,
64) -> impl Parser<'arn, 'grm, Vec<OP>, E> {
65 move |pos: Pos,
66 state: &mut ParserState<'arn, 'grm, E>,
67 context: ParserContext|
68 -> PResult<Vec<OP>, E> {
69 let mut last_res: PResult<Vec<OP>, E> = PResult::new_empty(vec![], pos);
70
71 for i in 0..max.unwrap_or(usize::MAX) {
72 let pos = last_res.end_pos();
73 let part = if i == 0 {
74 item.parse(pos, state, context)
75 } else {
76 seq2(&delimiter, &item)
77 .parse(pos, state, context)
78 .map(|x| x.1)
79 };
80 let should_continue = part.is_ok();
81
82 if i < min {
83 last_res = last_res.merge_seq(part).map(|(mut vec, item)| {
84 vec.push(item);
85 vec
86 });
87 } else {
88 last_res = last_res.merge_seq_opt(part).map(|(mut vec, item)| {
89 if let Some(item) = item {
90 vec.push(item);
91 }
92 vec
93 });
94 };
95
96 if !should_continue {
97 break;
98 };
99
100 if i != 0 && last_res.end_pos() <= pos {
104 let span = pos.span_to(pos);
105 let mut e = E::new(span);
106 e.add_label_explicit(Debug(span, "INFLOOP"));
107 return PResult::new_err(e, pos);
108 }
109 }
110
111 last_res
112 }
113}
114
115#[inline(always)]
116pub fn end<'arn, 'grm: 'arn, E: ParseError>() -> impl Parser<'arn, 'grm, (), E> {
117 move |pos: Pos, state: &mut ParserState<'arn, 'grm, E>, _: ParserContext| -> PResult<(), E> {
118 match pos.next(state.input) {
119 (s, Some(_)) => PResult::new_err(E::new(pos.span_to(s)), pos),
120 (s, None) => PResult::new_empty((), s),
121 }
122 }
123}
124
125#[inline(always)]
126pub fn positive_lookahead<'arn, 'grm: 'arn, O, E: ParseError>(
127 p: &impl Parser<'arn, 'grm, O, E>,
128) -> impl Parser<'arn, 'grm, O, E> + '_ {
129 move |pos: Pos,
130 state: &mut ParserState<'arn, 'grm, E>,
131 context: ParserContext|
132 -> PResult<O, E> {
133 match p.parse(pos, state, context) {
134 POk(o, _, _, err) => POk(o, pos, pos, err),
135 PErr(e, s) => PErr(e, s),
136 }
137 }
138}
139
140#[inline(always)]
141pub fn negative_lookahead<'arn, 'grm: 'arn, O, E: ParseError>(
142 p: &impl Parser<'arn, 'grm, O, E>,
143) -> impl Parser<'arn, 'grm, (), E> + '_ {
144 move |pos: Pos,
145 state: &mut ParserState<'arn, 'grm, E>,
146 context: ParserContext|
147 -> PResult<(), E> {
148 match p.parse(pos, state, context) {
149 POk(_, _, _, _) => PResult::new_err(E::new(pos.span_to(pos)), pos),
150 PErr(_, _) => PResult::new_empty((), pos),
151 }
152 }
153}