1
/*
2
 * Hurl (https://hurl.dev)
3
 * Copyright (C) 2024 Orange
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *          http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
use crate::reader::Reader;
19

            
20
/// Represent a parser error. This type of error ca be recoverable or not and
21
/// implements conversion to recoverable / non-recoverable instance.
22
pub trait ParseError {
23
    /// Is this error recoverable or not?
24
    fn is_recoverable(&self) -> bool;
25

            
26
    /// Transforms this error to a recoverable one.
27
    fn to_recoverable(self) -> Self;
28

            
29
    /// Transforms this error to a non-recoverable one.
30
    fn to_non_recoverable(self) -> Self;
31
}
32

            
33
/// A parser func.
34
pub type ParseFunc<T, E> = fn(&mut Reader) -> Result<T, E>;
35

            
36
/// Try to consume one instances of the provided parser.
37
772400
pub fn optional<T, E>(f: ParseFunc<T, E>, reader: &mut Reader) -> Result<Option<T>, E>
38
772400
where
39
772400
    E: ParseError,
40
772400
{
41
772400
    let start = reader.cursor();
42
772400
    match f(reader) {
43
27065
        Ok(r) => Ok(Some(r)),
44
745335
        Err(e) => {
45
745335
            if e.is_recoverable() {
46
745200
                reader.seek(start);
47
745200
                Ok(None)
48
            } else {
49
135
                Err(e)
50
            }
51
        }
52
    }
53
}
54

            
55
/// Makes an error recoverable but does not reset cursor.
56
254105
pub fn recover<T, E>(f: ParseFunc<T, E>, reader: &mut Reader) -> Result<T, E>
57
254105
where
58
254105
    E: ParseError,
59
254105
{
60
254105
    match f(reader) {
61
84545
        Ok(r) => Ok(r),
62
169560
        Err(e) => Err(e.to_recoverable()),
63
    }
64
}
65

            
66
/// Makes an error non recoverable.
67
2435
pub fn non_recover<T, E>(f: ParseFunc<T, E>, reader: &mut Reader) -> Result<T, E>
68
2435
where
69
2435
    E: ParseError,
70
2435
{
71
2435
    match f(reader) {
72
2320
        Ok(r) => Ok(r),
73
115
        Err(e) => Err(e.to_non_recoverable()),
74
    }
75
}
76

            
77
/// Consumes zero or more instances of the provided parser.
78
1183079
pub fn zero_or_more<T, E>(f: ParseFunc<T, E>, reader: &mut Reader) -> Result<Vec<T>, E>
79
1183079
where
80
1183079
    E: ParseError,
81
1183079
{
82
1183079
    let mut v = Vec::new();
83
    loop {
84
1378666
        let initial_state = reader.cursor();
85
1378666
        if reader.is_eof() {
86
21629
            return Ok(v);
87
        }
88
1357037

            
89
1357037
        match f(reader) {
90
195587
            Ok(r) => {
91
195587
                v.push(r);
92
            }
93
1161450
            Err(e) => {
94
1161450
                return if e.is_recoverable() {
95
1160992
                    reader.seek(initial_state);
96
1160992
                    Ok(v)
97
                } else {
98
458
                    Err(e)
99
                };
100
            }
101
        }
102
    }
103
}
104

            
105
/// Consumes one or more instances of the provided parser.
106
59070
pub fn one_or_more<T, E>(f: ParseFunc<T, E>, reader: &mut Reader) -> Result<Vec<T>, E>
107
59070
where
108
59070
    E: ParseError,
109
59070
{
110
59070
    match f(reader) {
111
59065
        Ok(first) => {
112
59065
            let mut v = vec![first];
113
            loop {
114
59445
                let initial_state = reader.cursor();
115
59445
                match f(reader) {
116
380
                    Ok(r) => {
117
380
                        v.push(r);
118
                    }
119
59065
                    Err(e) => {
120
59065
                        return if e.is_recoverable() {
121
59065
                            reader.seek(initial_state);
122
59065
                            Ok(v)
123
                        } else {
124
                            Err(e)
125
                        };
126
                    }
127
                }
128
            }
129
        }
130
        // if zero occurrence => should fail?
131
5
        Err(e) => Err(e.to_non_recoverable()),
132
    }
133
}
134

            
135
/// Tries to apply the list of parser until one of them succeeds.
136
/// Typically, this should be recoverable
137
139287
pub fn choice<T, E>(fs: &[ParseFunc<T, E>], reader: &mut Reader) -> Result<T, E>
138
139287
where
139
139287
    E: ParseError,
140
139287
{
141
1108904
    for (pos, f) in fs.iter().enumerate() {
142
1108904
        let start = reader.cursor();
143
1108904
        if pos == fs.len() - 1 {
144
75640
            return f(reader);
145
        }
146
1033264
        match f(reader) {
147
969761
            Err(err) if err.is_recoverable() => {
148
969617
                reader.seek(start);
149
969617
                continue;
150
            }
151
63647
            x => return x,
152
        }
153
    }
154
    unreachable!("You can't call choice with an empty vector of choice")
155
}