1pub mod element_type;
2
3use crate::{
4 language::HandlebarsLanguage,
5 lexer::{HandlebarsLexer, token_type::HandlebarsTokenType},
6};
7use oak_core::{
8 Parser,
9 errors::OakError,
10 parser::{ParseCache, ParseOutput, ParserState, parse_with_lexer},
11 source::{Source, TextEdit},
12};
13
14pub(crate) type State<'a, S> = ParserState<'a, HandlebarsLanguage, S>;
15
16pub struct HandlebarsParser<'config> {
18 pub(crate) config: &'config HandlebarsLanguage,
20}
21
22impl<'config> HandlebarsParser<'config> {
23 pub fn new(config: &'config HandlebarsLanguage) -> Self {
25 Self { config }
26 }
27}
28
29impl<'config> Parser<HandlebarsLanguage> for HandlebarsParser<'config> {
30 fn parse<'a, S: Source + ?Sized>(&self, text: &'a S, edits: &[TextEdit], cache: &'a mut impl ParseCache<HandlebarsLanguage>) -> ParseOutput<'a, HandlebarsLanguage> {
31 let lexer = HandlebarsLexer::new(&self.config);
32 parse_with_lexer(&lexer, text, edits, cache, |state| {
33 let checkpoint = state.checkpoint();
34
35 while state.not_at_end() {
36 self.parse_item(state)?
37 }
38
39 Ok(state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::Root))
40 })
41 }
42}
43
44impl<'config> HandlebarsParser<'config> {
45 fn parse_item<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
46 let token = match state.current() {
47 Some(t) => t,
48 None => {
49 let err = OakError::unexpected_eof(state.tokens.index(), state.source_id());
50 state.errors.push(err.clone());
51 return Err(err);
52 }
53 };
54
55 match token.kind {
56 HandlebarsTokenType::Content => {
57 let checkpoint = state.checkpoint();
58 state.advance();
59 state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::ContentNode);
60 }
61 HandlebarsTokenType::Open => self.parse_mustache(state)?,
62 HandlebarsTokenType::OpenUnescaped => self.parse_mustache_unescaped(state)?,
63 HandlebarsTokenType::OpenBlock => self.parse_block(state)?,
64 HandlebarsTokenType::OpenInverseBlock => self.parse_inverse_block(state)?,
65 HandlebarsTokenType::OpenRawBlock => self.parse_raw_block(state)?,
66 HandlebarsTokenType::OpenPartial => self.parse_partial(state)?,
67 HandlebarsTokenType::OpenComment | HandlebarsTokenType::OpenCommentBlock => self.parse_comment(state)?,
68 HandlebarsTokenType::Whitespace | HandlebarsTokenType::Newline => state.advance(),
69 _ => {
70 state.advance()
72 }
73 }
74
75 Ok(())
76 }
77
78 fn parse_mustache<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
79 let checkpoint = state.checkpoint();
80 state.expect(HandlebarsTokenType::Open)?;
81
82 self.skip_trivia(state);
83 self.parse_expression(state)?;
84 self.skip_trivia(state);
85
86 state.expect(HandlebarsTokenType::Close)?;
87 state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::Mustache);
88 Ok(())
89 }
90
91 fn parse_mustache_unescaped<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
92 let checkpoint = state.checkpoint();
93 state.expect(HandlebarsTokenType::OpenUnescaped)?;
94
95 self.skip_trivia(state);
96 self.parse_expression(state)?;
97 self.skip_trivia(state);
98
99 state.expect(HandlebarsTokenType::CloseUnescaped)?;
100 state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::Mustache);
101 Ok(())
102 }
103
104 fn parse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
105 let checkpoint = state.checkpoint();
106 state.expect(HandlebarsTokenType::OpenBlock)?;
107
108 self.skip_trivia(state);
109 self.parse_expression(state)?;
110 self.skip_trivia(state);
111
112 state.expect(HandlebarsTokenType::Close)?;
113
114 while state.not_at_end() && !state.at(HandlebarsTokenType::CloseBlock) {
116 if state.at(HandlebarsTokenType::Open) {
117 let next = state.peek_at(1);
119 if let Some(token) = next {
120 if token.kind == HandlebarsTokenType::Else {
121 self.parse_else_block(state)?;
122 continue;
123 }
124 }
125 }
126 self.parse_item(state)?
127 }
128
129 if state.at(HandlebarsTokenType::CloseBlock) {
130 state.expect(HandlebarsTokenType::CloseBlock)?;
131 self.skip_trivia(state);
132 self.parse_path(state)?;
133 self.skip_trivia(state);
134 state.expect(HandlebarsTokenType::Close)?
135 }
136
137 state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::Block);
138 Ok(())
139 }
140
141 fn parse_inverse_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
142 let checkpoint = state.checkpoint();
143 state.expect(HandlebarsTokenType::OpenInverseBlock)?;
144
145 self.skip_trivia(state);
146 if !state.at(HandlebarsTokenType::Close) {
147 self.parse_expression(state)?;
148 self.skip_trivia(state)
149 }
150
151 state.expect(HandlebarsTokenType::Close)?;
152
153 while state.not_at_end() && !state.at(HandlebarsTokenType::CloseBlock) {
154 self.parse_item(state)?
155 }
156
157 if state.at(HandlebarsTokenType::CloseBlock) {
158 state.expect(HandlebarsTokenType::CloseBlock)?;
159 self.skip_trivia(state);
160 self.parse_path(state)?;
161 self.skip_trivia(state);
162 state.expect(HandlebarsTokenType::Close)?
163 }
164
165 state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::InverseBlock);
166 Ok(())
167 }
168
169 fn parse_else_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
170 let checkpoint = state.checkpoint();
171 state.expect(HandlebarsTokenType::Open)?;
172 state.expect(HandlebarsTokenType::Else)?;
173 state.expect(HandlebarsTokenType::Close)?;
174
175 while state.not_at_end() && !state.at(HandlebarsTokenType::CloseBlock) {
176 self.parse_item(state)?
177 }
178
179 state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::ElseBlock);
180 Ok(())
181 }
182
183 fn parse_raw_block<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
184 let checkpoint = state.checkpoint();
185 state.expect(HandlebarsTokenType::OpenRawBlock)?;
186
187 self.skip_trivia(state);
188 self.parse_expression(state)?;
189 self.skip_trivia(state);
190
191 state.expect(HandlebarsTokenType::CloseRawBlock)?;
192
193 while state.not_at_end() && !state.at(HandlebarsTokenType::OpenEndRawBlock) {
195 state.advance()
196 }
197
198 if state.at(HandlebarsTokenType::OpenEndRawBlock) {
199 state.expect(HandlebarsTokenType::OpenEndRawBlock)?;
200 self.skip_trivia(state);
201 self.parse_path(state)?;
202 self.skip_trivia(state);
203 state.expect(HandlebarsTokenType::CloseRawBlock)?
204 }
205
206 state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::Block);
207 Ok(())
208 }
209
210 fn parse_partial<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
211 let checkpoint = state.checkpoint();
212 state.expect(HandlebarsTokenType::OpenPartial)?;
213
214 self.skip_trivia(state);
215 self.parse_path(state)?;
216 self.skip_trivia(state);
217
218 while state.not_at_end() && !state.at(HandlebarsTokenType::Close) {
219 self.parse_parameter(state)?;
220 self.skip_trivia(state)
221 }
222
223 state.expect(HandlebarsTokenType::Close)?;
224 state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::Partial);
225 Ok(())
226 }
227
228 fn parse_comment<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
229 let checkpoint = state.checkpoint();
230 if state.at(HandlebarsTokenType::OpenComment) {
231 state.expect(HandlebarsTokenType::OpenComment)?;
232 while state.not_at_end() && !state.at(HandlebarsTokenType::Close) {
233 state.advance()
234 }
235 state.expect(HandlebarsTokenType::Close)?
236 }
237 else {
238 state.expect(HandlebarsTokenType::OpenCommentBlock)?;
239 while state.not_at_end() && !state.at(HandlebarsTokenType::CloseCommentBlock) {
240 state.advance()
241 }
242 state.expect(HandlebarsTokenType::CloseCommentBlock)?
243 }
244 state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::CommentNode);
245 Ok(())
246 }
247
248 fn parse_expression<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
249 let checkpoint = state.checkpoint();
250
251 self.parse_path(state)?;
252
253 while state.not_at_end() && !state.at(HandlebarsTokenType::Close) && !state.at(HandlebarsTokenType::CloseUnescaped) {
254 self.skip_trivia(state);
255 if state.at(HandlebarsTokenType::Identifier) || state.at(HandlebarsTokenType::StringLiteral) || state.at(HandlebarsTokenType::NumberLiteral) || state.at(HandlebarsTokenType::BooleanLiteral) { self.parse_parameter(state)? } else { break }
256 }
257
258 state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::Expression);
259 Ok(())
260 }
261
262 fn parse_parameter<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
263 if state.at(HandlebarsTokenType::Identifier) {
264 let next = state.peek_at(1);
266 if let Some(token) = next {
267 if token.kind == HandlebarsTokenType::Equal {
268 let checkpoint = state.checkpoint();
269 state.expect(HandlebarsTokenType::Identifier)?;
270 state.expect(HandlebarsTokenType::Equal)?;
271 self.parse_value(state)?;
272 state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::Parameter);
273 return Ok(());
274 }
275 }
276 }
277
278 self.parse_value(state)
279 }
280
281 fn parse_value<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
282 if state.at(HandlebarsTokenType::Identifier) {
283 self.parse_path(state)?
284 }
285 else if state.at(HandlebarsTokenType::StringLiteral) || state.at(HandlebarsTokenType::NumberLiteral) || state.at(HandlebarsTokenType::BooleanLiteral) {
286 state.advance()
287 }
288 else if state.at(HandlebarsTokenType::LeftParen) {
289 self.parse_sub_expression(state)?
290 }
291 else {
292 let token = state.current();
293 let err = oak_core::errors::OakError::unexpected_token(format!("{:?}", token.map(|t| t.kind)), state.tokens.index(), state.source_id());
294 state.errors.push(err.clone());
295 return Err(err);
296 }
297 Ok(())
298 }
299
300 fn parse_path<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
301 let checkpoint = state.checkpoint();
302 state.expect(HandlebarsTokenType::Identifier)?;
303
304 while state.at(HandlebarsTokenType::Dot) || state.at(HandlebarsTokenType::Slash) {
305 state.advance();
306 state.expect(HandlebarsTokenType::Identifier)?
307 }
308
309 state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::Path);
310 Ok(())
311 }
312
313 fn parse_sub_expression<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) -> Result<(), OakError> {
314 let checkpoint = state.checkpoint();
315 state.expect(HandlebarsTokenType::LeftParen)?;
316
317 self.skip_trivia(state);
318 self.parse_expression(state)?;
319 self.skip_trivia(state);
320
321 state.expect(HandlebarsTokenType::RightParen)?;
322 state.finish_at(checkpoint, crate::parser::element_type::HandlebarsElementType::SubExpression);
323 Ok(())
324 }
325
326 fn skip_trivia<'a, S: Source + ?Sized>(&self, state: &mut State<'a, S>) {
327 while state.at(HandlebarsTokenType::Whitespace) || state.at(HandlebarsTokenType::Newline) {
328 state.advance()
329 }
330 }
331}