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