lazy_template/enclosed/
parser.rs1use super::{ComponentParserInput, ParserConfig, Segment};
2use crate::{IntoSkipOrFatal, Parse};
3use derive_more::{Display, Error};
4use split_first_char::split_first_char;
5
6#[derive(Debug, Clone, Copy)]
9pub struct EnclosedTemplateParser<EscapeParser, QueryParser> {
10 pub config: ParserConfig,
11 pub escape_parser: EscapeParser,
12 pub query_parser: QueryParser,
13}
14
15pub type Parser<EscapeParser, QueryParser> = EnclosedTemplateParser<EscapeParser, QueryParser>;
16
17impl<EscapeParser, QueryParser> Parser<EscapeParser, QueryParser> {
18 pub fn with_config(mut self, config: ParserConfig) -> Self {
20 self.config = config;
21 self
22 }
23
24 pub fn with_escape_parser<NewEscapeParser>(
26 self,
27 escape_parser: NewEscapeParser,
28 ) -> Parser<NewEscapeParser, QueryParser> {
29 let Parser {
30 config,
31 query_parser,
32 escape_parser: _,
33 } = self;
34 Parser {
35 config,
36 escape_parser,
37 query_parser,
38 }
39 }
40
41 pub fn with_query_parser<NewQueryParser>(
43 self,
44 query_parser: NewQueryParser,
45 ) -> Parser<EscapeParser, NewQueryParser> {
46 let Parser {
47 config,
48 escape_parser,
49 query_parser: _,
50 } = self;
51 Parser {
52 config,
53 escape_parser,
54 query_parser,
55 }
56 }
57}
58
59impl Parser<(), ()> {
60 pub fn curly_braces() -> Self {
93 Parser {
94 config: ParserConfig::curly_braces(),
95 escape_parser: (),
96 query_parser: (),
97 }
98 }
99}
100
101#[derive(Debug, Display, Error, Clone, Copy)]
103pub enum ParseError<ParseEscapeError, ParseQueryError> {
104 #[display("Unexpected token {_0:?}")]
105 UnexpectedChar(#[error(not(source))] char),
106 #[display("Unexpected end of input")]
107 UnexpectedEndOfInput,
108 #[display("Fail to escape: {_0}")]
109 ParseEscape(ParseEscapeError),
110 #[display("Fail to parse query: {_0}")]
111 ParseQuery(ParseQueryError),
112}
113
114impl<'a, EscapeParser, QueryParser> Parse<'a> for Parser<EscapeParser, QueryParser>
115where
116 EscapeParser: Parse<'a, ComponentParserInput<'a>, Output = char>,
117 EscapeParser::Error: IntoSkipOrFatal,
118 QueryParser: Parse<'a, ComponentParserInput<'a>>,
119 QueryParser::Error: IntoSkipOrFatal,
120{
121 type Output = Segment<QueryParser::Output>;
122 type Error = ParseError<
123 <EscapeParser::Error as IntoSkipOrFatal>::Fatal,
124 <QueryParser::Error as IntoSkipOrFatal>::Fatal,
125 >;
126
127 fn parse(&self, input: &'a str) -> Result<(Self::Output, &'a str), Self::Error> {
128 let component_parser_input = ComponentParserInput {
129 text: input,
130 config: self.config,
131 };
132
133 let escape_pair = self
134 .escape_parser
135 .parse_as_component(component_parser_input)
136 .map_err(ParseError::ParseEscape)?;
137 if let Some((escaped, rest)) = escape_pair {
138 return Ok((Segment::Character(escaped), rest));
139 }
140
141 let query_pair = self
142 .query_parser
143 .parse_as_component(component_parser_input)
144 .map_err(ParseError::ParseQuery)?;
145 if let Some((query, rest)) = query_pair {
146 return Ok((Segment::Expression(query), rest));
147 }
148
149 let (head, tail) = split_first_char(input).ok_or(ParseError::UnexpectedEndOfInput)?;
150
151 if head == self.config.close_bracket {
152 return Err(ParseError::UnexpectedChar(head));
153 }
154
155 Ok((Segment::Character(head), tail))
156 }
157}