Skip to main content

oxc_graphql_parser/
parser_ast.rs

1use crate::ast::*;
2use crate::lexer::Lexer;
3use crate::{Error, LimitTracker, T, Token, TokenKind};
4use oxc_allocator::{Allocator, Box as ArenaBox, Vec as ArenaVec};
5use std::ops::ControlFlow;
6
7pub struct Parser<'a> {
8    allocator: &'a Allocator,
9    input: &'a str,
10    lexer: Lexer<'a>,
11    current_token: Option<Token<'a>>,
12    errors: Vec<Error>,
13    comments: Vec<Span>,
14    recursion_limit: LimitTracker,
15    accept_errors: bool,
16    experimental_fragment_arguments: bool,
17    last_end: u32,
18    /// Reusable scratch stack for building AST lists. List elements are
19    /// collected here and copied into the arena once, at the exact final
20    /// size: growing an arena vec strands every outgrown copy in the arena,
21    /// because parsing the elements allocates in between. Recursive descent
22    /// finishes nested lists in LIFO order, so all list types share this one
23    /// stack: a list records the stack length when it starts and drains
24    /// everything above that mark when it ends.
25    scratch: Vec<ScratchNode<'a>>,
26}
27
28/// An element of [`Parser::scratch`]; one variant per AST list type built
29/// through the scratch stack.
30enum ScratchNode<'a> {
31    Definition(Definition<'a>),
32    Selection(Selection<'a>),
33    Argument(Argument<'a>),
34    VariableDefinition(VariableDefinition<'a>),
35    FieldDefinition(FieldDefinition<'a>),
36    InputValueDefinition(InputValueDefinition<'a>),
37    Directive(Directive<'a>),
38}
39
40#[derive(Clone, Copy)]
41enum Constness {
42    Const,
43    NotConst,
44}
45
46const DEFAULT_RECURSION_LIMIT: usize = 500;
47
48impl<'a> Parser<'a> {
49    /// # Panics
50    ///
51    /// Panics if `input` is larger than 4 GiB: AST spans store `u32` offsets.
52    pub fn new(allocator: &'a Allocator, input: &'a str) -> Self {
53        assert!(
54            u32::try_from(input.len()).is_ok(),
55            "source text is too long for u32 spans (max 4 GiB): {} bytes",
56            input.len()
57        );
58        Self {
59            allocator,
60            input,
61            lexer: Lexer::new(input),
62            current_token: None,
63            errors: Vec::new(),
64            comments: Vec::new(),
65            recursion_limit: LimitTracker::new(DEFAULT_RECURSION_LIMIT),
66            accept_errors: true,
67            experimental_fragment_arguments: false,
68            last_end: 0,
69            scratch: Vec::new(),
70        }
71    }
72
73    pub fn recursion_limit(mut self, recursion_limit: usize) -> Self {
74        self.recursion_limit = LimitTracker::new(recursion_limit);
75        self
76    }
77
78    pub fn token_limit(mut self, token_limit: usize) -> Self {
79        self.lexer = self.lexer.with_limit(token_limit);
80        self
81    }
82
83    pub fn experimental_fragment_arguments(mut self, allow: bool) -> Self {
84        self.experimental_fragment_arguments = allow;
85        self
86    }
87
88    pub fn parse(mut self) -> Ast<'a, Document<'a>> {
89        let document = self.parse_document();
90        self.into_ast(document)
91    }
92
93    pub fn parse_selection_set(mut self) -> Ast<'a, SelectionSet<'a>> {
94        let selection_set = self.parse_selection_set_inner();
95        self.into_ast(selection_set)
96    }
97
98    pub fn parse_type(mut self) -> Ast<'a, Type<'a>> {
99        let ty = self.parse_type_inner().unwrap_or_else(|| {
100            let span = self.current_span();
101            self.err("expected a type");
102            Type::Missing(span)
103        });
104        self.into_ast(ty)
105    }
106
107    fn into_ast<T>(self, root: T) -> Ast<'a, T> {
108        let token_limit = self.lexer.limit_tracker;
109        Ast::new(self.input, root, self.errors, self.comments, self.recursion_limit, token_limit)
110    }
111
112    /// Marks the start of a new scratch-built list, pre-sizing the stack so
113    /// small parses pay for at most one scratch allocation.
114    fn scratch_mark(&mut self) -> usize {
115        if self.scratch.capacity() == 0 {
116            self.scratch.reserve(128);
117        }
118        self.scratch.len()
119    }
120
121    /// Moves the scratch elements above `mark` into an exact-size arena vec.
122    #[inline]
123    fn drain_scratch<T>(
124        &mut self,
125        mark: usize,
126        unwrap: impl FnMut(ScratchNode<'a>) -> T,
127    ) -> ArenaVec<'a, T> {
128        ArenaVec::from_iter_in(self.scratch.drain(mark..).map(unwrap), &self.allocator)
129    }
130
131    fn parse_document(&mut self) -> Document<'a> {
132        let start = self.current_start();
133        let mark = self.scratch_mark();
134
135        if self.peek().is_none_or(|kind| kind == TokenKind::Eof) {
136            self.err("Unexpected <EOF>.");
137        }
138
139        self.peek_while(|parser, kind| {
140            if kind == TokenKind::Eof {
141                return ControlFlow::Break(());
142            }
143
144            let before = parser.current_span();
145            if let Some(definition) = parser.parse_definition() {
146                parser.scratch.push(ScratchNode::Definition(definition));
147            } else {
148                parser.err_and_pop("expected a StringValue, Name or OperationDefinition");
149            }
150
151            if parser.current_span() == before && parser.peek() != Some(TokenKind::Eof) {
152                parser.bump();
153            }
154
155            ControlFlow::Continue(())
156        });
157
158        let definitions = self.drain_scratch(mark, |node| match node {
159            ScratchNode::Definition(definition) => definition,
160            _ => unreachable!("scratch stack discipline"),
161        });
162        Document { definitions, span: self.span_from(start) }
163    }
164
165    fn parse_definition(&mut self) -> Option<Definition<'a>> {
166        let description = self.parse_description_if_present();
167        let selector = self.peek_data()?;
168
169        let definition = match selector {
170            "directive" => {
171                let definition = self.parse_directive_definition(description);
172                Definition::Directive(ArenaBox::new_in(definition, &self.allocator))
173            }
174            "enum" => {
175                let definition = self.parse_enum_type_definition(description);
176                Definition::EnumType(ArenaBox::new_in(definition, &self.allocator))
177            }
178            "extend" => {
179                if description.is_some() {
180                    self.err(
181                        "Unexpected description, only GraphQL definitions support descriptions.",
182                    );
183                }
184                return self.parse_extension();
185            }
186            "fragment" => {
187                let definition = self.parse_fragment_definition(description);
188                Definition::Fragment(ArenaBox::new_in(definition, &self.allocator))
189            }
190            "input" => {
191                let definition = self.parse_input_object_type_definition(description);
192                Definition::InputObjectType(ArenaBox::new_in(definition, &self.allocator))
193            }
194            "interface" => {
195                let definition = self.parse_interface_type_definition(description);
196                Definition::InterfaceType(ArenaBox::new_in(definition, &self.allocator))
197            }
198            "type" => {
199                let definition = self.parse_object_type_definition(description);
200                Definition::ObjectType(ArenaBox::new_in(definition, &self.allocator))
201            }
202            "{" => {
203                if description.is_some() {
204                    self.err(
205                        "Unexpected description, descriptions are not supported on shorthand queries.",
206                    );
207                }
208                let definition = self.parse_operation_definition(description);
209                Definition::Operation(ArenaBox::new_in(definition, &self.allocator))
210            }
211            "query" | "mutation" | "subscription" => {
212                let definition = self.parse_operation_definition(description);
213                Definition::Operation(ArenaBox::new_in(definition, &self.allocator))
214            }
215            "scalar" => {
216                let definition = self.parse_scalar_type_definition(description);
217                Definition::ScalarType(ArenaBox::new_in(definition, &self.allocator))
218            }
219            "schema" => {
220                let definition = self.parse_schema_definition(description);
221                Definition::Schema(ArenaBox::new_in(definition, &self.allocator))
222            }
223            "union" => {
224                let definition = self.parse_union_type_definition(description);
225                Definition::UnionType(ArenaBox::new_in(definition, &self.allocator))
226            }
227            _ => {
228                if description.is_some() {
229                    self.err("expected a definition after this StringValue");
230                } else {
231                    self.err_and_pop("expected definition");
232                }
233                return None;
234            }
235        };
236
237        Some(definition)
238    }
239
240    fn parse_extension(&mut self) -> Option<Definition<'a>> {
241        let start = self.current_start();
242        self.expect_name_value("extend");
243
244        let definition = match self.peek_data() {
245            Some("schema") => {
246                let extension = self.parse_schema_extension_from(start);
247                Definition::SchemaExtension(ArenaBox::new_in(extension, &self.allocator))
248            }
249            Some("scalar") => {
250                let extension = self.parse_scalar_type_extension_from(start);
251                Definition::ScalarTypeExtension(ArenaBox::new_in(extension, &self.allocator))
252            }
253            Some("type") => {
254                let extension = self.parse_object_type_extension_from(start);
255                Definition::ObjectTypeExtension(ArenaBox::new_in(extension, &self.allocator))
256            }
257            Some("interface") => {
258                let extension = self.parse_interface_type_extension_from(start);
259                Definition::InterfaceTypeExtension(ArenaBox::new_in(extension, &self.allocator))
260            }
261            Some("union") => {
262                let extension = self.parse_union_type_extension_from(start);
263                Definition::UnionTypeExtension(ArenaBox::new_in(extension, &self.allocator))
264            }
265            Some("enum") => {
266                let extension = self.parse_enum_type_extension_from(start);
267                Definition::EnumTypeExtension(ArenaBox::new_in(extension, &self.allocator))
268            }
269            Some("input") => {
270                let extension = self.parse_input_object_type_extension_from(start);
271                Definition::InputObjectTypeExtension(ArenaBox::new_in(extension, &self.allocator))
272            }
273            Some("directive") => {
274                let extension = self.parse_directive_extension_from(start);
275                Definition::DirectiveExtension(ArenaBox::new_in(extension, &self.allocator))
276            }
277            _ => {
278                self.err("expected a valid extension");
279                return None;
280            }
281        };
282
283        Some(definition)
284    }
285
286    fn parse_operation_definition(
287        &mut self,
288        description: Option<ArenaBox<'a, StringValue<'a>>>,
289    ) -> OperationDefinition<'a> {
290        let start = self.definition_start(&description);
291
292        if self.peek() == Some(T!['{']) {
293            let selection_set = Some(self.parse_alloc_selection_set());
294            return OperationDefinition {
295                description,
296                operation_type: OperationType::Query,
297                name: None,
298                variable_definitions: None,
299                directives: ArenaVec::new_in(&self.allocator),
300                selection_set,
301                span: self.span_from(start),
302            };
303        }
304
305        let operation_type = self.parse_operation_type("expected Operation Type");
306
307        let name = if self.peek() == Some(TokenKind::Name) { self.parse_name() } else { None };
308        let variable_definitions = self.parse_variable_definitions_if_present();
309        let directives = self.parse_directives(Constness::NotConst);
310        let selection_set = self.parse_required_selection_set();
311
312        OperationDefinition {
313            description,
314            operation_type,
315            name,
316            variable_definitions,
317            directives,
318            selection_set,
319            span: self.span_from(start),
320        }
321    }
322
323    fn parse_fragment_definition(
324        &mut self,
325        description: Option<ArenaBox<'a, StringValue<'a>>>,
326    ) -> FragmentDefinition<'a> {
327        let start = self.definition_start(&description);
328        self.expect_name_value("fragment");
329        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
330
331        let variable_definitions = if self.experimental_fragment_arguments {
332            self.parse_variable_definitions_if_present()
333        } else {
334            None
335        };
336
337        let type_condition = self.parse_type_condition();
338        let directives = self.parse_directives(Constness::NotConst);
339        let selection_set = self.parse_required_selection_set();
340
341        FragmentDefinition {
342            description,
343            name,
344            variable_definitions,
345            type_condition,
346            directives,
347            selection_set,
348            span: self.span_from(start),
349        }
350    }
351
352    fn parse_alloc_selection_set(&mut self) -> ArenaBox<'a, SelectionSet<'a>> {
353        let selection_set = self.parse_selection_set_inner();
354        ArenaBox::new_in(selection_set, &self.allocator)
355    }
356
357    /// Parse a selection set that is required in this position. If the next
358    /// token is not `{`, records an error and returns `None`.
359    fn parse_required_selection_set(&mut self) -> Option<ArenaBox<'a, SelectionSet<'a>>> {
360        if self.peek() == Some(T!['{']) {
361            Some(self.parse_alloc_selection_set())
362        } else {
363            self.err("expected a Selection Set");
364            None
365        }
366    }
367
368    /// Parse an operation type keyword (`query`, `mutation`, or `subscription`),
369    /// consuming it. If none is present, records an error using `missing` and
370    /// falls back to `OperationType::Query`.
371    fn parse_operation_type(&mut self, missing: &str) -> OperationType {
372        match self.peek_data() {
373            Some("query") => {
374                self.bump();
375                OperationType::Query
376            }
377            Some("mutation") => {
378                self.bump();
379                OperationType::Mutation
380            }
381            Some("subscription") => {
382                self.bump();
383                OperationType::Subscription
384            }
385            _ => {
386                self.err(missing);
387                OperationType::Query
388            }
389        }
390    }
391
392    fn parse_selection_set_inner(&mut self) -> SelectionSet<'a> {
393        let start = self.current_start();
394        self.expect(T!['{'], "expected {");
395
396        let mark = self.scratch_mark();
397
398        self.peek_while(|parser, kind| match kind {
399            T!['}'] => {
400                if parser.scratch.len() == mark {
401                    parser.err("expected Selection");
402                }
403                parser.bump();
404                ControlFlow::Break(())
405            }
406            TokenKind::Eof => {
407                parser.err("expected }");
408                ControlFlow::Break(())
409            }
410            TokenKind::Name | T![...] if parser.recursion_limit.check_and_increment() => {
411                parser.limit_err("parser recursion limit reached");
412                ControlFlow::Break(())
413            }
414            TokenKind::Name | T![...] => {
415                let selection = parser.parse_selection();
416                parser.scratch.push(ScratchNode::Selection(selection));
417                parser.recursion_limit.decrement();
418                ControlFlow::Continue(())
419            }
420            _ => {
421                parser.err_and_pop("expected a Selection");
422                ControlFlow::Continue(())
423            }
424        });
425
426        let selections = self.drain_scratch(mark, |node| match node {
427            ScratchNode::Selection(selection) => selection,
428            _ => unreachable!("scratch stack discipline"),
429        });
430
431        SelectionSet { selections, span: self.span_from(start) }
432    }
433
434    fn parse_selection(&mut self) -> Selection<'a> {
435        if self.peek() == Some(T![...]) {
436            self.parse_fragment_selection()
437        } else {
438            let field = self.parse_field();
439            Selection::Field(ArenaBox::new_in(field, &self.allocator))
440        }
441    }
442
443    fn parse_fragment_selection(&mut self) -> Selection<'a> {
444        let start = self.current_start();
445        self.expect(T![...], "expected ...");
446
447        if self.peek_data() == Some("on") {
448            let type_condition = Some(self.parse_type_condition());
449            let directives = self.parse_directives(Constness::NotConst);
450            let selection_set = self.parse_required_selection_set();
451            return Selection::InlineFragment(ArenaBox::new_in(
452                InlineFragment {
453                    type_condition,
454                    directives,
455                    selection_set,
456                    span: self.span_from(start),
457                },
458                &self.allocator,
459            ));
460        }
461
462        if matches!(self.peek(), Some(T![@] | T!['{'])) {
463            let directives = self.parse_directives(Constness::NotConst);
464            let selection_set = self.parse_required_selection_set();
465            return Selection::InlineFragment(ArenaBox::new_in(
466                InlineFragment {
467                    type_condition: None,
468                    directives,
469                    selection_set,
470                    span: self.span_from(start),
471                },
472                &self.allocator,
473            ));
474        }
475
476        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
477        let arguments = if self.experimental_fragment_arguments {
478            self.parse_arguments_if_present(Constness::NotConst)
479        } else {
480            None
481        };
482        let directives = self.parse_directives(Constness::NotConst);
483        Selection::FragmentSpread(ArenaBox::new_in(
484            FragmentSpread { name, arguments, directives, span: self.span_from(start) },
485            &self.allocator,
486        ))
487    }
488
489    fn parse_field(&mut self) -> Field<'a> {
490        let start = self.current_start();
491        let first_name = self.parse_name().unwrap_or_else(|| self.missing_name());
492        let (alias, name) = if self.peek() == Some(T![:]) {
493            self.bump();
494            let name = self.parse_name().unwrap_or_else(|| self.missing_name());
495            (Some(first_name), name)
496        } else {
497            (None, first_name)
498        };
499
500        let arguments = self.parse_arguments_if_present(Constness::NotConst);
501        let directives = self.parse_directives(Constness::NotConst);
502        let selection_set = if self.peek() == Some(T!['{']) {
503            Some(self.parse_alloc_selection_set())
504        } else {
505            None
506        };
507
508        Field { alias, name, arguments, directives, selection_set, span: self.span_from(start) }
509    }
510
511    fn parse_arguments_if_present(&mut self, constness: Constness) -> Option<Arguments<'a>> {
512        if self.peek() != Some(T!['(']) {
513            return None;
514        }
515
516        let open_start = self.current_start();
517        self.bump();
518        let mark = self.scratch_mark();
519        self.peek_while(|parser, kind| match kind {
520            T![')'] => {
521                parser.bump();
522                ControlFlow::Break(())
523            }
524            TokenKind::Name => {
525                let argument = parser.parse_argument(constness);
526                parser.scratch.push(ScratchNode::Argument(argument));
527                ControlFlow::Continue(())
528            }
529            TokenKind::Eof => {
530                parser.err("expected )");
531                ControlFlow::Break(())
532            }
533            _ => {
534                parser.err_and_pop("expected an Argument");
535                ControlFlow::Continue(())
536            }
537        });
538        let items = self.drain_scratch(mark, |node| match node {
539            ScratchNode::Argument(argument) => argument,
540            _ => unreachable!("scratch stack discipline"),
541        });
542        Some(Arguments { items, span: self.span_from(open_start) })
543    }
544
545    fn parse_argument(&mut self, constness: Constness) -> Argument<'a> {
546        let start = self.current_start();
547        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
548        let value = if self.peek() == Some(T![:]) {
549            self.bump();
550            Some(self.parse_value(constness, false))
551        } else {
552            self.err("expected :");
553            None
554        };
555        Argument { name, value, span: self.span_from(start) }
556    }
557
558    fn parse_variable_definitions_if_present(&mut self) -> Option<VariableDefinitions<'a>> {
559        if self.peek() != Some(T!['(']) {
560            return None;
561        }
562
563        let open_start = self.current_start();
564        self.bump();
565        let mark = self.scratch_mark();
566        self.peek_while(|parser, kind| match kind {
567            T![')'] => {
568                if parser.scratch.len() == mark {
569                    parser.err("expected a Variable Definition");
570                }
571                parser.bump();
572                ControlFlow::Break(())
573            }
574            T![$] | TokenKind::StringValue => {
575                let definition = parser.parse_variable_definition();
576                parser.scratch.push(ScratchNode::VariableDefinition(definition));
577                ControlFlow::Continue(())
578            }
579            TokenKind::Eof => {
580                parser.err("expected )");
581                ControlFlow::Break(())
582            }
583            _ => {
584                parser.err_and_pop("expected a Variable Definition");
585                ControlFlow::Continue(())
586            }
587        });
588        let items = self.drain_scratch(mark, |node| match node {
589            ScratchNode::VariableDefinition(definition) => definition,
590            _ => unreachable!("scratch stack discipline"),
591        });
592        Some(VariableDefinitions { items, span: self.span_from(open_start) })
593    }
594
595    fn parse_variable_definition(&mut self) -> VariableDefinition<'a> {
596        let start = self.current_start();
597        let description = self.parse_description_if_present();
598        let variable = self.parse_variable().unwrap_or_else(|| self.missing_variable());
599        let mut ty = None;
600        let mut default_value = None;
601        let mut directives = ArenaVec::new_in(&self.allocator);
602
603        if self.peek() == Some(T![:]) {
604            self.bump();
605            ty = self.parse_type_inner();
606            default_value = self.parse_default_value_if_present();
607            directives = self.parse_directives(Constness::Const);
608        } else {
609            self.err("expected a Name");
610        }
611
612        VariableDefinition {
613            description,
614            variable,
615            ty,
616            default_value,
617            directives,
618            span: self.span_from(start),
619        }
620    }
621
622    fn parse_variable(&mut self) -> Option<Variable<'a>> {
623        let start = self.current_start();
624        if self.peek() != Some(T![$]) {
625            self.err("expected a Variable");
626            return None;
627        }
628        self.bump();
629        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
630        Some(Variable { name, span: self.span_from(start) })
631    }
632
633    fn parse_directives(&mut self, constness: Constness) -> ArenaVec<'a, Directive<'a>> {
634        if self.peek() != Some(T![@]) {
635            return ArenaVec::new_in(&self.allocator);
636        }
637
638        let mark = self.scratch_mark();
639        while self.peek() == Some(T![@]) {
640            let directive = self.parse_directive(constness);
641            self.scratch.push(ScratchNode::Directive(directive));
642        }
643        self.drain_scratch(mark, |node| match node {
644            ScratchNode::Directive(directive) => directive,
645            _ => unreachable!("scratch stack discipline"),
646        })
647    }
648
649    fn parse_directive(&mut self, constness: Constness) -> Directive<'a> {
650        let start = self.current_start();
651        self.expect(T![@], "expected @ symbol");
652        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
653        let arguments = self.parse_arguments_if_present(constness);
654        Directive { name, arguments, span: self.span_from(start) }
655    }
656
657    fn parse_value(&mut self, constness: Constness, pop_on_error: bool) -> Value<'a> {
658        match self.peek() {
659            Some(T![$]) => {
660                if matches!(constness, Constness::Const) {
661                    self.err("unexpected variable value in a Const context");
662                }
663                match self.parse_variable() {
664                    Some(variable) => Value::Variable(ArenaBox::new_in(variable, &self.allocator)),
665                    None => Value::Missing(self.current_span()),
666                }
667            }
668            Some(TokenKind::Int) => self.parse_int_value(),
669            Some(TokenKind::Float) => self.parse_float_value(),
670            Some(TokenKind::StringValue) => match self.parse_string_value() {
671                Some(value) => Value::String(ArenaBox::new_in(value, &self.allocator)),
672                None => Value::Missing(self.current_span()),
673            },
674            Some(TokenKind::Name) => self.parse_name_value(),
675            Some(T!['[']) => self.parse_list_value(constness),
676            Some(T!['{']) => self.parse_object_value(constness),
677            _ => {
678                let message = "expected a valid Value";
679                if pop_on_error {
680                    self.err_and_pop(message);
681                } else {
682                    self.err(message);
683                }
684                Value::Missing(self.current_span())
685            }
686        }
687    }
688
689    fn parse_int_value(&mut self) -> Value<'a> {
690        let token = self.bump().expect("peeked int token must be available");
691        Value::Int(ArenaBox::new_in(
692            IntValue { raw: token.data(), span: token_span(&token) },
693            &self.allocator,
694        ))
695    }
696
697    fn parse_float_value(&mut self) -> Value<'a> {
698        let token = self.bump().expect("peeked float token must be available");
699        Value::Float(ArenaBox::new_in(
700            FloatValue { raw: token.data(), span: token_span(&token) },
701            &self.allocator,
702        ))
703    }
704
705    fn parse_name_value(&mut self) -> Value<'a> {
706        let Some(name) = self.parse_name() else {
707            return Value::Missing(self.current_span());
708        };
709        match name.value {
710            "true" => Value::Boolean(ArenaBox::new_in(
711                BooleanValue { value: true, span: name.span },
712                &self.allocator,
713            )),
714            "false" => Value::Boolean(ArenaBox::new_in(
715                BooleanValue { value: false, span: name.span },
716                &self.allocator,
717            )),
718            "null" => Value::Null(ArenaBox::new_in(NullValue { span: name.span }, &self.allocator)),
719            _ => Value::Enum(ArenaBox::new_in(EnumValue { name }, &self.allocator)),
720        }
721    }
722
723    fn parse_list_value(&mut self, constness: Constness) -> Value<'a> {
724        let start = self.current_start();
725        self.expect(T!['['], "expected [");
726        let mut values = ArenaVec::new_in(&self.allocator);
727
728        self.peek_while(|parser, kind| match kind {
729            T![']'] => {
730                parser.bump();
731                ControlFlow::Break(())
732            }
733            TokenKind::Eof => {
734                parser.err("expected ]");
735                ControlFlow::Break(())
736            }
737            _ if parser.recursion_limit.check_and_increment() => {
738                parser.limit_err("parser recursion limit reached");
739                ControlFlow::Break(())
740            }
741            _ => {
742                values.push(parser.parse_value(constness, true));
743                parser.recursion_limit.decrement();
744                ControlFlow::Continue(())
745            }
746        });
747
748        Value::List(ArenaBox::new_in(
749            ListValue { values, span: self.span_from(start) },
750            &self.allocator,
751        ))
752    }
753
754    fn parse_object_value(&mut self, constness: Constness) -> Value<'a> {
755        let start = self.current_start();
756        self.expect(T!['{'], "expected {");
757        let mut fields = ArenaVec::new_in(&self.allocator);
758
759        self.peek_while(|parser, kind| match kind {
760            T!['}'] => {
761                parser.bump();
762                ControlFlow::Break(())
763            }
764            TokenKind::Name if parser.recursion_limit.check_and_increment() => {
765                parser.limit_err("parser recursion limit reached");
766                ControlFlow::Break(())
767            }
768            TokenKind::Name => {
769                fields.push(parser.parse_object_field(constness));
770                parser.recursion_limit.decrement();
771                ControlFlow::Continue(())
772            }
773            TokenKind::Eof => {
774                parser.err("expected }");
775                ControlFlow::Break(())
776            }
777            _ => {
778                parser.err_and_pop("expected Object Field");
779                ControlFlow::Continue(())
780            }
781        });
782
783        Value::Object(ArenaBox::new_in(
784            ObjectValue { fields, span: self.span_from(start) },
785            &self.allocator,
786        ))
787    }
788
789    fn parse_object_field(&mut self, constness: Constness) -> ObjectField<'a> {
790        let start = self.current_start();
791        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
792        let value = if self.peek() == Some(T![:]) {
793            self.bump();
794            Some(self.parse_value(constness, true))
795        } else {
796            self.err("expected :");
797            None
798        };
799        ObjectField { name, value, span: self.span_from(start) }
800    }
801
802    fn parse_type_inner(&mut self) -> Option<Type<'a>> {
803        let start = self.current_start();
804        let mut ty = match self.peek() {
805            Some(T!['[']) => {
806                self.bump();
807                if self.recursion_limit.check_and_increment() {
808                    self.limit_err("parser recursion limit reached");
809                    return Some(Type::Missing(self.span_from(start)));
810                }
811                let inner =
812                    self.parse_type_inner().unwrap_or_else(|| Type::Missing(self.current_span()));
813                self.recursion_limit.decrement();
814                self.expect(T![']'], "expected ]");
815                Type::List(ArenaBox::new_in(
816                    ListType { ty: inner, span: self.span_from(start) },
817                    &self.allocator,
818                ))
819            }
820            Some(TokenKind::Name) => {
821                let name = self.parse_name().unwrap_or_else(|| self.missing_name());
822                Type::Named(ArenaBox::new_in(NamedType { name }, &self.allocator))
823            }
824            Some(_) => {
825                self.err("expected a type");
826                return None;
827            }
828            None => return None,
829        };
830
831        if self.peek() == Some(T![!]) {
832            self.bump();
833            ty = Type::NonNull(ArenaBox::new_in(
834                NonNullType { ty, span: self.span_from(start) },
835                &self.allocator,
836            ));
837        }
838
839        Some(ty)
840    }
841
842    fn parse_named_type(&mut self) -> Option<NamedType<'a>> {
843        self.parse_name().map(|name| NamedType { name })
844    }
845
846    fn parse_schema_definition(
847        &mut self,
848        description: Option<ArenaBox<'a, StringValue<'a>>>,
849    ) -> SchemaDefinition<'a> {
850        let start = self.definition_start(&description);
851        self.expect_name_value("schema");
852        let directives = self.parse_directives(Constness::Const);
853        let root_operations = self.parse_root_operation_types_if_present();
854        SchemaDefinition { description, directives, root_operations, span: self.span_from(start) }
855    }
856
857    fn parse_schema_extension_from(&mut self, start: u32) -> SchemaExtension<'a> {
858        self.expect_name_value("schema");
859        let directives = self.parse_directives(Constness::Const);
860        let root_operations = self.parse_root_operation_types_if_present();
861        if directives.is_empty() && root_operations.is_empty() {
862            self.err("expected Directives or Root Operation Types");
863        }
864        SchemaExtension { directives, root_operations, span: self.span_from(start) }
865    }
866
867    fn parse_root_operation_types_if_present(
868        &mut self,
869    ) -> ArenaVec<'a, RootOperationTypeDefinition<'a>> {
870        if self.peek() != Some(T!['{']) {
871            return ArenaVec::new_in(&self.allocator);
872        }
873
874        self.bump();
875        let mut root_operations = ArenaVec::new_in(&self.allocator);
876        self.peek_while(|parser, kind| match kind {
877            T!['}'] => {
878                parser.bump();
879                ControlFlow::Break(())
880            }
881            TokenKind::Name => {
882                root_operations.push(parser.parse_root_operation_type_definition());
883                ControlFlow::Continue(())
884            }
885            TokenKind::Eof => {
886                parser.err("expected }");
887                ControlFlow::Break(())
888            }
889            _ => {
890                parser.err_and_pop("expected Root Operation Type Definition");
891                ControlFlow::Continue(())
892            }
893        });
894        root_operations
895    }
896
897    fn parse_root_operation_type_definition(&mut self) -> RootOperationTypeDefinition<'a> {
898        let start = self.current_start();
899        let operation_type = self.parse_operation_type("expected an Operation Type");
900        self.expect(T![:], "expected :");
901        let named_type = self.parse_named_type().unwrap_or_else(|| self.missing_named_type());
902        RootOperationTypeDefinition { operation_type, named_type, span: self.span_from(start) }
903    }
904
905    fn parse_directive_extension_from(&mut self, start: u32) -> DirectiveExtension<'a> {
906        self.expect_name_value("directive");
907        self.expect(T![@], "expected @ symbol");
908        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
909        let directives = self.parse_directives(Constness::Const);
910        if directives.is_empty() {
911            self.err("expected Directives");
912        }
913        DirectiveExtension { name, directives, span: self.span_from(start) }
914    }
915
916    fn parse_directive_definition(
917        &mut self,
918        description: Option<ArenaBox<'a, StringValue<'a>>>,
919    ) -> DirectiveDefinition<'a> {
920        let start = self.definition_start(&description);
921        self.expect_name_value("directive");
922        self.expect(T![@], "expected @ symbol");
923        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
924        let arguments = self.parse_arguments_definition_if_present();
925        let directives = self.parse_directives(Constness::Const);
926        let repeatable = if self.peek_data() == Some("repeatable") {
927            self.bump();
928            true
929        } else {
930            false
931        };
932        self.expect_name_value("on");
933        let locations = self.parse_directive_locations();
934
935        DirectiveDefinition {
936            description,
937            name,
938            arguments,
939            directives,
940            repeatable,
941            locations,
942            span: self.span_from(start),
943        }
944    }
945
946    fn parse_directive_locations(&mut self) -> ArenaVec<'a, DirectiveLocation<'a>> {
947        if self.peek() == Some(T![|]) {
948            self.bump();
949        }
950
951        let mut locations = ArenaVec::new_in(&self.allocator);
952        loop {
953            if let Some(token) = self.peek_token().copied()
954                && token.kind() == TokenKind::Name
955            {
956                self.bump();
957                locations.push(DirectiveLocation { name: token.data(), span: token_span(&token) });
958            } else {
959                self.err("expected valid Directive Location");
960                break;
961            }
962
963            if self.peek() == Some(T![|]) {
964                self.bump();
965            } else {
966                break;
967            }
968        }
969        locations
970    }
971
972    fn parse_scalar_type_definition(
973        &mut self,
974        description: Option<ArenaBox<'a, StringValue<'a>>>,
975    ) -> ScalarTypeDefinition<'a> {
976        let start = self.definition_start(&description);
977        self.expect_name_value("scalar");
978        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
979        let directives = self.parse_directives(Constness::Const);
980        ScalarTypeDefinition { description, name, directives, span: self.span_from(start) }
981    }
982
983    fn parse_scalar_type_extension_from(&mut self, start: u32) -> ScalarTypeExtension<'a> {
984        self.expect_name_value("scalar");
985        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
986        let directives = self.parse_directives(Constness::Const);
987        if directives.is_empty() {
988            self.err("expected Directives");
989        }
990        ScalarTypeExtension { name, directives, span: self.span_from(start) }
991    }
992
993    fn parse_object_type_definition(
994        &mut self,
995        description: Option<ArenaBox<'a, StringValue<'a>>>,
996    ) -> ObjectTypeDefinition<'a> {
997        let start = self.definition_start(&description);
998        self.expect_name_value("type");
999        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
1000        let implements = self.parse_implements_interfaces_if_present();
1001        let directives = self.parse_directives(Constness::Const);
1002        let fields = self.parse_fields_definition_if_present();
1003        ObjectTypeDefinition {
1004            description,
1005            name,
1006            implements,
1007            directives,
1008            fields,
1009            span: self.span_from(start),
1010        }
1011    }
1012
1013    fn parse_object_type_extension_from(&mut self, start: u32) -> ObjectTypeExtension<'a> {
1014        self.expect_name_value("type");
1015        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
1016        let implements = self.parse_implements_interfaces_if_present();
1017        let directives = self.parse_directives(Constness::Const);
1018        let fields = self.parse_fields_definition_if_present();
1019        if implements.is_none() && directives.is_empty() && fields.is_none() {
1020            self.err("expected Implements Interfaces, Directives, or Fields Definition");
1021        }
1022        ObjectTypeExtension { name, implements, directives, fields, span: self.span_from(start) }
1023    }
1024
1025    fn parse_interface_type_definition(
1026        &mut self,
1027        description: Option<ArenaBox<'a, StringValue<'a>>>,
1028    ) -> InterfaceTypeDefinition<'a> {
1029        let start = self.definition_start(&description);
1030        self.expect_name_value("interface");
1031        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
1032        let implements = self.parse_implements_interfaces_if_present();
1033        let directives = self.parse_directives(Constness::Const);
1034        let fields = self.parse_fields_definition_if_present();
1035        InterfaceTypeDefinition {
1036            description,
1037            name,
1038            implements,
1039            directives,
1040            fields,
1041            span: self.span_from(start),
1042        }
1043    }
1044
1045    fn parse_interface_type_extension_from(&mut self, start: u32) -> InterfaceTypeExtension<'a> {
1046        self.expect_name_value("interface");
1047        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
1048        let implements = self.parse_implements_interfaces_if_present();
1049        let directives = self.parse_directives(Constness::Const);
1050        let fields = self.parse_fields_definition_if_present();
1051        if implements.is_none() && directives.is_empty() && fields.is_none() {
1052            self.err("expected an Implements Interfaces, Directives, or a Fields Definition");
1053        }
1054        InterfaceTypeExtension { name, implements, directives, fields, span: self.span_from(start) }
1055    }
1056
1057    fn parse_implements_interfaces_if_present(&mut self) -> Option<ImplementsInterfaces<'a>> {
1058        if self.peek_data() != Some("implements") {
1059            return None;
1060        }
1061
1062        let start = self.current_start();
1063        self.bump();
1064        if self.peek() == Some(T![&]) {
1065            self.bump();
1066        }
1067
1068        let mut interfaces = ArenaVec::new_in(&self.allocator);
1069        loop {
1070            if let Some(named_type) = self.parse_named_type() {
1071                interfaces.push(named_type);
1072            } else {
1073                self.err("expected Implements Interface");
1074                break;
1075            }
1076
1077            if self.peek() == Some(T![&]) {
1078                self.bump();
1079            } else {
1080                break;
1081            }
1082        }
1083        Some(ImplementsInterfaces { interfaces, span: self.span_from(start) })
1084    }
1085
1086    fn parse_fields_definition_if_present(&mut self) -> Option<FieldsDefinition<'a>> {
1087        if self.peek() != Some(T!['{']) {
1088            return None;
1089        }
1090
1091        let open_start = self.current_start();
1092        self.bump();
1093        let mark = self.scratch_mark();
1094        self.peek_while(|parser, kind| match kind {
1095            T!['}'] => {
1096                if parser.scratch.len() == mark {
1097                    parser.err("expected Field Definition");
1098                }
1099                parser.bump();
1100                ControlFlow::Break(())
1101            }
1102            TokenKind::Name | TokenKind::StringValue => {
1103                let field = parser.parse_field_definition();
1104                parser.scratch.push(ScratchNode::FieldDefinition(field));
1105                ControlFlow::Continue(())
1106            }
1107            TokenKind::Eof => {
1108                parser.err("expected }");
1109                ControlFlow::Break(())
1110            }
1111            _ => {
1112                parser.err_and_pop("expected a Field Definition");
1113                ControlFlow::Continue(())
1114            }
1115        });
1116        let fields = self.drain_scratch(mark, |node| match node {
1117            ScratchNode::FieldDefinition(field) => field,
1118            _ => unreachable!("scratch stack discipline"),
1119        });
1120        Some(FieldsDefinition { fields, span: self.span_from(open_start) })
1121    }
1122
1123    fn parse_field_definition(&mut self) -> FieldDefinition<'a> {
1124        let start = self.current_start();
1125        let description = self.parse_description_if_present();
1126        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
1127        let arguments = self.parse_arguments_definition_if_present();
1128        let ty = if self.peek() == Some(T![:]) {
1129            self.bump();
1130            self.parse_type_inner()
1131        } else {
1132            self.err("expected a Type");
1133            None
1134        };
1135        let directives = self.parse_directives(Constness::Const);
1136        FieldDefinition {
1137            description,
1138            name,
1139            arguments,
1140            ty,
1141            directives,
1142            span: self.span_from(start),
1143        }
1144    }
1145
1146    fn parse_arguments_definition_if_present(&mut self) -> Option<ArgumentsDefinition<'a>> {
1147        if self.peek() != Some(T!['(']) {
1148            return None;
1149        }
1150
1151        let open_start = self.current_start();
1152        self.bump();
1153        let mark = self.scratch_mark();
1154        self.peek_while(|parser, kind| match kind {
1155            T![')'] => {
1156                parser.bump();
1157                ControlFlow::Break(())
1158            }
1159            TokenKind::Name | TokenKind::StringValue => {
1160                let definition = parser.parse_input_value_definition();
1161                parser.scratch.push(ScratchNode::InputValueDefinition(definition));
1162                ControlFlow::Continue(())
1163            }
1164            TokenKind::Eof => {
1165                parser.err("expected )");
1166                ControlFlow::Break(())
1167            }
1168            _ => {
1169                parser.err_and_pop("expected an Argument Definition");
1170                ControlFlow::Continue(())
1171            }
1172        });
1173        let items = self.drain_scratch(mark, |node| match node {
1174            ScratchNode::InputValueDefinition(definition) => definition,
1175            _ => unreachable!("scratch stack discipline"),
1176        });
1177        Some(ArgumentsDefinition { items, span: self.span_from(open_start) })
1178    }
1179
1180    fn parse_input_value_definition(&mut self) -> InputValueDefinition<'a> {
1181        let start = self.current_start();
1182        let description = self.parse_description_if_present();
1183        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
1184        let ty = if self.peek() == Some(T![:]) {
1185            self.bump();
1186            self.parse_type_inner()
1187        } else {
1188            self.err("expected a Type");
1189            None
1190        };
1191        let default_value = self.parse_default_value_if_present();
1192        let directives = self.parse_directives(Constness::Const);
1193        InputValueDefinition {
1194            description,
1195            name,
1196            ty,
1197            default_value,
1198            directives,
1199            span: self.span_from(start),
1200        }
1201    }
1202
1203    fn parse_union_type_definition(
1204        &mut self,
1205        description: Option<ArenaBox<'a, StringValue<'a>>>,
1206    ) -> UnionTypeDefinition<'a> {
1207        let start = self.definition_start(&description);
1208        self.expect_name_value("union");
1209        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
1210        let directives = self.parse_directives(Constness::Const);
1211        let members = self.parse_union_members_if_present();
1212        UnionTypeDefinition { description, name, directives, members, span: self.span_from(start) }
1213    }
1214
1215    fn parse_union_type_extension_from(&mut self, start: u32) -> UnionTypeExtension<'a> {
1216        self.expect_name_value("union");
1217        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
1218        let directives = self.parse_directives(Constness::Const);
1219        let members = self.parse_union_members_if_present();
1220        if directives.is_empty() && members.is_none() {
1221            self.err("expected Directives or Union Member Types");
1222        }
1223        UnionTypeExtension { name, directives, members, span: self.span_from(start) }
1224    }
1225
1226    fn parse_union_members_if_present(&mut self) -> Option<UnionMemberTypes<'a>> {
1227        if self.peek() != Some(T![=]) {
1228            return None;
1229        }
1230
1231        let start = self.current_start();
1232        self.bump();
1233        if self.peek() == Some(T![|]) {
1234            self.bump();
1235        }
1236
1237        let mut members = ArenaVec::new_in(&self.allocator);
1238        loop {
1239            if let Some(member) = self.parse_named_type() {
1240                members.push(member);
1241            } else {
1242                self.err("expected Union Member Type");
1243                break;
1244            }
1245
1246            if self.peek() == Some(T![|]) {
1247                self.bump();
1248            } else {
1249                break;
1250            }
1251        }
1252        Some(UnionMemberTypes { members, span: self.span_from(start) })
1253    }
1254
1255    fn parse_enum_type_definition(
1256        &mut self,
1257        description: Option<ArenaBox<'a, StringValue<'a>>>,
1258    ) -> EnumTypeDefinition<'a> {
1259        let start = self.definition_start(&description);
1260        self.expect_name_value("enum");
1261        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
1262        let directives = self.parse_directives(Constness::Const);
1263        let values = self.parse_enum_values_definition_if_present();
1264        EnumTypeDefinition { description, name, directives, values, span: self.span_from(start) }
1265    }
1266
1267    fn parse_enum_type_extension_from(&mut self, start: u32) -> EnumTypeExtension<'a> {
1268        self.expect_name_value("enum");
1269        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
1270        let directives = self.parse_directives(Constness::Const);
1271        let values = self.parse_enum_values_definition_if_present();
1272        if directives.is_empty() && values.is_none() {
1273            self.err("expected Directives or Enum Values Definition");
1274        }
1275        EnumTypeExtension { name, directives, values, span: self.span_from(start) }
1276    }
1277
1278    fn parse_enum_values_definition_if_present(&mut self) -> Option<EnumValuesDefinition<'a>> {
1279        if self.peek() != Some(T!['{']) {
1280            return None;
1281        }
1282
1283        let open_start = self.current_start();
1284        self.bump();
1285        let mut values = ArenaVec::new_in(&self.allocator);
1286        self.peek_while(|parser, kind| match kind {
1287            T!['}'] => {
1288                if values.is_empty() {
1289                    parser.err("expected Enum Value Definition");
1290                }
1291                parser.bump();
1292                ControlFlow::Break(())
1293            }
1294            TokenKind::Name | TokenKind::StringValue => {
1295                values.push(parser.parse_enum_value_definition());
1296                ControlFlow::Continue(())
1297            }
1298            TokenKind::Eof => {
1299                parser.err("expected }");
1300                ControlFlow::Break(())
1301            }
1302            _ => {
1303                parser.err_and_pop("expected an Enum Value Definition");
1304                ControlFlow::Continue(())
1305            }
1306        });
1307        Some(EnumValuesDefinition { values, span: self.span_from(open_start) })
1308    }
1309
1310    fn parse_enum_value_definition(&mut self) -> EnumValueDefinition<'a> {
1311        let start = self.current_start();
1312        let description = self.parse_description_if_present();
1313        let value = EnumValue { name: self.parse_name().unwrap_or_else(|| self.missing_name()) };
1314        if matches!(value.name.as_str(), "true" | "false" | "null") {
1315            self.err("invalid Enum Value");
1316        }
1317        let directives = self.parse_directives(Constness::Const);
1318        EnumValueDefinition { description, value, directives, span: self.span_from(start) }
1319    }
1320
1321    fn parse_input_object_type_definition(
1322        &mut self,
1323        description: Option<ArenaBox<'a, StringValue<'a>>>,
1324    ) -> InputObjectTypeDefinition<'a> {
1325        let start = self.definition_start(&description);
1326        self.expect_name_value("input");
1327        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
1328        let directives = self.parse_directives(Constness::Const);
1329        let fields = self.parse_input_fields_definition_if_present();
1330        InputObjectTypeDefinition {
1331            description,
1332            name,
1333            directives,
1334            fields,
1335            span: self.span_from(start),
1336        }
1337    }
1338
1339    fn parse_input_object_type_extension_from(
1340        &mut self,
1341        start: u32,
1342    ) -> InputObjectTypeExtension<'a> {
1343        self.expect_name_value("input");
1344        let name = self.parse_name().unwrap_or_else(|| self.missing_name());
1345        let directives = self.parse_directives(Constness::Const);
1346        let fields = self.parse_input_fields_definition_if_present();
1347        if directives.is_empty() && fields.is_none() {
1348            self.err("expected Directives or Input Fields Definition");
1349        }
1350        InputObjectTypeExtension { name, directives, fields, span: self.span_from(start) }
1351    }
1352
1353    fn parse_input_fields_definition_if_present(&mut self) -> Option<InputFieldsDefinition<'a>> {
1354        if self.peek() != Some(T!['{']) {
1355            return None;
1356        }
1357
1358        let open_start = self.current_start();
1359        self.bump();
1360        let mark = self.scratch_mark();
1361        self.peek_while(|parser, kind| match kind {
1362            T!['}'] => {
1363                if parser.scratch.len() == mark {
1364                    parser.err("expected an Input Value Definition");
1365                }
1366                parser.bump();
1367                ControlFlow::Break(())
1368            }
1369            TokenKind::Name | TokenKind::StringValue => {
1370                let field = parser.parse_input_value_definition();
1371                parser.scratch.push(ScratchNode::InputValueDefinition(field));
1372                ControlFlow::Continue(())
1373            }
1374            TokenKind::Eof => {
1375                parser.err("expected }");
1376                ControlFlow::Break(())
1377            }
1378            _ => {
1379                parser.err_and_pop("expected an Input Value Definition");
1380                ControlFlow::Continue(())
1381            }
1382        });
1383        let fields = self.drain_scratch(mark, |node| match node {
1384            ScratchNode::InputValueDefinition(field) => field,
1385            _ => unreachable!("scratch stack discipline"),
1386        });
1387        Some(InputFieldsDefinition { fields, span: self.span_from(open_start) })
1388    }
1389
1390    fn parse_description_if_present(&mut self) -> Option<ArenaBox<'a, StringValue<'a>>> {
1391        if self.peek() == Some(TokenKind::StringValue) {
1392            let value = self.parse_string_value()?;
1393            Some(ArenaBox::new_in(value, &self.allocator))
1394        } else {
1395            None
1396        }
1397    }
1398
1399    /// The span start of a definition: the start of its already-parsed
1400    /// description if it has one, otherwise the start of the current token.
1401    fn definition_start(&mut self, description: &Option<ArenaBox<'a, StringValue<'a>>>) -> u32 {
1402        description.as_ref().map_or_else(|| self.current_start(), |value| value.span.start)
1403    }
1404
1405    fn parse_string_value(&mut self) -> Option<StringValue<'a>> {
1406        let token = self.bump()?;
1407        let raw = token.data();
1408        let block = raw.starts_with(r#"""""#);
1409        let value = if block {
1410            let content = raw
1411                .strip_prefix(r#"""""#)
1412                .and_then(|value| value.strip_suffix(r#"""""#))
1413                .unwrap_or(raw);
1414            if content.contains('\r') {
1415                self.allocator.alloc_str(&normalize_block_string(raw))
1416            } else {
1417                // No line endings to normalize: borrow from the source text.
1418                content
1419            }
1420        } else {
1421            // Strip exactly one quote from each end: `trim_matches` would also
1422            // eat a trailing escaped quote (`"abc\""` must keep its `"`).
1423            let content =
1424                raw.strip_prefix('"').and_then(|value| value.strip_suffix('"')).unwrap_or(raw);
1425            if content.contains('\\') {
1426                self.allocator.alloc_str(&unescape_string(content))
1427            } else {
1428                // No escape sequences: borrow from the source text.
1429                content
1430            }
1431        };
1432        Some(StringValue { raw, value, block, span: token_span(&token) })
1433    }
1434
1435    fn parse_name(&mut self) -> Option<Name<'a>> {
1436        if self.peek()? != TokenKind::Name {
1437            self.err("expected a Name");
1438            return None;
1439        }
1440        let token = self.bump().expect("peeked Name token must be available");
1441        Some(Name { value: token.data(), span: token_span(&token) })
1442    }
1443
1444    fn expect_name_value(&mut self, expected: &str) {
1445        if self.peek_data() == Some(expected) {
1446            self.bump();
1447        } else {
1448            self.err(&format!("expected {expected}"));
1449        }
1450    }
1451
1452    fn expect(&mut self, token: TokenKind, message: &str) {
1453        if self.peek() == Some(token) {
1454            self.bump();
1455        } else {
1456            self.err(message);
1457        }
1458    }
1459
1460    /// `on NamedType`. The `on` keyword is required;
1461    /// on error recovery the condition's type is synthesized as missing and the span collapses.
1462    fn parse_type_condition(&mut self) -> TypeCondition<'a> {
1463        let start = self.current_start();
1464        self.expect_name_value("on");
1465        let named_type = self.parse_named_type().unwrap_or_else(|| self.missing_named_type());
1466        TypeCondition { named_type, span: self.span_from(start) }
1467    }
1468
1469    /// `= Value[Const]`, when present.
1470    fn parse_default_value_if_present(&mut self) -> Option<DefaultValue<'a>> {
1471        if self.peek() != Some(T![=]) {
1472            return None;
1473        }
1474        let start = self.current_start();
1475        self.bump();
1476        let value = self.parse_value(Constness::Const, false);
1477        Some(DefaultValue { value, span: self.span_from(start) })
1478    }
1479
1480    fn missing_name(&self) -> Name<'a> {
1481        Name { value: "", span: Span::new(self.last_end, self.last_end) }
1482    }
1483
1484    fn missing_named_type(&self) -> NamedType<'a> {
1485        NamedType { name: self.missing_name() }
1486    }
1487
1488    fn missing_variable(&self) -> Variable<'a> {
1489        Variable { name: self.missing_name(), span: Span::new(self.last_end, self.last_end) }
1490    }
1491
1492    fn limit_err<S: Into<String>>(&mut self, message: S) {
1493        let index = if let Some(token) = self.peek_token() {
1494            token.index()
1495        } else {
1496            self.last_end as usize
1497        };
1498        self.push_err(Error::limit(message, index));
1499        self.accept_errors = false;
1500    }
1501
1502    fn err(&mut self, message: &str) {
1503        let Some(token) = self.peek_token().copied() else {
1504            return;
1505        };
1506        let err = if token.kind() == TokenKind::Eof {
1507            Error::eof(message, token.index())
1508        } else {
1509            Error::with_loc(message, token.data().to_string(), token.index())
1510        };
1511        self.push_err(err);
1512    }
1513
1514    fn err_and_pop(&mut self, message: &str) {
1515        let Some(token) = self.bump() else {
1516            return;
1517        };
1518        let err = if token.kind() == TokenKind::Eof {
1519            Error::eof(message, token.index())
1520        } else {
1521            Error::with_loc(message, token.data().to_string(), token.index())
1522        };
1523        self.push_err(err);
1524    }
1525
1526    fn push_err(&mut self, err: Error) {
1527        if self.accept_errors {
1528            self.errors.push(err);
1529        }
1530    }
1531
1532    fn peek_while(&mut self, mut run: impl FnMut(&mut Parser<'a>, TokenKind) -> ControlFlow<()>) {
1533        while let Some(kind) = self.peek() {
1534            let before = self.current_token;
1535            match run(self, kind) {
1536                ControlFlow::Break(()) => break,
1537                ControlFlow::Continue(()) => {
1538                    debug_assert!(
1539                        before != self.current_token,
1540                        "peek_while() iteration must advance parsing"
1541                    );
1542                }
1543            }
1544        }
1545    }
1546
1547    fn peek(&mut self) -> Option<TokenKind> {
1548        self.peek_token().map(Token::kind)
1549    }
1550
1551    fn peek_data(&mut self) -> Option<&'a str> {
1552        self.peek_token().map(Token::data)
1553    }
1554
1555    fn peek_token(&mut self) -> Option<&Token<'a>> {
1556        if self.current_token.is_none() {
1557            self.current_token = self.next_significant_token();
1558        }
1559        self.current_token.as_ref()
1560    }
1561
1562    fn bump(&mut self) -> Option<Token<'a>> {
1563        let token = if let Some(token) = self.current_token.take() {
1564            token
1565        } else {
1566            self.next_significant_token()?
1567        };
1568        self.last_end = span_index(token.index() + token.data().len());
1569        Some(token)
1570    }
1571
1572    fn next_significant_token(&mut self) -> Option<Token<'a>> {
1573        // `next_significant` skips whitespace and comma trivia in the cursor;
1574        // comments still surface as tokens so their spans can be recorded.
1575        loop {
1576            match self.lexer.next_significant()? {
1577                Ok(token) => match token.kind() {
1578                    TokenKind::Comment => {
1579                        let span = token_span(&token);
1580                        self.comments.push(span);
1581                    }
1582                    _ => return Some(token),
1583                },
1584                Err(err) => {
1585                    if err.is_limit() {
1586                        self.accept_errors = false;
1587                    }
1588                    self.errors.push(err);
1589                }
1590            }
1591        }
1592    }
1593
1594    fn current_start(&mut self) -> u32 {
1595        if let Some(token) = self.peek_token() { span_index(token.index()) } else { self.last_end }
1596    }
1597
1598    fn current_span(&mut self) -> Span {
1599        self.peek_token().map(token_span).unwrap_or_else(|| Span::new(self.last_end, self.last_end))
1600    }
1601
1602    fn span_from(&self, start: u32) -> Span {
1603        Span::new(start, self.last_end.max(start))
1604    }
1605}
1606
1607/// Converts a byte index to a span offset.
1608///
1609/// `Parser::new` asserts the source text fits in `u32`, so token indexes are
1610/// always in range.
1611#[expect(clippy::cast_possible_truncation)]
1612#[inline]
1613fn span_index(index: usize) -> u32 {
1614    debug_assert!(u32::try_from(index).is_ok());
1615    index as u32
1616}
1617
1618fn token_span(token: &Token<'_>) -> Span {
1619    let start = span_index(token.index());
1620    let end = span_index(token.index() + token.data().len());
1621    Span::new(start, end)
1622}
1623
1624fn unescape_string(input: &str) -> String {
1625    let mut output = String::with_capacity(input.len());
1626    let mut iter = input.chars();
1627    while let Some(c) = iter.next() {
1628        if c != '\\' {
1629            output.push(c);
1630            continue;
1631        }
1632
1633        let Some(c2) = iter.next() else {
1634            output.push(c);
1635            break;
1636        };
1637
1638        match c2 {
1639            '"' | '\\' | '/' => output.push(c2),
1640            'b' => output.push('\u{0008}'),
1641            'f' => output.push('\u{000c}'),
1642            'n' => output.push('\n'),
1643            'r' => output.push('\r'),
1644            't' => output.push('\t'),
1645            'u' => {
1646                let value = iter.by_ref().take(4).fold(0, |acc, c| {
1647                    let digit = c.to_digit(16).unwrap_or(0);
1648                    (acc << 4) + digit
1649                });
1650                if let Some(c) = char::from_u32(value) {
1651                    output.push(c);
1652                }
1653            }
1654            _ => {}
1655        }
1656    }
1657    output
1658}
1659
1660fn normalize_block_string(raw: &str) -> String {
1661    let content =
1662        raw.strip_prefix(r#"""""#).and_then(|value| value.strip_suffix(r#"""""#)).unwrap_or(raw);
1663    let mut output = String::with_capacity(content.len());
1664    let mut chars = content.chars().peekable();
1665    while let Some(ch) = chars.next() {
1666        if ch == '\r' {
1667            chars.next_if_eq(&'\n');
1668            output.push('\n');
1669        } else {
1670            output.push(ch);
1671        }
1672    }
1673    output
1674}