1use crate::{
4 types::{ParserOutput, RawOutputConcat},
5 ParseContext, ParseIter, Parser, Reported, Result,
6};
7
8#[derive(Clone, Copy)]
9pub struct SequenceParser<Head, Tail, Op> {
10 head: Head,
11 tail: Tail,
12 _op: Op,
13}
14
15pub struct SequenceParseIter<'parse, Head, Tail, Op>
16where
17 Head: Parser + 'parse,
18 Tail: Parser + 'parse,
19{
20 parsers: &'parse SequenceParser<Head, Tail, Op>,
21 head_iter: Head::Iter<'parse>,
22 tail_iter: Tail::Iter<'parse>,
23}
24
25pub trait BinaryOp<Head, Tail>: Copy + Clone {
27 type Output: ParserOutput;
28
29 fn apply(head: Head, tail: Tail) -> Self::Output;
30}
31
32#[derive(Debug, Copy, Clone)]
34pub struct Concat;
35
36impl<Head, Tail> BinaryOp<Head, Tail> for Concat
37where
38 Head: RawOutputConcat<Tail>,
39{
40 type Output = <Head as RawOutputConcat<Tail>>::Output;
41
42 fn apply(head: Head, tail: Tail) -> Self::Output {
43 head.concat(tail)
44 }
45}
46
47#[derive(Debug, Copy, Clone)]
49pub struct Pair;
50
51impl<Head, Tail> BinaryOp<Head, Tail> for Pair
52where
53 Head: ParserOutput,
54 Tail: ParserOutput,
55{
56 type Output = (Head::UserType, Tail::UserType);
57
58 fn apply(head: Head, tail: Tail) -> Self::Output {
59 (head.into_user_type(), tail.into_user_type())
60 }
61}
62
63impl<Head, Tail, Op> Parser for SequenceParser<Head, Tail, Op>
64where
65 Head: Parser,
66 Tail: Parser,
67 Op: BinaryOp<Head::RawOutput, Tail::RawOutput>,
68{
69 type Output = <Op::Output as ParserOutput>::UserType;
70 type RawOutput = Op::Output;
71 type Iter<'parse> = SequenceParseIter<'parse, Head, Tail, Op>
72 where
73 Head: 'parse,
74 Tail: 'parse,
75 Op: 'parse;
76
77 fn parse_iter<'parse>(
78 &'parse self,
79 context: &mut ParseContext<'parse>,
80 start: usize,
81 ) -> Result<Self::Iter<'parse>, Reported> {
82 let mut head_iter = self.head.parse_iter(context, start)?;
83 let tail_iter = first_tail_match::<Head, Tail>(context, &mut head_iter, &self.tail)?;
84 Ok(SequenceParseIter {
85 parsers: self,
86 head_iter,
87 tail_iter,
88 })
89 }
90}
91
92fn first_tail_match<'parse, Head, Tail>(
93 context: &mut ParseContext<'parse>,
94 head: &mut Head::Iter<'parse>,
95 tail: &'parse Tail,
96) -> Result<Tail::Iter<'parse>, Reported>
97where
98 Head: Parser,
99 Tail: Parser,
100{
101 loop {
102 let mid = head.match_end();
103 if let Ok(tail_iter) = tail.parse_iter(context, mid) {
104 return Ok(tail_iter);
105 }
106 head.backtrack(context)?;
107 }
108}
109
110impl<'parse, Head, Tail, Op> ParseIter<'parse> for SequenceParseIter<'parse, Head, Tail, Op>
111where
112 Head: Parser,
113 Tail: Parser,
114 Op: BinaryOp<Head::RawOutput, Tail::RawOutput>,
115 Op::Output: ParserOutput,
116{
117 type RawOutput = Op::Output;
118
119 fn match_end(&self) -> usize {
120 self.tail_iter.match_end()
121 }
122
123 fn backtrack(&mut self, context: &mut ParseContext<'parse>) -> Result<(), Reported> {
124 self.tail_iter.backtrack(context).or_else(|Reported| {
125 self.head_iter.backtrack(context)?;
126 let tail_iter =
127 first_tail_match::<Head, Tail>(context, &mut self.head_iter, &self.parsers.tail)?;
128 self.tail_iter = tail_iter;
129 Ok(())
130 })
131 }
132
133 fn convert(&self) -> Self::RawOutput {
134 let head = self.head_iter.convert();
135 let tail = self.tail_iter.convert();
136 Op::apply(head, tail)
137 }
138}
139
140#[doc(hidden)]
142pub fn sequence<Head, Tail>(head: Head, tail: Tail) -> SequenceParser<Head, Tail, Concat> {
143 SequenceParser {
144 head,
145 tail,
146 _op: Concat,
147 }
148}
149
150#[doc(hidden)]
152pub fn pair<Head, Tail>(head: Head, tail: Tail) -> SequenceParser<Head, Tail, Pair> {
153 SequenceParser {
154 head,
155 tail,
156 _op: Pair,
157 }
158}