1use crate::{
8 ast::*,
9 error::{Error, ErrorKind},
10 pos::Span,
11 scanner::{ScalarStyle, Scanner, Token, TokenKind},
12};
13use oxc_allocator::{Allocator, Box, Vec};
14
15type ParseResult<T> = Result<T, Error>;
16
17pub struct Parser<'a> {
18 allocator: &'a Allocator,
19 source: &'a str,
20 scanner: Scanner<'a>,
21 peeked: Option<Token>,
22}
23
24impl<'a> Parser<'a> {
25 pub fn new(allocator: &'a Allocator, source: &'a str) -> Self {
26 Self { allocator, source, scanner: Scanner::new(allocator, source), peeked: None }
27 }
28
29 #[expect(clippy::cast_possible_truncation)] pub fn parse(mut self) -> ParseResult<Root<'a>> {
35 if u32::try_from(self.source.len()).is_err() {
36 return Err(Error::new(ErrorKind::SourceTooLong, Span::empty(0)));
37 }
38 let source_len = self.source.len() as u32;
39
40 let first = self.next()?;
41 debug_assert_eq!(first.kind, TokenKind::StreamStart);
42
43 let mut children = Vec::new_in(&self.allocator);
44 loop {
45 if self.peek()?.kind == TokenKind::StreamEnd {
46 break;
47 }
48 children.push(self.parse_document()?);
49 }
50
51 let comments = std::mem::replace(&mut self.scanner.comments, Vec::new_in(&self.allocator));
53
54 Ok(Root { span: Span::new(0, source_len), children, comments })
55 }
56
57 fn next(&mut self) -> ParseResult<Token> {
60 if let Some(t) = self.peeked.take() {
61 return Ok(t);
62 }
63 self.scanner.next_token()?.ok_or_else(|| {
64 Error::point(ErrorKind::UnexpectedEof, self.source.len().saturating_sub(1))
65 })
66 }
67
68 fn peek(&mut self) -> ParseResult<&Token> {
69 if self.peeked.is_none() {
70 self.peeked = Some(self.next()?);
71 }
72 Ok(self.peeked.as_ref().unwrap())
73 }
74
75 fn peek_kind(&mut self) -> ParseResult<TokenKind> {
76 Ok(self.peek()?.kind)
77 }
78
79 fn eat(&mut self, kind: TokenKind) -> ParseResult<Option<Token>> {
80 if self.peek()?.kind == kind {
81 return Ok(Some(self.next()?));
82 }
83 Ok(None)
84 }
85
86 fn alloc<T>(&self, value: T) -> Box<'a, T> {
87 Box::new_in(value, &self.allocator)
88 }
89
90 fn parse_optional_node(
94 &mut self,
95 allow_indentless: bool,
96 ) -> ParseResult<Option<Box<'a, Node<'a>>>> {
97 let kind = self.peek_kind()?;
98 let starts =
99 if allow_indentless { kind.starts_mapping_entry_node() } else { kind.starts_node() };
100 if starts {
101 let node = self.parse_node(allow_indentless)?;
102 Ok(Some(self.alloc(node)))
103 } else {
104 Ok(None)
105 }
106 }
107
108 fn parse_document(&mut self) -> ParseResult<Document<'a>> {
111 let head_start = self.peek()?.span.start;
112 let mut directives = Vec::new_in(&self.allocator);
113 while self.peek_kind()? == TokenKind::Directive {
114 let token = self.next()?;
115 directives.push(self.build_directive(token));
116 }
117 let head_end = directives.last().map_or(head_start, |d: &Directive<'a>| d.span.end);
118
119 let directives_end_marker = self.eat(TokenKind::DocumentStart)?.map(|t| t.span);
120 if !directives.is_empty() && directives_end_marker.is_none() {
121 return Err(Error::new(
122 ErrorKind::ExpectedDocumentStart,
123 Span::new(head_start, head_end),
124 ));
125 }
126
127 let head = DocumentHead {
128 span: Span::new(head_start, directives_end_marker.map_or(head_end, |s| s.end)),
129 directives,
130 };
131
132 let content = self.parse_optional_node(false)?;
133
134 let body_span = content.as_ref().map_or_else(
135 || Span::empty(directives_end_marker.map_or(head_start, |s| s.end)),
136 |node| node.span,
137 );
138 let body = DocumentBody { span: body_span, content };
139
140 let document_end_marker = self.eat(TokenKind::DocumentEnd)?.map(|t| t.span);
141 if document_end_marker.is_none() {
145 match self.peek_kind()? {
146 TokenKind::StreamEnd | TokenKind::DocumentStart | TokenKind::Directive => {}
147 _ => {
148 let span = self.peek()?.span;
149 return Err(Error::new(ErrorKind::ExpectedDocumentEnd, span));
150 }
151 }
152 }
153
154 let span_end = document_end_marker.map_or(body.span.end.max(head.span.end), |s| s.end);
157
158 Ok(Document {
159 span: Span::new(head_start, span_end),
160 head,
161 body,
162 directives_end_marker,
163 document_end_marker,
164 })
165 }
166
167 fn build_directive(&self, token: Token) -> Directive<'a> {
168 let text = token.span.slice(self.source);
169 let mut words = text.trim_start_matches('%').split_ascii_whitespace();
170 let name = words.next().unwrap_or("");
171 let parameters = Vec::from_iter_in(words, &self.allocator);
172 Directive { span: token.span, name, parameters }
173 }
174
175 fn parse_props(&mut self) -> ParseResult<Props> {
178 let mut props = Props { anchor: None, tag: None };
179 loop {
180 match self.peek_kind()? {
181 TokenKind::Anchor => {
182 let token = self.next()?;
183 if props.anchor.is_some() {
184 return Err(Error::new(ErrorKind::DuplicatedNodeProperty, token.span));
185 }
186 props.anchor = Some(Anchor { span: token.span });
187 }
188 TokenKind::Tag => {
189 let token = self.next()?;
190 if props.tag.is_some() {
191 return Err(Error::new(ErrorKind::DuplicatedNodeProperty, token.span));
192 }
193 props.tag = Some(Tag { span: token.span });
194 }
195 _ => break,
196 }
197 }
198 Ok(props)
199 }
200
201 fn parse_node(&mut self, allow_indentless: bool) -> ParseResult<Node<'a>> {
204 let props = self.parse_props()?;
205 let content = self.parse_content(&props, allow_indentless)?;
206 let content_span = content.span();
207 let span = Span::new(props.start().unwrap_or(content_span.start), content_span.end);
208 Ok(Node { span, props, content })
209 }
210
211 fn parse_content(&mut self, props: &Props, allow_indentless: bool) -> ParseResult<Content<'a>> {
216 let token = *self.peek()?;
217 match token.kind {
218 TokenKind::Alias => {
219 self.next()?;
220 if props.anchor.is_some() || props.tag.is_some() {
221 return Err(Error::new(ErrorKind::DuplicatedNodeProperty, token.span));
222 }
223 Ok(Content::Alias(self.alloc(Alias { span: token.span })))
224 }
225 TokenKind::Scalar(style, header_index) => {
226 self.next()?;
227 Ok(self.build_scalar(style, header_index, token.span))
228 }
229 TokenKind::FlowSequenceStart => self.parse_flow_sequence(),
230 TokenKind::FlowMappingStart => self.parse_flow_mapping(),
231 TokenKind::BlockSequenceStart => self.parse_block_sequence(),
232 TokenKind::BlockMappingStart => self.parse_block_mapping(),
233 TokenKind::BlockEntry if allow_indentless => self.parse_indentless_sequence(),
238 _ => {
239 if props.anchor.is_some() || props.tag.is_some() {
242 let at = props
243 .anchor
244 .map(|a| a.span.end)
245 .max(props.tag.map(|t| t.span.end))
246 .unwrap();
247 return Ok(Content::Plain(self.alloc(Plain { span: Span::empty(at) })));
248 }
249 Err(Error::new(ErrorKind::ExpectedNode, token.span))
250 }
251 }
252 }
253
254 fn build_scalar(
255 &self,
256 style: ScalarStyle,
257 header_index: Option<crate::scanner::BlockHeaderIndex>,
258 span: Span,
259 ) -> Content<'a> {
260 match style {
261 ScalarStyle::Plain => Content::Plain(self.alloc(Plain { span })),
262 ScalarStyle::SingleQuoted => Content::QuoteSingle(self.alloc(QuoteSingle { span })),
263 ScalarStyle::DoubleQuoted => Content::QuoteDouble(self.alloc(QuoteDouble { span })),
264 ScalarStyle::Literal | ScalarStyle::Folded => {
265 let index = header_index.expect("block scalar token must carry a header index");
266 let header = self.scanner.block_headers[index.get()];
267 let node = BlockScalar {
268 span,
269 chomping: header.chomping,
270 indent: header.indent,
271 content_start: header.content_start,
272 content_end: header.content_end,
273 };
274 if style == ScalarStyle::Literal {
275 Content::BlockLiteral(self.alloc(node))
276 } else {
277 Content::BlockFolded(self.alloc(node))
278 }
279 }
280 }
281 }
282
283 fn parse_sequence_item(&mut self) -> ParseResult<SequenceItem<'a>> {
285 let entry_token = self.next()?;
286 debug_assert_eq!(entry_token.kind, TokenKind::BlockEntry);
287 let content = self.parse_optional_node(false)?;
288 let end = content.as_ref().map_or(entry_token.span.end, |n| n.span.end);
289 Ok(SequenceItem { span: Span::new(entry_token.span.start, end), content })
290 }
291
292 fn parse_block_sequence(&mut self) -> ParseResult<Content<'a>> {
293 let start_token = self.next()?; let mut children = Vec::new_in(&self.allocator);
295
296 loop {
297 match self.peek_kind()? {
298 TokenKind::BlockEnd => {
299 self.next()?;
300 break;
301 }
302 TokenKind::BlockEntry => children.push(self.parse_sequence_item()?),
303 _ => {
304 let span = self.peek()?.span;
305 return Err(Error::new(ErrorKind::UnexpectedToken("token in sequence"), span));
306 }
307 }
308 }
309
310 let span = container_span(start_token.span, children.first(), children.last());
311 Ok(Content::Sequence(self.alloc(Sequence { span, children })))
312 }
313
314 fn parse_indentless_sequence(&mut self) -> ParseResult<Content<'a>> {
319 let mut children = Vec::new_in(&self.allocator);
320 let first = self.peek()?.span;
321
322 while self.peek_kind()? == TokenKind::BlockEntry {
323 children.push(self.parse_sequence_item()?);
324 }
325
326 let span = container_span(Span::empty(first.start), children.first(), children.last());
327 Ok(Content::Sequence(self.alloc(Sequence { span, children })))
328 }
329
330 fn parse_block_mapping(&mut self) -> ParseResult<Content<'a>> {
331 let start_token = self.next()?; let mut children = Vec::new_in(&self.allocator);
333
334 loop {
335 match self.peek_kind()? {
336 TokenKind::BlockEnd => {
337 self.next()?;
338 break;
339 }
340 TokenKind::Key | TokenKind::Value => {
341 children.push(self.parse_mapping_item()?);
342 }
343 _ => {
344 let span = self.peek()?.span;
345 return Err(Error::new(ErrorKind::UnexpectedToken("token in mapping"), span));
346 }
347 }
348 }
349
350 let span = container_span(start_token.span, children.first(), children.last());
351 Ok(Content::Mapping(self.alloc(Mapping { span, children })))
352 }
353
354 fn parse_mapping_item(&mut self) -> ParseResult<MappingItem<'a>> {
357 let key_token = self.eat(TokenKind::Key)?;
360 let key = if let Some(key_token) = key_token {
361 let explicit = !key_token.synthesized;
362 let content = self.parse_optional_node(true)?;
363 match content {
364 Some(node) => {
365 let start = if explicit { key_token.span.start } else { node.span.start };
367 let span = Span::new(start, node.span.end);
368 Some(MappingKey { span, content: Some(node), explicit })
369 }
370 None if explicit => {
371 Some(MappingKey { span: key_token.span, content: None, explicit })
372 }
373 None => None,
376 }
377 } else {
378 None
379 };
380
381 let value = if let Some(value_token) = self.eat(TokenKind::Value)? {
383 let content = self.parse_optional_node(true)?;
384 let end = content.as_ref().map_or(value_token.span.end, |n| n.span.end);
385 Some(MappingValue { span: Span::new(value_token.span.start, end), content })
386 } else {
387 None
388 };
389
390 let start = key
393 .as_ref()
394 .map(|k| k.span.start)
395 .or_else(|| value.as_ref().map(|v| v.span.start))
396 .or_else(|| key_token.map(|t| t.span.start))
397 .expect("parse_mapping_item is entered at a Key or Value token");
398 let end = value
399 .as_ref()
400 .map(|v| v.span.end)
401 .max(key.as_ref().map(|k| k.span.end))
402 .unwrap_or(start);
403 Ok(MappingItem { span: Span::new(start, end), key, value })
404 }
405
406 fn parse_flow_sequence(&mut self) -> ParseResult<Content<'a>> {
407 let start_token = self.next()?; let mut children = Vec::new_in(&self.allocator);
409
410 loop {
411 match self.peek_kind()? {
412 TokenKind::FlowSequenceEnd => {
413 let end_token = self.next()?;
414 let span = Span::new(start_token.span.start, end_token.span.end);
415 return Ok(Content::FlowSequence(self.alloc(FlowSequence { span, children })));
416 }
417 TokenKind::FlowEntry => {
418 self.next()?;
419 }
420 TokenKind::Key | TokenKind::Value => {
421 let item = self.parse_mapping_item()?;
424 children.push(FlowSequenceEntry::Pair(self.alloc(item)));
425 }
426 _ => {
427 let is_synthesized_pair = {
430 let token = self.peek()?;
431 token.kind == TokenKind::FlowMappingStart && token.synthesized
432 };
433 let node = self.parse_node(false)?;
434 if is_synthesized_pair {
435 if let Content::FlowMapping(mapping) = node.content {
436 let mut mapping = mapping.unbox();
437 debug_assert_eq!(mapping.children.len(), 1);
438 if let Some(item) = mapping.children.pop() {
439 children.push(FlowSequenceEntry::Pair(self.alloc(item)));
440 }
441 continue;
442 }
443 unreachable!("synthesized FlowMappingStart must produce a FlowMapping");
444 }
445 children.push(FlowSequenceEntry::Item(self.alloc(node)));
446 }
447 }
448 }
449 }
450
451 fn parse_flow_mapping(&mut self) -> ParseResult<Content<'a>> {
452 let start_token = self.next()?; let mut children = Vec::new_in(&self.allocator);
454
455 loop {
456 match self.peek_kind()? {
457 TokenKind::FlowMappingEnd => {
458 let end_token = self.next()?;
459 let span = if end_token.synthesized {
460 container_span(start_token.span, children.first(), children.last())
462 } else {
463 Span::new(start_token.span.start, end_token.span.end)
464 };
465 return Ok(Content::FlowMapping(self.alloc(FlowMapping { span, children })));
466 }
467 TokenKind::FlowEntry => {
468 self.next()?;
469 }
470 TokenKind::Key | TokenKind::Value => {
471 children.push(self.parse_mapping_item()?);
472 }
473 _ if self.peek_kind()?.starts_node() => {
474 let node = self.parse_node(false)?;
476 let span = node.span;
477 children.push(MappingItem {
478 span,
479 key: Some(MappingKey {
480 span,
481 content: Some(self.alloc(node)),
482 explicit: false,
483 }),
484 value: None,
485 });
486 }
487 _ => {
488 let span = self.peek()?.span;
489 return Err(Error::new(
490 ErrorKind::UnexpectedToken("token in flow mapping"),
491 span,
492 ));
493 }
494 }
495 }
496 }
497}
498
499fn container_span<T: HasSpan>(start: Span, first: Option<&T>, last: Option<&T>) -> Span {
502 let start_pos = first.map_or(start.start, |c| c.span().start.min(start.start));
503 let end_pos = last.map_or(start.end, |c| c.span().end.max(start.end));
504 Span::new(start_pos, end_pos)
505}
506
507trait HasSpan {
509 fn span(&self) -> Span;
510}
511
512impl HasSpan for SequenceItem<'_> {
513 fn span(&self) -> Span {
514 self.span
515 }
516}
517
518impl HasSpan for MappingItem<'_> {
519 fn span(&self) -> Span {
520 self.span
521 }
522}