sqparse/parser/
parse_result_ext.rs

1use crate::parser::error::TokenAffinity;
2use crate::parser::token_list::TokenList;
3use crate::parser::token_list_ext::TokenListExt;
4use crate::parser::ParseResult;
5use crate::{ContextType, ParseError, ParseErrorType};
6use std::ops::Range;
7
8pub trait ParseResultExt<'s, T>: Sized {
9    fn into_parse_result(self) -> ParseResult<'s, T>;
10
11    fn maybe(self, tokens: TokenList<'s>) -> ParseResult<'s, Option<T>> {
12        match self.into_parse_result() {
13            Ok((tokens, val)) => Ok((tokens, Some(val))),
14            Err(err) if err.is_fatal => Err(err),
15            Err(_) => Ok((tokens, None)),
16        }
17    }
18
19    fn not_definite(self) -> ParseResult<'s, T> {
20        self.into_parse_result().map_err(|err| err.into_non_fatal())
21    }
22
23    fn definite(self) -> ParseResult<'s, T> {
24        self.into_parse_result().map_err(|err| err.into_fatal())
25    }
26
27    fn not_line_ending(self) -> ParseResult<'s, T> {
28        let (tokens, val) = self.into_parse_result()?;
29        if tokens.is_newline() {
30            Err(tokens.error(ParseErrorType::IllegalLineBreak))
31        } else {
32            Ok((tokens, val))
33        }
34    }
35
36    fn map_val<B, F: FnOnce(T) -> B>(self, map: F) -> ParseResult<'s, B> {
37        self.into_parse_result().map(|(tokens, a)| (tokens, map(a)))
38    }
39
40    fn or_try<F: FnOnce() -> ParseResult<'s, T>>(self, f: F) -> ParseResult<'s, T> {
41        match self.into_parse_result() {
42            Ok((tokens, val)) => Ok((tokens, val)),
43            Err(err) if err.is_fatal => Err(err),
44            Err(_) => f(),
45        }
46    }
47
48    fn or_error<F: FnOnce() -> ParseError>(self, f: F) -> ParseResult<'s, T> {
49        self.or_try(|| Err(f()))
50    }
51
52    fn with_context(self, ty: ContextType, range: Range<usize>) -> ParseResult<'s, T> {
53        self.replace_context(ContextType::Span, ty, range)
54    }
55
56    fn with_context_from(self, ty: ContextType, tokens: TokenList) -> ParseResult<'s, T> {
57        self.replace_context_from(ContextType::Span, ty, tokens)
58    }
59
60    fn replace_context(
61        self,
62        from_ty: ContextType,
63        to_ty: ContextType,
64        range: Range<usize>,
65    ) -> ParseResult<'s, T> {
66        self.into_parse_result()
67            .map_err(|err| err.replace_context(from_ty, to_ty, range, TokenAffinity::Inline))
68    }
69
70    fn replace_context_from(
71        self,
72        from_ty: ContextType,
73        to_ty: ContextType,
74        tokens: TokenList,
75    ) -> ParseResult<'s, T> {
76        let start_index = tokens.start_index();
77        self.into_parse_result().map_err(|err| {
78            let range = start_index..err.token_index;
79            err.replace_context(from_ty, to_ty, range, TokenAffinity::Before)
80        })
81    }
82
83    fn determines<B, F: FnOnce(TokenList<'s>, T) -> ParseResult<'s, B>>(
84        self,
85        f: F,
86    ) -> ParseResult<'s, B> {
87        let (tokens, a) = self.into_parse_result().not_definite()?;
88        f(tokens, a).definite()
89    }
90
91    fn opens<
92        Close,
93        Out,
94        FClose: Fn(TokenList<'s>) -> ParseResult<'s, Close>,
95        FInner: FnOnce(TokenList<'s>, T, Close) -> ParseResult<'s, Out>,
96    >(
97        self,
98        context: ContextType,
99        close: FClose,
100        inner: FInner,
101    ) -> ParseResult<'s, Out> {
102        let (tokens, open_val) = self.into_parse_result()?;
103        let close_index = tokens.previous().unwrap().close_index.unwrap();
104        let span_range = (tokens.start_index() - 1)..(close_index + 1);
105
106        let (inner_tokens, outer_tokens) = tokens.split_at(close_index);
107        let (outer_tokens, close_val) =
108            close(outer_tokens).with_context(context, span_range.clone())?;
109        let (inner_tokens, value) =
110            inner(inner_tokens, open_val, close_val).with_context(context, span_range.clone())?;
111
112        if !inner_tokens.is_ended() {
113            let mut remaining_tokens = inner_tokens;
114
115            // Hack to trigger an error with the close parser, since the inner parser did not
116            // consume all of the input.
117            loop {
118                let (new_tokens, _) =
119                    close(remaining_tokens).with_context(context, span_range.clone())?;
120
121                // If parsing succeeded with no input tokens, something has gone wrong and we don't
122                // want to loop forever.
123                assert!(!remaining_tokens.is_ended());
124
125                remaining_tokens = new_tokens;
126            }
127        }
128
129        Ok((outer_tokens, value))
130    }
131
132    fn determines_and_opens<
133        Close,
134        Out,
135        FClose: Fn(TokenList<'s>) -> ParseResult<'s, Close>,
136        FInner: FnOnce(TokenList<'s>, T, Close) -> ParseResult<'s, Out>,
137    >(
138        self,
139        context: ContextType,
140        close: FClose,
141        inner: FInner,
142    ) -> ParseResult<'s, Out> {
143        let (tokens, open_val) = self.into_parse_result().not_definite()?;
144        Ok((tokens, open_val))
145            .opens(context, close, inner)
146            .definite()
147    }
148}
149
150impl<'s, T> ParseResultExt<'s, T> for ParseResult<'s, T> {
151    #[inline]
152    fn into_parse_result(self) -> ParseResult<'s, T> {
153        self
154    }
155}