Fork of daniellemaywood.uk/gleam — Wasm codegen work
197 kB
5365 lines
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2020 The Gleam contributors
3
4// Gleam Parser
5//
6// Terminology:
7// Expression Unit:
8// Essentially a thing that goes between operators.
9// Int, Bool, function call, "{" expression-sequence "}", case x {}, ..etc
10//
11// Expression:
12// One or more Expression Units separated by an operator
13//
14// Binding:
15// (let|let assert|use) name (:TypeAnnotation)? = Expression
16//
17// Expression Sequence:
18// * One or more Expressions
19// * A Binding followed by at least one more Expression Sequences
20//
21// Naming Conventions:
22// parse_x
23// Parse a specific part of the grammar, not erroring if it cannot.
24// Generally returns `Result<Option<A>, ParseError>`, note the inner Option
25//
26// expect_x
27// Parse a generic or specific part of the grammar, erroring if it cannot.
28// Generally returns `Result<A, ParseError>`, note no inner Option
29//
30// maybe_x
31// Parse a generic part of the grammar. Returning `None` if it cannot.
32// Returns `Some(x)` and advances the token stream if it can.
33//
34// Operator Precedence Parsing:
35// Needs to take place in expressions and in clause guards.
36// It is accomplished using the Simple Precedence Parser algorithm.
37// See: https://en.wikipedia.org/wiki/Simple_precedence_parser
38//
39// It relies or the operator grammar being in the general form:
40// e ::= expr op expr | expr
41// Which just means that exprs and operators always alternate, starting with an expr
42//
43// The gist of the algorithm is:
44// Create 2 stacks, one to hold expressions, and one to hold un-reduced operators.
45// While consuming the input stream, if an expression is encountered add it to the top
46// of the expression stack. If an operator is encountered, compare its precedence to the
47// top of the operator stack and perform the appropriate action, which is either using an
48// operator to reduce 2 expressions on the top of the expression stack or put it on the top
49// of the operator stack. When the end of the input is reached, attempt to reduce all of the
50// expressions down to a single expression(or no expression) using the remaining operators
51// on the operator stack. If there are any operators left, or more than 1 expression left
52// this is a syntax error. But the implementation here shouldn't need to handle that case
53// as the outer parser ensures the correct structure.
54//
55pub mod error;
56pub mod extra;
57pub mod lexer;
58mod token;
59
60use crate::Warning;
61use crate::analyse::Inferred;
62use crate::ast::{
63 Arg, ArgNames, Assert, AssignName, Assignment, AssignmentKind, BinOp, BitArrayOption,
64 BitArraySegment, BitArraySize, CAPTURE_VARIABLE, CallArg, Clause, ClauseGuard, Constant,
65 CustomType, Definition, Function, FunctionLiteralKind, HasLocation, Import, IntOperator,
66 Module, ModuleConstant, Pattern, Publicity, RecordBeingUpdated, RecordConstructor,
67 RecordConstructorArg, RecordUpdateArg, SrcSpan, Statement, TailPattern, TargetedDefinition,
68 TodoKind, TypeAlias, TypeAst, TypeAstConstructor, TypeAstConstructorName, TypeAstFn,
69 TypeAstHole, TypeAstTuple, TypeAstVar, UnqualifiedImport, UntypedArg, UntypedClause,
70 UntypedClauseGuard, UntypedConstant, UntypedDefinition, UntypedExpr, UntypedModule,
71 UntypedPattern, UntypedRecordUpdateArg, UntypedStatement, UntypedUseAssignment, Use,
72 UseAssignment,
73};
74use crate::build::Target;
75use crate::error::wrap;
76use crate::exhaustiveness::CompiledCase;
77use crate::parse::error::IncorrectNamePosition;
78use crate::parse::extra::ModuleExtra;
79use crate::type_::Deprecation;
80use crate::type_::error::{VariableDeclaration, VariableOrigin, VariableSyntax};
81use crate::type_::expression::{Implementations, Purity};
82use crate::type_::printer::Names;
83use crate::warning::{DeprecatedSyntaxWarning, WarningEmitter};
84use camino::Utf8PathBuf;
85use ecow::EcoString;
86use error::{LexicalError, ParseError, ParseErrorType};
87use lexer::{LexResult, Spanned};
88use num_bigint::BigInt;
89use serde::{Deserialize, Serialize};
90use std::cmp::Ordering;
91use std::collections::{HashSet, VecDeque};
92use std::hash::{Hash, Hasher};
93use std::str::FromStr;
94pub use token::Token;
95use vec1::{Vec1, vec1};
96
97#[cfg(test)]
98mod tests;
99
100#[derive(Debug)]
101pub struct Parsed {
102 pub module: UntypedModule,
103 pub extra: ModuleExtra,
104}
105
106/// We use this to keep track of the `@internal` annotation for top level
107/// definitions. Instead of using just a boolean we want to keep track of the
108/// source position of the annotation in case it is present. This way we can
109/// report a better error message highlighting the annotation in case it is
110/// used on a private definition (it doesn't make sense to mark something
111/// private as internal):
112///
113/// ```txt
114/// @internal
115/// ^^^^^^^^^ we first get to the annotation
116/// fn wibble() {}
117/// ^^ and only later discover it's applied on a private definition
118/// so we have to keep track of the attribute's position to highlight it
119/// in the resulting error message.
120/// ```
121#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
122enum InternalAttribute {
123 #[default]
124 Missing,
125 Present(SrcSpan),
126}
127
128#[derive(Debug, Default)]
129struct Attributes {
130 target: Option<Target>,
131 deprecated: Deprecation,
132 external_erlang: Option<(EcoString, EcoString, SrcSpan)>,
133 external_javascript: Option<(EcoString, EcoString, SrcSpan)>,
134 external_cranelift: Option<(EcoString, EcoString, SrcSpan)>,
135 internal: InternalAttribute,
136}
137
138impl Attributes {
139 fn has_function_only(&self) -> bool {
140 self.external_erlang.is_some()
141 || self.external_javascript.is_some()
142 || self.external_cranelift.is_some()
143 }
144
145 fn has_external_for(&self, target: Target) -> bool {
146 match target {
147 Target::Erlang => self.external_erlang.is_some(),
148 Target::JavaScript => self.external_javascript.is_some(),
149 Target::Cranelift => self.external_cranelift.is_some(),
150 }
151 }
152
153 fn set_external_for(&mut self, target: Target, ext: Option<(EcoString, EcoString, SrcSpan)>) {
154 match target {
155 Target::Erlang => self.external_erlang = ext,
156 Target::JavaScript => self.external_javascript = ext,
157 Target::Cranelift => self.external_cranelift = ext,
158 }
159 }
160}
161
162//
163// Public Interface
164//
165
166pub type SpannedString = (SrcSpan, EcoString);
167
168pub fn parse_module(
169 path: Utf8PathBuf,
170 src: &str,
171 warnings: &WarningEmitter,
172) -> Result<Parsed, ParseError> {
173 let lex = lexer::make_tokenizer(src);
174 let mut parser = Parser::new(lex);
175 let mut parsed = parser.parse_module()?;
176 parsed.extra = parser.extra;
177
178 let src = EcoString::from(src);
179 for warning in parser.warnings {
180 warnings.emit(Warning::DeprecatedSyntax {
181 path: path.clone(),
182 src: src.clone(),
183 warning,
184 });
185 }
186
187 for detached in parser.detached_doc_comments {
188 warnings.emit(Warning::DetachedDocComment {
189 path: path.clone(),
190 src: src.clone(),
191 location: detached,
192 });
193 }
194
195 Ok(parsed)
196}
197
198//
199// Test Interface
200//
201#[cfg(test)]
202pub fn parse_statement_sequence(src: &str) -> Result<Vec1<UntypedStatement>, ParseError> {
203 let lex = lexer::make_tokenizer(src);
204 let mut parser = Parser::new(lex);
205 let expr = parser.parse_statement_seq();
206 let expr = parser.ensure_no_errors_or_remaining_input(expr)?;
207 match expr {
208 Some((e, _)) => Ok(e),
209 _ => parse_error(ParseErrorType::ExpectedExpr, SrcSpan { start: 0, end: 0 }),
210 }
211}
212
213//
214// Test Interface
215//
216#[cfg(test)]
217pub fn parse_const_value(src: &str) -> Result<UntypedConstant, ParseError> {
218 let lex = lexer::make_tokenizer(src);
219 let mut parser = Parser::new(lex);
220 let expr = parser.parse_const_value();
221 let expr = parser.ensure_no_errors_or_remaining_input(expr)?;
222 match expr {
223 Some(e) => Ok(e),
224 _ => parse_error(ParseErrorType::ExpectedExpr, SrcSpan { start: 0, end: 0 }),
225 }
226}
227
228//
229// Parser
230//
231#[derive(Debug)]
232pub struct Parser<T: Iterator<Item = LexResult>> {
233 tokens: T,
234 lex_errors: Vec<LexicalError>,
235 warnings: Vec<DeprecatedSyntaxWarning>,
236 tok0: Option<Spanned>,
237 tok1: Option<Spanned>,
238 extra: ModuleExtra,
239 doc_comments: VecDeque<(u32, EcoString)>,
240 detached_doc_comments: Vec<SrcSpan>,
241}
242impl<T> Parser<T>
243where
244 T: Iterator<Item = LexResult>,
245{
246 pub fn new(input: T) -> Self {
247 let mut parser = Parser {
248 tokens: input,
249 lex_errors: vec![],
250 warnings: vec![],
251 tok0: None,
252 tok1: None,
253 extra: ModuleExtra::new(),
254 doc_comments: VecDeque::new(),
255 detached_doc_comments: Vec::new(),
256 };
257 parser.advance();
258 parser.advance();
259 parser
260 }
261
262 fn parse_module(&mut self) -> Result<Parsed, ParseError> {
263 let definitions = self.series_of(&Parser::parse_definition, None);
264 let definitions = self.ensure_no_errors_or_remaining_input(definitions)?;
265 let module = Module {
266 name: "".into(),
267 documentation: vec![],
268 type_info: (),
269 definitions,
270 names: Names::new(),
271 unused_definition_positions: HashSet::new(),
272 };
273 Ok(Parsed {
274 module,
275 extra: ModuleExtra::new(),
276 })
277 }
278
279 // The way the parser is currently implemented, it cannot exit immediately while advancing
280 // the token stream upon seeing a LexError. That is to avoid having to put `?` all over the
281 // place and instead we collect LexErrors in `self.lex_errors` and attempt to continue parsing.
282 // Once parsing has returned we want to surface an error in the order:
283 // 1) LexError, 2) ParseError, 3) More Tokens Left
284 fn ensure_no_errors_or_remaining_input<A>(
285 &mut self,
286 parse_result: Result<A, ParseError>,
287 ) -> Result<A, ParseError> {
288 let parse_result = self.ensure_no_errors(parse_result)?;
289 if let Some((start, token, end)) = self.next_tok() {
290 // there are still more tokens
291 let expected = vec!["An import, const, type, or function.".into()];
292 return parse_error(
293 ParseErrorType::UnexpectedToken {
294 token,
295 expected,
296 hint: None,
297 },
298 SrcSpan { start, end },
299 );
300 }
301 // no errors
302 Ok(parse_result)
303 }
304
305 // The way the parser is currently implemented, it cannot exit immediately
306 // while advancing the token stream upon seeing a LexError. That is to avoid
307 // having to put `?` all over the place and instead we collect LexErrors in
308 // `self.lex_errors` and attempt to continue parsing.
309 // Once parsing has returned we want to surface an error in the order:
310 // 1) LexError, 2) ParseError
311 fn ensure_no_errors<A>(
312 &mut self,
313 parse_result: Result<A, ParseError>,
314 ) -> Result<A, ParseError> {
315 if let Some(error) = self.lex_errors.first() {
316 // Lex errors first
317 let location = error.location;
318 let error = *error;
319 parse_error(ParseErrorType::LexError { error }, location)
320 } else {
321 // Return any existing parse error
322 parse_result
323 }
324 }
325
326 fn parse_definition(&mut self) -> Result<Option<TargetedDefinition>, ParseError> {
327 let mut attributes = Attributes::default();
328 let location = self.parse_attributes(&mut attributes)?;
329
330 let def = match (self.tok0.take(), self.tok1.as_ref()) {
331 // Imports
332 (Some((start, Token::Import, _)), _) => {
333 self.advance();
334 self.parse_import(start)
335 }
336 // Module Constants
337 (Some((start, Token::Const, _)), _) => {
338 self.advance();
339 self.parse_module_const(start, false, &attributes)
340 }
341 (Some((start, Token::Pub, _)), Some((_, Token::Const, _))) => {
342 self.advance();
343 self.advance();
344 self.parse_module_const(start, true, &attributes)
345 }
346
347 // Function
348 (Some((start, Token::Fn, _)), _) => {
349 self.advance();
350 self.parse_function(start, false, false, &mut attributes)
351 }
352 (Some((start, Token::Pub, _)), Some((_, Token::Fn, _))) => {
353 self.advance();
354 self.advance();
355 self.parse_function(start, true, false, &mut attributes)
356 }
357
358 // Custom Types, and Type Aliases
359 (Some((start, Token::Type, _)), _) => {
360 self.advance();
361 self.parse_custom_type(start, false, false, &mut attributes)
362 }
363 (Some((start, Token::Pub, _)), Some((_, Token::Opaque, _))) => {
364 self.advance();
365 self.advance();
366 let _ = self.expect_one(&Token::Type)?;
367 self.parse_custom_type(start, true, true, &mut attributes)
368 }
369 (Some((start, Token::Pub, _)), Some((_, Token::Type, _))) => {
370 self.advance();
371 self.advance();
372 self.parse_custom_type(start, true, false, &mut attributes)
373 }
374 (Some((start, Token::Opaque, _)), Some((_, Token::Type, _))) => {
375 // A private opaque type makes no sense! We still want to parse it
376 // and return an error later during the analysis phase.
377 self.advance();
378 self.advance();
379 self.parse_custom_type(start, false, true, &mut attributes)
380 }
381
382 (t0, _) => {
383 self.tok0 = t0;
384 Ok(None)
385 }
386 }?;
387
388 match (def, location) {
389 (Some(definition), _) if definition.is_function() || definition.is_custom_type() => {
390 Ok(Some(TargetedDefinition {
391 definition,
392 target: attributes.target,
393 }))
394 }
395
396 (Some(definition), None) => Ok(Some(TargetedDefinition {
397 definition,
398 target: attributes.target,
399 })),
400
401 (_, Some(location)) if attributes.has_function_only() => {
402 parse_error(ParseErrorType::ExpectedFunctionDefinition, location)
403 }
404
405 (Some(definition), _) => Ok(Some(TargetedDefinition {
406 definition,
407 target: attributes.target,
408 })),
409
410 (_, Some(location)) => parse_error(ParseErrorType::ExpectedDefinition, location),
411
412 (None, None) => Ok(None),
413 }
414 }
415
416 //
417 // Parse Expressions
418 //
419
420 // examples:
421 // unit
422 // unit op unit
423 // unit op unit pipe unit(call)
424 // unit op unit pipe unit(call) pipe unit(call)
425 fn parse_expression(&mut self) -> Result<Option<UntypedExpr>, ParseError> {
426 self.parse_expression_inner(false)
427 }
428
429 fn parse_expression_inner(
430 &mut self,
431 is_let_binding: bool,
432 ) -> Result<Option<UntypedExpr>, ParseError> {
433 // uses the simple operator parser algorithm
434 let mut opstack = vec![];
435 let mut estack = vec![];
436 let mut last_op_start = 0;
437 let mut last_op_end = 0;
438
439 // This is used to keep track if we've just ran into a `|>` operator in
440 // order to properly parse an echo based on its position: if it is in a
441 // pipeline then it isn't expected to be followed by an expression.
442 // Otherwise, it's expected to be followed by an expression.
443 let mut expression_unit_context = ExpressionUnitContext::Other;
444
445 loop {
446 match self.parse_expression_unit(expression_unit_context)? {
447 Some(unit) => {
448 self.post_process_expression_unit(&unit, is_let_binding)?;
449 estack.push(unit);
450 }
451 _ if estack.is_empty() => return Ok(None),
452 _ => {
453 return parse_error(
454 ParseErrorType::OpNakedRight,
455 SrcSpan {
456 start: last_op_start,
457 end: last_op_end,
458 },
459 );
460 }
461 }
462
463 let Some((op_s, t, op_e)) = self.tok0.take() else {
464 break;
465 };
466
467 let Some(p) = precedence(&t) else {
468 self.tok0 = Some((op_s, t, op_e));
469 break;
470 };
471
472 expression_unit_context = if t == Token::Pipe {
473 ExpressionUnitContext::FollowingPipe
474 } else {
475 ExpressionUnitContext::Other
476 };
477
478 // Is Op
479 self.advance();
480 last_op_start = op_s;
481 last_op_end = op_e;
482 let _ = handle_op(
483 Some(((op_s, t, op_e), p)),
484 &mut opstack,
485 &mut estack,
486 &do_reduce_expression,
487 );
488 }
489
490 Ok(handle_op(
491 None,
492 &mut opstack,
493 &mut estack,
494 &do_reduce_expression,
495 ))
496 }
497
498 fn post_process_expression_unit(
499 &mut self,
500 unit: &UntypedExpr,
501 is_let_binding: bool,
502 ) -> Result<(), ParseError> {
503 // Produce better error message for `[x] = [1]` outside
504 // of `let` statement.
505 if !is_let_binding
506 && let UntypedExpr::List { .. } = unit
507 && let Some((start, Token::Equal, end)) = self.tok0
508 {
509 return parse_error(ParseErrorType::NoLetBinding, SrcSpan { start, end });
510 }
511 Ok(())
512 }
513
514 // examples:
515 // 1
516 // "one"
517 // True
518 // fn() { "hi" }
519 // unit().unit().unit()
520 // A(a.., label: tuple(1))
521 // { expression_sequence }
522 fn parse_expression_unit(
523 &mut self,
524 context: ExpressionUnitContext,
525 ) -> Result<Option<UntypedExpr>, ParseError> {
526 let mut expr = match self.tok0.take() {
527 Some((start, Token::String { value }, end)) => {
528 self.advance();
529 UntypedExpr::String {
530 location: SrcSpan { start, end },
531 value,
532 }
533 }
534 Some((start, Token::Int { value, int_value }, end)) => {
535 self.advance();
536 UntypedExpr::Int {
537 location: SrcSpan { start, end },
538 value,
539 int_value,
540 }
541 }
542
543 Some((start, Token::Float { value, float_value }, end)) => {
544 self.advance();
545 UntypedExpr::Float {
546 location: SrcSpan { start, end },
547 value,
548 float_value,
549 }
550 }
551
552 // var lower_name and UpName
553 Some((start, Token::Name { name } | Token::UpName { name }, end)) => {
554 self.advance();
555 UntypedExpr::Var {
556 location: SrcSpan { start, end },
557 name,
558 }
559 }
560
561 Some((start, Token::Todo, end)) => {
562 self.advance();
563 let message = self.maybe_parse_as_message()?;
564 let end = message.as_ref().map_or(end, |m| m.location().end);
565 UntypedExpr::Todo {
566 location: SrcSpan { start, end },
567 kind: TodoKind::Keyword,
568 message,
569 }
570 }
571
572 Some((start, Token::Panic, end)) => {
573 self.advance();
574 let message = self.maybe_parse_as_message()?;
575 let end = message.as_ref().map_or(end, |m| m.location().end);
576 UntypedExpr::Panic {
577 location: SrcSpan { start, end },
578 message,
579 }
580 }
581
582 Some((start, Token::Echo, echo_end)) => {
583 self.advance();
584 if context == ExpressionUnitContext::FollowingPipe {
585 // If an echo is used as a step in a pipeline (`|> echo`)
586 // then it cannot be followed by an expression.
587 let message = self.maybe_parse_as_message()?;
588 let end = message.as_ref().map_or(echo_end, |m| m.location().end);
589 UntypedExpr::Echo {
590 location: SrcSpan { start, end },
591 keyword_end: echo_end,
592 expression: None,
593 message,
594 }
595 } else {
596 // Otherwise it must be followed by an expression.
597 // However, you might have noticed we're not erroring if the
598 // expression is not there. Instead we move this error to
599 // the analysis phase so that a wrong usage of echo won't
600 // stop analysis from happening everywhere and be fault
601 // tolerant like everything else.
602 let expression = self.parse_expression()?;
603 let end = expression.as_ref().map_or(echo_end, |e| e.location().end);
604
605 let message = self.maybe_parse_as_message()?;
606 let end = message.as_ref().map_or(end, |m| m.location().end);
607
608 UntypedExpr::Echo {
609 location: SrcSpan { start, end },
610 keyword_end: echo_end,
611 expression: expression.map(Box::new),
612 message,
613 }
614 }
615 }
616
617 Some((start, Token::Hash, _)) => {
618 self.advance();
619 let _ = self
620 .expect_one(&Token::LeftParen)
621 .map_err(|error| self.add_comment_style_hint(error))?;
622 let elements = self.series_of(&Parser::parse_expression, Some(&Token::Comma))?;
623 let (_, end) =
624 self.expect_one_following_series(&Token::RightParen, "an expression")?;
625 UntypedExpr::Tuple {
626 location: SrcSpan { start, end },
627 elements,
628 }
629 }
630
631 // list
632 Some((start, Token::LeftSquare, _)) => {
633 self.advance();
634 let (elements, elements_end_with_comma) = self.series_of_has_trailing_separator(
635 &Parser::parse_expression,
636 Some(&Token::Comma),
637 )?;
638
639 // Parse an optional tail
640 let mut tail = None;
641 let mut elements_after_tail = None;
642 let mut dot_dot_location = None;
643
644 if let Some((start, end)) = self.maybe_one(&Token::DotDot) {
645 dot_dot_location = Some((start, end));
646 tail = self.parse_expression()?.map(Box::new);
647 if self.maybe_one(&Token::Comma).is_some() {
648 // See if there's a list of items after the tail,
649 // like `[..wibble, wobble, wabble]`
650 let elements =
651 self.series_of(&Parser::parse_expression, Some(&Token::Comma));
652 match elements {
653 Err(_) => {}
654 Ok(elements) => {
655 elements_after_tail = Some(elements);
656 }
657 }
658 }
659
660 if tail.is_some() {
661 if !elements_end_with_comma {
662 self.warnings
663 .push(DeprecatedSyntaxWarning::DeprecatedListPrepend {
664 location: SrcSpan { start, end },
665 });
666 }
667
668 // Give a better error when there is two consecutive spreads
669 // like `[..wibble, ..wabble, woo]`. However, if there's other
670 // elements after the tail of the list
671 if let Some((second_start, second_end)) = self.maybe_one(&Token::DotDot) {
672 let _second_tail = self.parse_expression();
673
674 if elements_after_tail.is_none()
675 || elements_after_tail
676 .as_ref()
677 .is_some_and(|vec| vec.is_empty())
678 {
679 return parse_error(
680 ParseErrorType::ListSpreadWithAnotherSpread {
681 first_spread_location: SrcSpan { start, end },
682 },
683 SrcSpan {
684 start: second_start,
685 end: second_end,
686 },
687 );
688 }
689 }
690 }
691 }
692
693 let (_, end) = self.expect_one(&Token::RightSquare)?;
694
695 // Return errors for malformed lists
696 match dot_dot_location {
697 Some((start, end)) if tail.is_none() => {
698 return parse_error(
699 ParseErrorType::ListSpreadWithoutTail,
700 SrcSpan { start, end },
701 );
702 }
703 _ => {}
704 }
705 if tail.is_some()
706 && elements.is_empty()
707 && elements_after_tail.as_ref().is_none_or(|e| e.is_empty())
708 {
709 return parse_error(
710 ParseErrorType::ListSpreadWithoutElements,
711 SrcSpan { start, end },
712 );
713 }
714
715 match elements_after_tail {
716 Some(elements) if !elements.is_empty() => {
717 let (start, end) = match (dot_dot_location, tail) {
718 (Some((start, _)), Some(tail)) => (start, tail.location().end),
719 (_, _) => (start, end),
720 };
721 return parse_error(
722 ParseErrorType::ListSpreadFollowedByElements,
723 SrcSpan { start, end },
724 );
725 }
726 _ => {}
727 }
728
729 UntypedExpr::List {
730 location: SrcSpan { start, end },
731 elements,
732 tail,
733 }
734 }
735
736 // BitArray
737 Some((start, Token::LtLt, _)) => {
738 self.advance();
739 let segments = self.series_of(
740 &|this| {
741 Parser::parse_bit_array_segment(
742 this,
743 &(|this| this.parse_expression_unit(ExpressionUnitContext::Other)),
744 &Parser::expect_expression,
745 &bit_array_expr_int,
746 )
747 },
748 Some(&Token::Comma),
749 )?;
750 let (_, end) =
751 self.expect_one_following_series(&Token::GtGt, "a bit array segment")?;
752 UntypedExpr::BitArray {
753 location: SrcSpan { start, end },
754 segments,
755 }
756 }
757 Some((start, Token::Fn, _)) => {
758 self.advance();
759 let mut attributes = Attributes::default();
760 match self.parse_function(start, false, true, &mut attributes)? {
761 Some(Definition::Function(Function {
762 location,
763 arguments,
764 body,
765 return_annotation,
766 end_position,
767 ..
768 })) => {
769 let Ok(body) = Vec1::try_from_vec(body) else {
770 return parse_error(ParseErrorType::ExpectedFunctionBody, location);
771 };
772
773 UntypedExpr::Fn {
774 location: SrcSpan::new(location.start, end_position),
775 end_of_head_byte_index: location.end,
776 kind: FunctionLiteralKind::Anonymous { head: location },
777 arguments,
778 body,
779 return_annotation,
780 }
781 }
782
783 _ => {
784 // this isn't just none, it could also be Some(UntypedExpr::..)
785 return self.next_tok_unexpected(vec!["An opening parenthesis.".into()]);
786 }
787 }
788 }
789
790 // expression block "{" "}"
791 Some((start, Token::LeftBrace, _)) => {
792 self.advance();
793 self.parse_block(start)?
794 }
795
796 // case
797 Some((start, Token::Case, case_e)) => {
798 self.advance();
799 let subjects = self.series_of(&Parser::parse_expression, Some(&Token::Comma))?;
800 if self.maybe_one(&Token::LeftBrace).is_some() {
801 let clauses = self.series_of(&Parser::parse_case_clause, None)?;
802 let (_, end) =
803 self.expect_one_following_series(&Token::RightBrace, "a case clause")?;
804 if subjects.is_empty() {
805 return parse_error(
806 ParseErrorType::ExpectedExpr,
807 SrcSpan { start, end: case_e },
808 );
809 } else {
810 UntypedExpr::Case {
811 location: SrcSpan { start, end },
812 subjects,
813 clauses: Some(clauses),
814 }
815 }
816 } else {
817 UntypedExpr::Case {
818 location: SrcSpan::new(
819 start,
820 subjects
821 .last()
822 .map(|subject| subject.location().end)
823 .unwrap_or(case_e),
824 ),
825 subjects,
826 clauses: None,
827 }
828 }
829 }
830
831 // Helpful error if trying to write an if expression instead of a
832 // case.
833 Some((start, Token::If, end)) => {
834 return parse_error(ParseErrorType::IfExpression, SrcSpan { start, end });
835 }
836
837 // Helpful error on possibly trying to group with "(".
838 Some((start, Token::LeftParen, _)) => {
839 return parse_error(ParseErrorType::ExprLparStart, SrcSpan { start, end: start });
840 }
841
842 // Boolean negation
843 Some((start, Token::Bang, _end)) => {
844 self.advance();
845 match self.parse_expression_unit(ExpressionUnitContext::Other)? {
846 Some(value) => UntypedExpr::NegateBool {
847 location: SrcSpan {
848 start,
849 end: value.location().end,
850 },
851 value: Box::from(value),
852 },
853 None => {
854 return parse_error(
855 ParseErrorType::ExpectedExpr,
856 SrcSpan { start, end: start },
857 );
858 }
859 }
860 }
861
862 // Int negation
863 Some((start, Token::Minus, _end)) => {
864 self.advance();
865 match self.parse_expression_unit(ExpressionUnitContext::Other)? {
866 Some(value) => UntypedExpr::NegateInt {
867 location: SrcSpan {
868 start,
869 end: value.location().end,
870 },
871 value: Box::from(value),
872 },
873 None => {
874 return parse_error(
875 ParseErrorType::ExpectedExpr,
876 SrcSpan { start, end: start },
877 );
878 }
879 }
880 }
881
882 t0 => {
883 self.tok0 = t0;
884 return Ok(None);
885 }
886 };
887
888 // field access and call can stack up
889 loop {
890 match self.maybe_one(&Token::Dot) {
891 Some((dot_start, _)) => {
892 let start = expr.location().start;
893 // field access
894 match self.tok0.take() {
895 // tuple access
896 Some((
897 _,
898 Token::Int {
899 value,
900 int_value: _,
901 },
902 end,
903 )) => {
904 self.advance();
905 let v = value.replace("_", "");
906 match u64::from_str(&v) {
907 Ok(index) => {
908 expr = UntypedExpr::TupleIndex {
909 location: SrcSpan { start, end },
910 index,
911 tuple: Box::new(expr),
912 }
913 }
914 _ => {
915 return parse_error(
916 ParseErrorType::InvalidTupleAccess,
917 SrcSpan { start, end },
918 );
919 }
920 }
921 }
922
923 Some((label_start, Token::Name { name: label }, end)) => {
924 self.advance();
925 expr = UntypedExpr::FieldAccess {
926 location: SrcSpan { start, end },
927 label_location: SrcSpan {
928 start: label_start,
929 end,
930 },
931 label,
932 container: Box::new(expr),
933 }
934 }
935
936 Some((label_start, Token::UpName { name: label }, end)) => {
937 self.advance();
938 expr = UntypedExpr::FieldAccess {
939 location: SrcSpan { start, end },
940 label_location: SrcSpan {
941 start: label_start,
942 end,
943 },
944 label,
945 container: Box::new(expr),
946 }
947 }
948
949 t0 => {
950 // parse a field access with no label
951 self.tok0 = t0;
952 let end = dot_start + 1;
953 expr = UntypedExpr::FieldAccess {
954 location: SrcSpan { start, end },
955 label_location: SrcSpan {
956 start: dot_start,
957 end,
958 },
959 label: "".into(),
960 container: Box::new(expr),
961 };
962 return Ok(Some(expr));
963 }
964 }
965 }
966 _ => {
967 if let Some((left_paren, _)) = self.maybe_one(&Token::LeftParen) {
968 let start = expr.location().start;
969 match self.maybe_one(&Token::DotDot) {
970 Some((dot_s, _)) => {
971 // Record update
972 let base = self.expect_expression()?;
973 let base_e = base.location().end;
974 let record = RecordBeingUpdated {
975 base: Box::new(base),
976 location: SrcSpan {
977 start: dot_s,
978 end: base_e,
979 },
980 };
981 let mut arguments = vec![];
982 if self.maybe_one(&Token::Comma).is_some() {
983 arguments = self.series_of(
984 &Parser::parse_record_update_arg,
985 Some(&Token::Comma),
986 )?;
987 }
988 let (_, end) = self.expect_one(&Token::RightParen)?;
989
990 expr = UntypedExpr::RecordUpdate {
991 location: SrcSpan { start, end },
992 spread_start: dot_s,
993 constructor: Box::new(expr),
994 record,
995 arguments,
996 };
997 }
998 _ => {
999 // Call
1000 let arguments = self.parse_fn_arguments()?;
1001 let (_, end) = self.expect_one(&Token::RightParen)?;
1002 expr = make_call(expr, arguments, start, end, left_paren)?;
1003 }
1004 }
1005 } else {
1006 // done
1007 break;
1008 }
1009 }
1010 }
1011 }
1012
1013 Ok(Some(expr))
1014 }
1015
1016 fn add_comment_style_hint(&self, mut err: ParseError) -> ParseError {
1017 if let ParseErrorType::UnexpectedToken { ref mut hint, .. } = err.error {
1018 let text =
1019 "Maybe you meant to create a comment?\nComments in Gleam start with `//`, not `#`";
1020 *hint = Some(text.into());
1021 }
1022 err
1023 }
1024
1025 // A `use` expression
1026 // use <- function
1027 // use <- function()
1028 // use <- function(a, b)
1029 // use <- module.function(a, b)
1030 // use a, b, c <- function(a, b)
1031 // use a, b, c, <- function(a, b)
1032 fn parse_use(&mut self, start: u32, end: u32) -> Result<UntypedStatement, ParseError> {
1033 let assignments = match self.tok0 {
1034 Some((_, Token::LArrow, _)) => {
1035 vec![]
1036 }
1037 _ => self.series_of(&Parser::parse_use_assignment, Some(&Token::Comma))?,
1038 };
1039
1040 _ = self.expect_one_following_series(&Token::LArrow, "a use variable assignment")?;
1041 let call = self.expect_expression()?;
1042
1043 let assignments_location = match (assignments.first(), assignments.last()) {
1044 (Some(first), Some(last)) => SrcSpan {
1045 start: first.location.start,
1046 end: last.location.end,
1047 },
1048 (_, _) => SrcSpan { start, end },
1049 };
1050
1051 Ok(Statement::Use(Use {
1052 location: SrcSpan::new(start, call.location().end),
1053 assignments_location,
1054 right_hand_side_location: call.location(),
1055 assignments,
1056 call: Box::new(call),
1057 }))
1058 }
1059
1060 fn parse_use_assignment(&mut self) -> Result<Option<UntypedUseAssignment>, ParseError> {
1061 let start = self.tok0.as_ref().map(|t| t.0).unwrap_or(0);
1062
1063 let pattern = self
1064 .parse_pattern(PatternPosition::UsePattern)?
1065 .ok_or_else(|| ParseError {
1066 error: ParseErrorType::ExpectedPattern,
1067 location: SrcSpan { start, end: start },
1068 })?;
1069
1070 let annotation = self.parse_type_annotation(&Token::Colon)?;
1071 let end = match annotation {
1072 Some(ref a) => a.location().end,
1073 None => pattern.location().end,
1074 };
1075
1076 Ok(Some(UseAssignment {
1077 location: SrcSpan { start, end },
1078 pattern,
1079 annotation,
1080 }))
1081 }
1082
1083 fn maybe_parse_as_message(&mut self) -> Result<Option<Box<UntypedExpr>>, ParseError> {
1084 let message = if self.maybe_one(&Token::As).is_some() {
1085 let expression = self.expect_expression_unit(ExpressionUnitContext::Other)?;
1086 Some(Box::new(expression))
1087 } else {
1088 None
1089 };
1090
1091 Ok(message)
1092 }
1093
1094 fn maybe_parse_constant_as_message(
1095 &mut self,
1096 ) -> Result<Option<Box<UntypedConstant>>, ParseError> {
1097 let message = if let Some((as_start, as_end)) = self.maybe_one(&Token::As) {
1098 match self.parse_const_value_unit()? {
1099 Some(constant) => Some(Box::new(constant)),
1100 None => {
1101 return Err(ParseError {
1102 error: ParseErrorType::MissingConstantAsMessage,
1103 location: SrcSpan::new(as_start, as_end),
1104 });
1105 }
1106 }
1107 } else {
1108 None
1109 };
1110
1111 Ok(message)
1112 }
1113
1114 // An assignment, with `Let` already consumed
1115 fn parse_assignment(&mut self, start: u32) -> Result<UntypedStatement, ParseError> {
1116 let mut kind = match self.tok0 {
1117 Some((assert_keyword_start, Token::Assert, assert_end)) => {
1118 _ = self.next_tok();
1119 AssignmentKind::Assert {
1120 location: SrcSpan::new(start, assert_end),
1121 assert_keyword_start,
1122 message: None,
1123 }
1124 }
1125 _ => AssignmentKind::Let,
1126 };
1127 let pattern = match self.parse_pattern(PatternPosition::LetAssignment)? {
1128 Some(p) => p,
1129 _ => {
1130 // DUPE: 62884
1131 return self.next_tok_unexpected(vec!["A pattern".into()])?;
1132 }
1133 };
1134 let annotation = self.parse_type_annotation(&Token::Colon)?;
1135 let (eq_s, eq_e) = self.maybe_one(&Token::Equal).ok_or(ParseError {
1136 error: ParseErrorType::ExpectedEqual,
1137 location: SrcSpan {
1138 start: pattern.location().start,
1139 end: pattern.location().end,
1140 },
1141 })?;
1142 let value = self.parse_expression_inner(true)?.ok_or(match self.tok0 {
1143 Some((start, Token::DiscardName { .. }, end)) => ParseError {
1144 error: ParseErrorType::IncorrectName {
1145 kind: IncorrectNamePosition::Variable,
1146 },
1147 location: SrcSpan { start, end },
1148 },
1149
1150 _ => ParseError {
1151 error: ParseErrorType::ExpectedValue,
1152 location: SrcSpan {
1153 start: eq_s,
1154 end: eq_e,
1155 },
1156 },
1157 })?;
1158
1159 let mut end = value.location().end;
1160
1161 match &mut kind {
1162 AssignmentKind::Let | AssignmentKind::Generated => {}
1163 AssignmentKind::Assert { message, .. } => {
1164 if self.maybe_one(&Token::As).is_some() {
1165 let message_expression =
1166 self.expect_expression_unit(ExpressionUnitContext::Other)?;
1167 end = message_expression.location().end;
1168 *message = Some(message_expression);
1169 }
1170 }
1171 }
1172
1173 Ok(Statement::Assignment(Box::new(Assignment {
1174 location: SrcSpan { start, end },
1175 value,
1176 compiled_case: CompiledCase::failure(),
1177 pattern,
1178 annotation,
1179 kind,
1180 })))
1181 }
1182
1183 // An assert statement, with `Assert` already consumed
1184 fn parse_assert(&mut self, start: u32) -> Result<UntypedStatement, ParseError> {
1185 let value = self.expect_expression()?;
1186 let mut end = value.location().end;
1187
1188 let message = if self.maybe_one(&Token::As).is_some() {
1189 let message_expression = self.expect_expression_unit(ExpressionUnitContext::Other)?;
1190 end = message_expression.location().end;
1191 Some(message_expression)
1192 } else {
1193 None
1194 };
1195
1196 Ok(Statement::Assert(Assert {
1197 location: SrcSpan { start, end },
1198 value,
1199 message,
1200 }))
1201 }
1202
1203 // examples:
1204 // expr
1205 // expr expr..
1206 // expr assignment..
1207 // assignment
1208 // assignment expr..
1209 // assignment assignment..
1210 fn parse_statement_seq(&mut self) -> Result<Option<(Vec1<UntypedStatement>, u32)>, ParseError> {
1211 let mut statements = vec![];
1212 let mut start = None;
1213 let mut end = 0;
1214
1215 // Try and parse as many expressions as possible
1216 while let Some(statement) = self.parse_statement()? {
1217 if start.is_none() {
1218 start = Some(statement.location().start);
1219 }
1220 end = statement.location().end;
1221 statements.push(statement);
1222 }
1223
1224 match Vec1::try_from_vec(statements) {
1225 Ok(statements) => Ok(Some((statements, end))),
1226 Err(_) => Ok(None),
1227 }
1228 }
1229
1230 fn parse_statement(&mut self) -> Result<Option<UntypedStatement>, ParseError> {
1231 match self.tok0.take() {
1232 Some((start, Token::Use, end)) => {
1233 self.advance();
1234 Ok(Some(self.parse_use(start, end)?))
1235 }
1236
1237 Some((start, Token::Let, _)) => {
1238 self.advance();
1239 Ok(Some(self.parse_assignment(start)?))
1240 }
1241
1242 Some((start, Token::Assert, _)) => {
1243 self.advance();
1244 Ok(Some(self.parse_assert(start)?))
1245 }
1246
1247 // Helpful error when trying to define a constant inside a function.
1248 Some((start, Token::Const, end)) => parse_error(
1249 ParseErrorType::ConstantInsideFunction,
1250 SrcSpan { start, end },
1251 ),
1252
1253 token => {
1254 self.tok0 = token;
1255 self.parse_statement_errors()?;
1256 let expression = self.parse_expression()?.map(Statement::Expression);
1257 Ok(expression)
1258 }
1259 }
1260 }
1261
1262 fn parse_statement_errors(&mut self) -> Result<(), ParseError> {
1263 // Better error: name definitions must start with `let`
1264 if let Some((_, Token::Name { .. }, _)) = self.tok0.as_ref()
1265 && let Some((start, Token::Equal | Token::Colon, end)) = self.tok1
1266 {
1267 return parse_error(ParseErrorType::NoLetBinding, SrcSpan { start, end });
1268 }
1269 Ok(())
1270 }
1271
1272 fn parse_block(&mut self, start: u32) -> Result<UntypedExpr, ParseError> {
1273 let body = self.parse_statement_seq()?;
1274 let (_, end) = self.expect_one(&Token::RightBrace)?;
1275 let location = SrcSpan { start, end };
1276 let statements = match body {
1277 Some((statements, _)) => statements,
1278 None => vec1![Statement::Expression(UntypedExpr::Todo {
1279 kind: TodoKind::EmptyBlock,
1280 location,
1281 message: None
1282 })],
1283 };
1284
1285 Ok(UntypedExpr::Block {
1286 location,
1287 statements,
1288 })
1289 }
1290
1291 // The left side of an "=" or a "->"
1292 fn parse_pattern(
1293 &mut self,
1294 position: PatternPosition,
1295 ) -> Result<Option<UntypedPattern>, ParseError> {
1296 let pattern = match self.tok0.take() {
1297 // Pattern::Var or Pattern::Constructor start
1298 Some((start, Token::Name { name }, end)) => {
1299 self.advance();
1300
1301 // A variable is not permitted on the left hand side of a `<>`
1302 if let Some((_, Token::Concatenate, _)) = self.tok0.as_ref() {
1303 return concat_pattern_variable_left_hand_side_error(start, end);
1304 }
1305
1306 if self.maybe_one(&Token::Dot).is_some() {
1307 // We're doing this to get a better error message instead of a generic
1308 // `I was expecting a type`, you can have a look at this issue to get
1309 // a better idea: https://github.com/gleam-lang/gleam/issues/2841.
1310 match self.expect_constructor_pattern(Some((start, name, end)), position) {
1311 Ok(result) => result,
1312 Err(ParseError {
1313 location: SrcSpan { end, .. },
1314 ..
1315 }) => {
1316 return parse_error(
1317 ParseErrorType::InvalidModuleTypePattern,
1318 SrcSpan { start, end },
1319 );
1320 }
1321 }
1322 } else {
1323 Pattern::Variable {
1324 origin: VariableOrigin {
1325 syntax: VariableSyntax::Variable(name.clone()),
1326 declaration: position.to_declaration(),
1327 },
1328 location: SrcSpan { start, end },
1329 name,
1330 type_: (),
1331 }
1332 }
1333 }
1334 // Constructor
1335 Some((start, tok @ Token::UpName { .. }, end)) => {
1336 self.tok0 = Some((start, tok, end));
1337 self.expect_constructor_pattern(None, position)?
1338 }
1339
1340 Some((start, Token::DiscardName { name }, end)) => {
1341 self.advance();
1342
1343 // A discard is not permitted on the left hand side of a `<>`
1344 if let Some((_, Token::Concatenate, _)) = self.tok0.as_ref() {
1345 return concat_pattern_variable_left_hand_side_error(start, end);
1346 }
1347
1348 Pattern::Discard {
1349 location: SrcSpan { start, end },
1350 name,
1351 type_: (),
1352 }
1353 }
1354
1355 Some((start, Token::String { value }, end)) => {
1356 self.advance();
1357
1358 match self.tok0 {
1359 // String matching with assignment, it could either be a
1360 // String prefix matching: "Hello, " as greeting <> name -> ...
1361 // or a full string matching: "Hello, World!" as greeting -> ...
1362 Some((_, Token::As, _)) => {
1363 self.advance();
1364 let (name_start, name, name_end) =
1365 self.expect_name(IncorrectNamePosition::AsPattern)?;
1366 let name_span = SrcSpan {
1367 start: name_start,
1368 end: name_end,
1369 };
1370
1371 match self.tok0 {
1372 // String prefix matching with assignment
1373 // "Hello, " as greeting <> name -> ...
1374 Some((_, Token::Concatenate, _)) => {
1375 self.advance();
1376 let (r_start, right, r_end) = self.expect_assign_name()?;
1377
1378 // Can't match on suffix literal
1379 if let Some((
1380 second_concat_start,
1381 Token::Concatenate,
1382 second_concat_end,
1383 )) = self.tok0
1384 {
1385 let suffix_end = match &self.tok1 {
1386 Some((_start, Token::String { .. }, end)) => *end,
1387 _ => second_concat_end,
1388 };
1389 return concat_pattern_variable_with_suffix(
1390 second_concat_start,
1391 right.name().clone(),
1392 suffix_end,
1393 );
1394 }
1395
1396 Pattern::StringPrefix {
1397 location: SrcSpan { start, end: r_end },
1398 left_location: SrcSpan {
1399 start,
1400 end: name_end,
1401 },
1402 right_location: SrcSpan {
1403 start: r_start,
1404 end: r_end,
1405 },
1406 left_side_string: value,
1407 left_side_assignment: Some((name, name_span)),
1408 right_side_assignment: right,
1409 }
1410 }
1411 // Full string matching with assignment
1412 _ => {
1413 return Ok(Some(Pattern::Assign {
1414 name,
1415 location: name_span,
1416 pattern: Box::new(Pattern::String {
1417 location: SrcSpan { start, end },
1418 value,
1419 }),
1420 }));
1421 }
1422 }
1423 }
1424
1425 // String prefix matching with no left side assignment
1426 // "Hello, " <> name -> ...
1427 Some((_, Token::Concatenate, _)) => {
1428 self.advance();
1429 let (r_start, right, r_end) = self.expect_assign_name()?;
1430
1431 // Can't match on suffix literal
1432 if let Some((second_concat_start, Token::Concatenate, second_concat_end)) =
1433 self.tok0
1434 {
1435 let suffix_end = match &self.tok1 {
1436 Some((_start, Token::String { .. }, end)) => *end,
1437 _ => second_concat_end,
1438 };
1439 return concat_pattern_variable_with_suffix(
1440 second_concat_start,
1441 right.name().clone(),
1442 suffix_end,
1443 );
1444 }
1445
1446 Pattern::StringPrefix {
1447 location: SrcSpan { start, end: r_end },
1448 left_location: SrcSpan { start, end },
1449 right_location: SrcSpan {
1450 start: r_start,
1451 end: r_end,
1452 },
1453 left_side_string: value,
1454 left_side_assignment: None,
1455 right_side_assignment: right,
1456 }
1457 }
1458
1459 // Full string matching
1460 // "Hello, World!" -> ...
1461 _ => Pattern::String {
1462 location: SrcSpan { start, end },
1463 value,
1464 },
1465 }
1466 }
1467 Some((start, Token::Int { value, int_value }, end)) => {
1468 self.advance();
1469 Pattern::Int {
1470 location: SrcSpan { start, end },
1471 value,
1472 int_value,
1473 }
1474 }
1475 Some((start, Token::Float { value, float_value }, end)) => {
1476 self.advance();
1477 Pattern::Float {
1478 location: SrcSpan { start, end },
1479 value,
1480 float_value,
1481 }
1482 }
1483 Some((start, Token::Hash, _)) => {
1484 self.advance();
1485 let _ = self.expect_one(&Token::LeftParen)?;
1486 let elements =
1487 self.series_of(&|this| this.parse_pattern(position), Some(&Token::Comma))?;
1488 let (_, end) = self.expect_one_following_series(&Token::RightParen, "a pattern")?;
1489 Pattern::Tuple {
1490 location: SrcSpan { start, end },
1491 elements,
1492 }
1493 }
1494 // BitArray
1495 Some((start, Token::LtLt, _)) => {
1496 self.advance();
1497 let segments = self.series_of(
1498 &|this| {
1499 this.parse_bit_array_segment(
1500 &|this| match this.parse_pattern(position) {
1501 Ok(Some(Pattern::BitArray { location, .. })) => {
1502 parse_error(ParseErrorType::NestedBitArrayPattern, location)
1503 }
1504 x => x,
1505 },
1506 &Parser::expect_bit_array_pattern_segment_arg,
1507 &bit_array_size_int,
1508 )
1509 },
1510 Some(&Token::Comma),
1511 )?;
1512 let (_, end) =
1513 self.expect_one_following_series(&Token::GtGt, "a bit array segment pattern")?;
1514 Pattern::BitArray {
1515 location: SrcSpan { start, end },
1516 segments,
1517 }
1518 }
1519
1520 // List
1521 Some((start, Token::LeftSquare, _)) => {
1522 self.advance();
1523 let (elements, elements_end_with_comma) = self.series_of_has_trailing_separator(
1524 &|this| this.parse_pattern(position),
1525 Some(&Token::Comma),
1526 )?;
1527
1528 let mut elements_after_tail = None;
1529 let mut dot_dot_location = None;
1530 let tail = match self.tok0 {
1531 Some((dot_dot_start, Token::DotDot, dot_dot_end)) => {
1532 dot_dot_location = Some((dot_dot_start, dot_dot_end));
1533 if !elements.is_empty() && !elements_end_with_comma {
1534 self.warnings
1535 .push(DeprecatedSyntaxWarning::DeprecatedListPattern {
1536 location: SrcSpan {
1537 start: dot_dot_start,
1538 end: dot_dot_end,
1539 },
1540 });
1541 }
1542
1543 self.advance();
1544 let tail = self.parse_pattern(position)?;
1545 if self.maybe_one(&Token::Comma).is_some() {
1546 // See if there's a list of items after the tail,
1547 // like `[..wibble, wobble, wabble]`
1548 let elements = self.series_of(
1549 &|this| this.parse_pattern(position),
1550 Some(&Token::Comma),
1551 );
1552 match elements {
1553 Err(_) => {}
1554 Ok(elements) => {
1555 elements_after_tail = Some(elements);
1556 }
1557 }
1558 }
1559 Some(tail)
1560 }
1561 _ => None,
1562 };
1563
1564 let (end, closing_square_bracket_end) =
1565 self.expect_one_following_series(&Token::RightSquare, "a pattern")?;
1566
1567 // If there are elements after the tail, return an error
1568 match elements_after_tail {
1569 Some(elements) if !elements.is_empty() => {
1570 let (start, end) = match (dot_dot_location, tail) {
1571 (Some((start, _)), Some(Some(tail))) => (start, tail.location().end),
1572 (Some((start, end)), Some(None)) => (start, end),
1573 (_, _) => (start, end),
1574 };
1575 return parse_error(
1576 ParseErrorType::ListPatternSpreadFollowedByElements,
1577 SrcSpan { start, end },
1578 );
1579 }
1580 _ => {}
1581 }
1582
1583 let tail = match tail {
1584 // There is a tail and it has a Pattern::Var or Pattern::Discard
1585 Some(Some(pattern @ (Pattern::Variable { .. } | Pattern::Discard { .. }))) => {
1586 Some(pattern)
1587 }
1588 // There is a tail and but it has no content, implicit discard
1589 Some(Some(pattern)) => {
1590 return parse_error(ParseErrorType::InvalidTailPattern, pattern.location());
1591 }
1592 Some(None) => Some(Pattern::Discard {
1593 location: SrcSpan {
1594 start: closing_square_bracket_end - 1,
1595 end: closing_square_bracket_end,
1596 },
1597 name: "_".into(),
1598 type_: (),
1599 }),
1600 // No tail specified
1601 None => None,
1602 };
1603
1604 if elements.is_empty() && tail.as_ref().is_some_and(|pattern| pattern.is_discard())
1605 {
1606 self.warnings
1607 .push(DeprecatedSyntaxWarning::DeprecatedListCatchAllPattern {
1608 location: SrcSpan {
1609 start,
1610 end: closing_square_bracket_end,
1611 },
1612 });
1613 }
1614
1615 Pattern::List {
1616 location: SrcSpan {
1617 start,
1618 end: closing_square_bracket_end,
1619 },
1620 elements,
1621 tail: tail.map(|tail_pattern| {
1622 let dot_dot_start = dot_dot_location
1623 .expect("parsed tail with no preceding `..`")
1624 .0;
1625
1626 Box::new(TailPattern {
1627 location: SrcSpan::new(dot_dot_start, tail_pattern.location().end),
1628 pattern: tail_pattern,
1629 })
1630 }),
1631 type_: (),
1632 }
1633 }
1634
1635 // No pattern
1636 t0 => {
1637 self.tok0 = t0;
1638 return Ok(None);
1639 }
1640 };
1641
1642 match self.tok0 {
1643 Some((_, Token::As, _)) => {
1644 self.advance();
1645 let (start, name, end) = self.expect_name(IncorrectNamePosition::AsPattern)?;
1646 Ok(Some(Pattern::Assign {
1647 name,
1648 location: SrcSpan { start, end },
1649 pattern: Box::new(pattern),
1650 }))
1651 }
1652 _ => Ok(Some(pattern)),
1653 }
1654 }
1655
1656 fn add_multi_line_clause_hint(&self, mut err: ParseError) -> ParseError {
1657 if let ParseErrorType::UnexpectedToken { ref mut hint, .. } = err.error {
1658 *hint = Some("Did you mean to wrap a multi line clause in curly braces?".into());
1659 }
1660 err
1661 }
1662
1663 // examples:
1664 // pattern -> expr
1665 // pattern, pattern if -> expr
1666 // pattern, pattern | pattern, pattern if -> expr
1667 fn parse_case_clause(&mut self) -> Result<Option<UntypedClause>, ParseError> {
1668 let patterns = self.parse_patterns(PatternPosition::CaseClause)?;
1669 match &patterns.first() {
1670 Some(lead) => {
1671 let mut alternative_patterns = vec![];
1672 while let Some((vbar_start, vbar_end)) = self.maybe_one(&Token::Vbar) {
1673 let patterns = self.parse_patterns(PatternPosition::CaseClause)?;
1674 if patterns.is_empty() {
1675 return parse_error(
1676 ParseErrorType::ExpectedPattern,
1677 SrcSpan {
1678 start: vbar_start,
1679 end: vbar_end,
1680 },
1681 );
1682 }
1683 alternative_patterns.push(patterns);
1684 }
1685 let guard = self.parse_case_clause_guard()?;
1686 let (arr_s, arr_e) = self
1687 .expect_one(&Token::RArrow)
1688 .map_err(|error| self.add_multi_line_clause_hint(error))?;
1689 let then = self.parse_expression()?;
1690 match then {
1691 Some(then) => Ok(Some(Clause {
1692 location: SrcSpan {
1693 start: lead.location().start,
1694 end: then.location().end,
1695 },
1696 pattern: patterns,
1697 alternative_patterns,
1698 guard,
1699 then,
1700 })),
1701 None => match self.tok0 {
1702 Some((start, Token::DiscardName { .. }, end)) => parse_error(
1703 ParseErrorType::IncorrectName {
1704 kind: IncorrectNamePosition::Variable,
1705 },
1706 SrcSpan { start, end },
1707 ),
1708 _ => parse_error(
1709 ParseErrorType::ExpectedExpr,
1710 SrcSpan {
1711 start: arr_s,
1712 end: arr_e,
1713 },
1714 ),
1715 },
1716 }
1717 }
1718 _ => Ok(None),
1719 }
1720 }
1721 fn parse_patterns(
1722 &mut self,
1723 position: PatternPosition,
1724 ) -> Result<Vec<UntypedPattern>, ParseError> {
1725 self.series_of(&|this| this.parse_pattern(position), Some(&Token::Comma))
1726 }
1727
1728 // examples:
1729 // if a
1730 // if a < b
1731 // if a < b || b < c
1732 fn parse_case_clause_guard(&mut self) -> Result<Option<UntypedClauseGuard>, ParseError> {
1733 let Some((start, end)) = self.maybe_one(&Token::If) else {
1734 return Ok(None);
1735 };
1736 let clause_guard_result = self.parse_clause_guard_inner();
1737 // If inner clause is none, a warning should be shown to let the user
1738 // know that empty clauses in guards are deprecated.
1739 if let Ok(None) = clause_guard_result {
1740 self.warnings
1741 .push(DeprecatedSyntaxWarning::DeprecatedEmptyClauseGuard {
1742 location: SrcSpan { start, end },
1743 });
1744 }
1745 clause_guard_result
1746 }
1747
1748 fn parse_clause_guard_inner(&mut self) -> Result<Option<UntypedClauseGuard>, ParseError> {
1749 let mut opstack = vec![];
1750 let mut estack = vec![];
1751 let mut last_op_start = 0;
1752 let mut last_op_end = 0;
1753 loop {
1754 match self.parse_case_clause_guard_unit()? {
1755 Some(unit) => estack.push(unit),
1756 _ => {
1757 if estack.is_empty() {
1758 return Ok(None);
1759 } else {
1760 return parse_error(
1761 ParseErrorType::OpNakedRight,
1762 SrcSpan {
1763 start: last_op_start,
1764 end: last_op_end,
1765 },
1766 );
1767 }
1768 }
1769 }
1770
1771 let Some((op_s, t, op_e)) = self.tok0.take() else {
1772 break;
1773 };
1774
1775 let Some(precedence) = t.guard_precedence() else {
1776 // Is not Op
1777 self.tok0 = Some((op_s, t, op_e));
1778 break;
1779 };
1780
1781 // Is Op
1782 self.advance();
1783 last_op_start = op_s;
1784 last_op_end = op_e;
1785 let _ = handle_op(
1786 Some(((op_s, t, op_e), precedence)),
1787 &mut opstack,
1788 &mut estack,
1789 &do_reduce_clause_guard,
1790 );
1791 }
1792
1793 Ok(handle_op(
1794 None,
1795 &mut opstack,
1796 &mut estack,
1797 &do_reduce_clause_guard,
1798 ))
1799 }
1800
1801 /// Checks if we have an unexpected left parenthesis and returns appropriate
1802 /// error if it is a function call.
1803 fn parse_function_call_in_clause_guard(&mut self, start: u32) -> Result<(), ParseError> {
1804 if let Some((l_paren_start, l_paren_end)) = self.maybe_one(&Token::LeftParen) {
1805 if let Ok((_, end)) = self
1806 .parse_fn_arguments()
1807 .and(self.expect_one(&Token::RightParen))
1808 {
1809 return parse_error(ParseErrorType::CallInClauseGuard, SrcSpan { start, end });
1810 }
1811
1812 return parse_error(
1813 ParseErrorType::UnexpectedToken {
1814 token: Token::LeftParen,
1815 expected: vec![Token::RArrow.to_string().into()],
1816 hint: None,
1817 },
1818 SrcSpan {
1819 start: l_paren_start,
1820 end: l_paren_end,
1821 },
1822 )
1823 .map_err(|error| self.add_multi_line_clause_hint(error));
1824 }
1825
1826 Ok(())
1827 }
1828
1829 // examples
1830 // a
1831 // 1
1832 // a.1
1833 // { a }
1834 // a || b
1835 // a < b || b < c
1836 fn parse_case_clause_guard_unit(&mut self) -> Result<Option<UntypedClauseGuard>, ParseError> {
1837 match self.tok0.take() {
1838 Some((start, Token::Bang, _)) => {
1839 self.advance();
1840 match self.parse_case_clause_guard_unit()? {
1841 Some(unit) => Ok(Some(ClauseGuard::Not {
1842 location: SrcSpan {
1843 start,
1844 end: unit.location().end,
1845 },
1846 expression: Box::new(unit),
1847 })),
1848 None => {
1849 parse_error(ParseErrorType::ExpectedValue, SrcSpan { start, end: start })
1850 }
1851 }
1852 }
1853
1854 Some((start, Token::Name { name }, end)) => {
1855 self.advance();
1856
1857 self.parse_function_call_in_clause_guard(start)?;
1858
1859 let mut unit =
1860 match self.parse_record_in_clause_guard(&name, SrcSpan { start, end })? {
1861 Some(record) => record,
1862 _ => ClauseGuard::Var {
1863 location: SrcSpan { start, end },
1864 type_: (),
1865 name,
1866 definition_location: SrcSpan::default(),
1867 // We don't know the origin until type analysis, so
1868 // we just put `Generated` here as a placeholder.
1869 origin: VariableOrigin {
1870 syntax: VariableSyntax::Generated,
1871 declaration: VariableDeclaration::Generated,
1872 },
1873 },
1874 };
1875
1876 loop {
1877 let dot_s = match self.maybe_one(&Token::Dot) {
1878 Some((dot_s, _)) => dot_s,
1879 None => return Ok(Some(unit)),
1880 };
1881
1882 match self.next_tok() {
1883 Some((
1884 _,
1885 Token::Int {
1886 value,
1887 int_value: _,
1888 },
1889 int_e,
1890 )) => {
1891 let v = value.replace("_", "");
1892 match u64::from_str(&v) {
1893 Ok(index) => {
1894 unit = ClauseGuard::TupleIndex {
1895 location: SrcSpan {
1896 start: dot_s,
1897 end: int_e,
1898 },
1899 index,
1900 type_: (),
1901 tuple: Box::new(unit),
1902 };
1903 }
1904 _ => {
1905 return parse_error(
1906 ParseErrorType::InvalidTupleAccess,
1907 SrcSpan { start, end },
1908 );
1909 }
1910 }
1911 }
1912
1913 Some((name_start, Token::Name { name: label }, name_end)) => {
1914 self.parse_function_call_in_clause_guard(start)?;
1915
1916 unit = ClauseGuard::FieldAccess {
1917 label_location: SrcSpan {
1918 start: name_start,
1919 end: name_end,
1920 },
1921 index: None,
1922 label,
1923 type_: (),
1924 container: Box::new(unit),
1925 };
1926 }
1927
1928 Some((start, _, end)) => {
1929 return parse_error(
1930 ParseErrorType::IncorrectName {
1931 kind: IncorrectNamePosition::Variable,
1932 },
1933 SrcSpan { start, end },
1934 );
1935 }
1936
1937 _ => return self.next_tok_unexpected(vec!["A positive integer".into()]),
1938 }
1939 }
1940 }
1941
1942 Some((start, Token::LeftBrace, _)) => {
1943 self.advance();
1944 Ok(Some(self.parse_case_clause_guard_block(start)?))
1945 }
1946
1947 t0 => {
1948 self.tok0 = t0;
1949 match self.parse_const_value()? {
1950 Some(const_val) => {
1951 // Constant
1952 Ok(Some(ClauseGuard::Constant(const_val)))
1953 }
1954 _ => Ok(None),
1955 }
1956 }
1957 }
1958 }
1959
1960 fn parse_case_clause_guard_block(
1961 &mut self,
1962 start: u32,
1963 ) -> Result<UntypedClauseGuard, ParseError> {
1964 let body = self.parse_clause_guard_inner()?;
1965
1966 let Some(body) = body else {
1967 let location = match self.next_tok() {
1968 Some((_, Token::RightBrace, end)) => SrcSpan { start, end },
1969 Some((_, _, _)) | None => SrcSpan {
1970 start,
1971 end: start + 1,
1972 },
1973 };
1974
1975 return parse_error(ParseErrorType::EmptyGuardBlock, location);
1976 };
1977
1978 let (_, end) = self.expect_one(&Token::RightBrace)?;
1979 Ok(ClauseGuard::Block {
1980 location: SrcSpan { start, end },
1981 value: Box::new(body),
1982 })
1983 }
1984
1985 fn parse_record_in_clause_guard(
1986 &mut self,
1987 module: &EcoString,
1988 module_location: SrcSpan,
1989 ) -> Result<Option<UntypedClauseGuard>, ParseError> {
1990 let (name, end) = match (self.tok0.take(), self.peek_tok1()) {
1991 (Some((_, Token::Dot, _)), Some(Token::UpName { .. })) => {
1992 self.advance(); // dot
1993 let Some((_, Token::UpName { name }, end)) = self.next_tok() else {
1994 return Ok(None);
1995 };
1996 (name, end)
1997 }
1998 (tok0, _) => {
1999 self.tok0 = tok0;
2000 return Ok(None);
2001 }
2002 };
2003
2004 match self.parse_const_record_finish(
2005 module_location.start,
2006 Some((module.clone(), module_location)),
2007 name,
2008 end,
2009 )? {
2010 Some(record) => Ok(Some(ClauseGuard::Constant(record))),
2011 _ => Ok(None),
2012 }
2013 }
2014
2015 // examples:
2016 // UpName( args )
2017 fn expect_constructor_pattern(
2018 &mut self,
2019 module: Option<(u32, EcoString, u32)>,
2020 position: PatternPosition,
2021 ) -> Result<UntypedPattern, ParseError> {
2022 let (name_start, name, name_end) = self.expect_upname()?;
2023 let mut start = name_start;
2024 let (arguments, spread, end) =
2025 self.parse_constructor_pattern_arguments(name_end, position)?;
2026 if let Some((s, _, _)) = module {
2027 start = s;
2028 }
2029 Ok(Pattern::Constructor {
2030 location: SrcSpan { start, end },
2031 name_location: SrcSpan::new(name_start, name_end),
2032 arguments,
2033 module: module.map(|(start, n, end)| (n, SrcSpan { start, end })),
2034 name,
2035 spread,
2036 constructor: Inferred::Unknown,
2037 type_: (),
2038 })
2039 }
2040
2041 // examples:
2042 // ( args )
2043 #[allow(clippy::type_complexity)]
2044 fn parse_constructor_pattern_arguments(
2045 &mut self,
2046 upname_end: u32,
2047 position: PatternPosition,
2048 ) -> Result<(Vec<CallArg<UntypedPattern>>, Option<SrcSpan>, u32), ParseError> {
2049 if self.maybe_one(&Token::LeftParen).is_some() {
2050 let (arguments, arguments_end_with_comma) = self.series_of_has_trailing_separator(
2051 &|this| this.parse_constructor_pattern_arg(position),
2052 Some(&Token::Comma),
2053 )?;
2054
2055 let spread = self
2056 .maybe_one(&Token::DotDot)
2057 .map(|(start, end)| SrcSpan { start, end });
2058
2059 if let Some(spread_location) = spread {
2060 let _ = self.maybe_one(&Token::Comma);
2061 if !arguments.is_empty() && !arguments_end_with_comma {
2062 self.warnings
2063 .push(DeprecatedSyntaxWarning::DeprecatedRecordSpreadPattern {
2064 location: spread_location,
2065 });
2066 }
2067 }
2068 let (_, end) = self.expect_one(&Token::RightParen)?;
2069 Ok((arguments, spread, end))
2070 } else {
2071 Ok((vec![], None, upname_end))
2072 }
2073 }
2074
2075 // examples:
2076 // a: <pattern>
2077 // a:
2078 // <pattern>
2079 fn parse_constructor_pattern_arg(
2080 &mut self,
2081 position: PatternPosition,
2082 ) -> Result<Option<CallArg<UntypedPattern>>, ParseError> {
2083 match (self.tok0.take(), self.tok1.take()) {
2084 // named arg
2085 (Some((start, Token::Name { name }, _)), Some((_, Token::Colon, end))) => {
2086 self.advance();
2087 self.advance();
2088 match self.parse_pattern(position)? {
2089 Some(value) => Ok(Some(CallArg {
2090 implicit: None,
2091 location: SrcSpan {
2092 start,
2093 end: value.location().end,
2094 },
2095 label: Some(name),
2096 value,
2097 })),
2098 _ => {
2099 // Argument supplied with a label shorthand.
2100 Ok(Some(CallArg {
2101 implicit: None,
2102 location: SrcSpan { start, end },
2103 label: Some(name.clone()),
2104 value: UntypedPattern::Variable {
2105 origin: VariableOrigin {
2106 syntax: VariableSyntax::LabelShorthand(name.clone()),
2107 declaration: position.to_declaration(),
2108 },
2109 name,
2110 location: SrcSpan { start, end },
2111 type_: (),
2112 },
2113 }))
2114 }
2115 }
2116 }
2117 // unnamed arg
2118 (t0, t1) => {
2119 self.tok0 = t0;
2120 self.tok1 = t1;
2121 match self.parse_pattern(position)? {
2122 Some(value) => Ok(Some(CallArg {
2123 implicit: None,
2124 location: value.location(),
2125 label: None,
2126 value,
2127 })),
2128 _ => Ok(None),
2129 }
2130 }
2131 }
2132 }
2133
2134 // examples:
2135 // a: expr
2136 // a:
2137 fn parse_record_update_arg(&mut self) -> Result<Option<UntypedRecordUpdateArg>, ParseError> {
2138 match self.maybe_name() {
2139 Some((start, label, _)) => {
2140 let (_, end) = self.expect_one(&Token::Colon)?;
2141 let value = self.parse_expression()?;
2142 match value {
2143 Some(value) => Ok(Some(UntypedRecordUpdateArg {
2144 label,
2145 location: SrcSpan {
2146 start,
2147 end: value.location().end,
2148 },
2149 value,
2150 })),
2151 _ => {
2152 // Argument supplied with a label shorthand.
2153 Ok(Some(UntypedRecordUpdateArg {
2154 label: label.clone(),
2155 location: SrcSpan { start, end },
2156 value: UntypedExpr::Var {
2157 name: label,
2158 location: SrcSpan { start, end },
2159 },
2160 }))
2161 }
2162 }
2163 }
2164 _ => Ok(None),
2165 }
2166 }
2167
2168 //
2169 // Parse Functions
2170 //
2171
2172 // Starts after "fn"
2173 //
2174 // examples:
2175 // fn a(name: String) -> String { .. }
2176 // pub fn a(name name: String) -> String { .. }
2177 fn parse_function(
2178 &mut self,
2179 start: u32,
2180 public: bool,
2181 is_anon: bool,
2182 attributes: &mut Attributes,
2183 ) -> Result<Option<UntypedDefinition>, ParseError> {
2184 let documentation = if is_anon {
2185 None
2186 } else {
2187 self.take_documentation(start)
2188 };
2189 let mut name = None;
2190 if !is_anon {
2191 let (name_start, n, name_end) = self.expect_name(IncorrectNamePosition::Function)?;
2192 name = Some((
2193 SrcSpan {
2194 start: name_start,
2195 end: name_end,
2196 },
2197 n,
2198 ));
2199 }
2200 if let Some((less_start, less_end)) = self.maybe_one(&Token::Less) {
2201 return Err(ParseError {
2202 error: ParseErrorType::FunctionDefinitionAngleGenerics,
2203 location: SrcSpan {
2204 start: less_start,
2205 end: less_end,
2206 },
2207 });
2208 }
2209 let _ = self
2210 .expect_one(&Token::LeftParen)
2211 .map_err(|error| self.add_anon_function_hint(error))?;
2212 let arguments =
2213 self.series_of(&|this| this.parse_fn_param(is_anon), Some(&Token::Comma))?;
2214 let (_, rpar_e) =
2215 self.expect_one_following_series(&Token::RightParen, "a function parameter")?;
2216
2217 // Check for TypeScript-style return type annotation (:) instead of arrow (->)
2218 if let Some((colon_start, colon_end)) = self.maybe_one(&Token::Colon) {
2219 return Err(ParseError {
2220 error: ParseErrorType::UnexpectedToken {
2221 token: Token::Colon,
2222 expected: vec!["`->`".into()],
2223 hint: Some("Return type annotations are written using `->`, not `:`".into()),
2224 },
2225 location: SrcSpan {
2226 start: colon_start,
2227 end: colon_end,
2228 },
2229 });
2230 }
2231
2232 let return_annotation = self.parse_type_annotation(&Token::RArrow)?;
2233
2234 let (body_start, body, end, end_position) = match self.maybe_one(&Token::LeftBrace) {
2235 Some((left_brace_start, _)) => {
2236 let some_body = self.parse_statement_seq()?;
2237 let (_, right_brace_end) = self.expect_one(&Token::RightBrace)?;
2238 let end = return_annotation
2239 .as_ref()
2240 .map(|l| l.location().end)
2241 .unwrap_or(rpar_e);
2242 let body = match some_body {
2243 None => vec![Statement::Expression(UntypedExpr::Todo {
2244 kind: TodoKind::EmptyFunction {
2245 function_location: SrcSpan { start, end },
2246 },
2247 location: SrcSpan {
2248 start: left_brace_start + 1,
2249 end: right_brace_end,
2250 },
2251 message: None,
2252 })],
2253 Some((body, _)) => body.to_vec(),
2254 };
2255
2256 (Some(left_brace_start), body, end, right_brace_end)
2257 }
2258
2259 None => (None, vec![], rpar_e, rpar_e),
2260 };
2261
2262 Ok(Some(Definition::Function(Function {
2263 documentation,
2264 location: SrcSpan { start, end },
2265 end_position,
2266 body_start,
2267 publicity: self.publicity(public, attributes.internal)?,
2268 name,
2269 arguments,
2270 body,
2271 return_type: (),
2272 return_annotation,
2273 deprecation: std::mem::take(&mut attributes.deprecated),
2274 external_erlang: attributes.external_erlang.take(),
2275 external_javascript: attributes.external_javascript.take(),
2276 external_cranelift: attributes.external_cranelift.take(),
2277 implementations: Implementations {
2278 gleam: true,
2279 can_run_on_erlang: true,
2280 can_run_on_javascript: true,
2281 can_run_on_cranelift: true,
2282 uses_erlang_externals: false,
2283 uses_javascript_externals: false,
2284 uses_cranelift_externals: false,
2285 },
2286 purity: Purity::Pure,
2287 })))
2288 }
2289
2290 fn add_anon_function_hint(&self, mut err: ParseError) -> ParseError {
2291 if let ParseErrorType::UnexpectedToken {
2292 ref mut hint,
2293 token: Token::Name { .. },
2294 ..
2295 } = err.error
2296 {
2297 *hint = Some("Only module-level functions can be named.".into());
2298 }
2299 err
2300 }
2301
2302 fn publicity(
2303 &self,
2304 public: bool,
2305 internal: InternalAttribute,
2306 ) -> Result<Publicity, ParseError> {
2307 match (internal, public) {
2308 (InternalAttribute::Missing, true) => Ok(Publicity::Public),
2309 (InternalAttribute::Missing, false) => Ok(Publicity::Private),
2310 (InternalAttribute::Present(location), true) => Ok(Publicity::Internal {
2311 attribute_location: Some(location),
2312 }),
2313 (InternalAttribute::Present(location), false) => Err(ParseError {
2314 error: ParseErrorType::RedundantInternalAttribute,
2315 location,
2316 }),
2317 }
2318 }
2319
2320 // Parse a single function definition param
2321 //
2322 // examples:
2323 // _
2324 // a
2325 // a a
2326 // a _
2327 // a _:A
2328 // a a:A
2329 fn parse_fn_param(&mut self, is_anon: bool) -> Result<Option<UntypedArg>, ParseError> {
2330 let (start, names, mut end) = match (self.tok0.take(), self.tok1.take()) {
2331 // labeled discard
2332 (
2333 Some((start, Token::Name { name: label }, tok0_end)),
2334 Some((name_start, Token::DiscardName { name }, end)),
2335 ) => {
2336 if is_anon {
2337 return parse_error(
2338 ParseErrorType::UnexpectedLabel,
2339 SrcSpan {
2340 start,
2341 end: tok0_end,
2342 },
2343 );
2344 }
2345
2346 self.advance();
2347 self.advance();
2348 (
2349 start,
2350 ArgNames::LabelledDiscard {
2351 name,
2352 name_location: SrcSpan::new(name_start, end),
2353 label,
2354 label_location: SrcSpan::new(start, tok0_end),
2355 },
2356 end,
2357 )
2358 }
2359 // discard
2360 (Some((start, Token::DiscardName { name }, end)), t1) => {
2361 self.tok1 = t1;
2362 self.advance();
2363 (
2364 start,
2365 ArgNames::Discard {
2366 name,
2367 location: SrcSpan { start, end },
2368 },
2369 end,
2370 )
2371 }
2372 // labeled name
2373 (
2374 Some((start, Token::Name { name: label }, tok0_end)),
2375 Some((name_start, Token::Name { name }, end)),
2376 ) => {
2377 if is_anon {
2378 return parse_error(
2379 ParseErrorType::UnexpectedLabel,
2380 SrcSpan {
2381 start,
2382 end: tok0_end,
2383 },
2384 );
2385 }
2386
2387 self.advance();
2388 self.advance();
2389 (
2390 start,
2391 ArgNames::NamedLabelled {
2392 name,
2393 name_location: SrcSpan::new(name_start, end),
2394 label,
2395 label_location: SrcSpan::new(start, tok0_end),
2396 },
2397 end,
2398 )
2399 }
2400 // name
2401 (Some((start, Token::Name { name }, end)), t1) => {
2402 self.tok1 = t1;
2403 self.advance();
2404 (
2405 start,
2406 ArgNames::Named {
2407 name,
2408 location: SrcSpan { start, end },
2409 },
2410 end,
2411 )
2412 }
2413 (t0, t1) => {
2414 self.tok0 = t0;
2415 self.tok1 = t1;
2416 return Ok(None);
2417 }
2418 };
2419 let annotation = match self.parse_type_annotation(&Token::Colon)? {
2420 Some(a) => {
2421 end = a.location().end;
2422 Some(a)
2423 }
2424 _ => None,
2425 };
2426 Ok(Some(Arg {
2427 location: SrcSpan { start, end },
2428 type_: (),
2429 names,
2430 annotation,
2431 }))
2432 }
2433
2434 // Parse function call arguments, no parens
2435 //
2436 // examples:
2437 // _
2438 // expr, expr
2439 // a: _, expr
2440 // a: expr, _, b: _
2441 fn parse_fn_arguments(&mut self) -> Result<Vec<ParserArg>, ParseError> {
2442 self.series_of(&Parser::parse_fn_argument, Some(&Token::Comma))
2443 }
2444
2445 // Parse a single function call arg
2446 //
2447 // examples:
2448 // _
2449 // expr
2450 // a: _
2451 // a: expr
2452 fn parse_fn_argument(&mut self) -> Result<Option<ParserArg>, ParseError> {
2453 let label = match (self.tok0.take(), self.tok1.take()) {
2454 (Some((start, Token::Name { name }, _)), Some((_, Token::Colon, end))) => {
2455 self.advance();
2456 self.advance();
2457 Some((start, name, end))
2458 }
2459 (t0, t1) => {
2460 self.tok0 = t0;
2461 self.tok1 = t1;
2462 None
2463 }
2464 };
2465
2466 match self.parse_expression()? {
2467 Some(value) => {
2468 let arg = match label {
2469 Some((start, label, _)) => CallArg {
2470 implicit: None,
2471 label: Some(label),
2472 location: SrcSpan {
2473 start,
2474 end: value.location().end,
2475 },
2476 value,
2477 },
2478 _ => CallArg {
2479 implicit: None,
2480 label: None,
2481 location: value.location(),
2482 value,
2483 },
2484 };
2485 Ok(Some(ParserArg::Arg(Box::new(arg))))
2486 }
2487 _ => {
2488 match self.maybe_discard_name() {
2489 Some((name_start, name, name_end)) => {
2490 let arg = match label {
2491 Some((label_start, label, _)) => ParserArg::Hole {
2492 label: Some(label),
2493 arg_location: SrcSpan {
2494 start: label_start,
2495 end: name_end,
2496 },
2497 discard_location: SrcSpan {
2498 start: name_start,
2499 end: name_end,
2500 },
2501 name,
2502 },
2503 _ => ParserArg::Hole {
2504 label: None,
2505 arg_location: SrcSpan {
2506 start: name_start,
2507 end: name_end,
2508 },
2509 discard_location: SrcSpan {
2510 start: name_start,
2511 end: name_end,
2512 },
2513 name,
2514 },
2515 };
2516
2517 Ok(Some(arg))
2518 }
2519 _ => {
2520 match label {
2521 Some((start, label, end)) => {
2522 // Argument supplied with a label shorthand.
2523 Ok(Some(ParserArg::Arg(Box::new(CallArg {
2524 implicit: None,
2525 label: Some(label.clone()),
2526 location: SrcSpan { start, end },
2527 value: UntypedExpr::Var {
2528 name: label,
2529 location: SrcSpan { start, end },
2530 },
2531 }))))
2532 }
2533 _ => Ok(None),
2534 }
2535 }
2536 }
2537 }
2538 }
2539 }
2540
2541 //
2542 // Parse Custom Types
2543 //
2544
2545 // examples:
2546 // type A { A }
2547 // type A { A(String) }
2548 // type Box(inner_type) { Box(inner: inner_type) }
2549 // type NamedBox(inner_type) { Box(String, inner: inner_type) }
2550 fn parse_custom_type(
2551 &mut self,
2552 start: u32,
2553 public: bool,
2554 opaque: bool,
2555 attributes: &mut Attributes,
2556 ) -> Result<Option<UntypedDefinition>, ParseError> {
2557 let documentation = self.take_documentation(start);
2558 let (name_start, name, parameters, end, name_end) = self.expect_type_name()?;
2559 let name_location = SrcSpan::new(name_start, name_end);
2560
2561 let (constructors, end_position) = match self.tok0.take() {
2562 // If we see `type Wibble {`, then we know we're parsing a custom type.
2563 Some((_, Token::LeftBrace, _)) => {
2564 self.advance();
2565
2566 // If we see a lowercase name, rather than an uppercase one. We
2567 // know there's a syntax error! So now we can try and provide a
2568 // nice error message, based on what that wrong code looks like.
2569 if let Some((name_start, Token::Name { .. }, name_end)) = &self.tok0 {
2570 return Err(self.invalid_record_constructor_error(
2571 name,
2572 public,
2573 opaque,
2574 *name_start,
2575 *name_end,
2576 ));
2577 }
2578
2579 let constructors = self.series_of(
2580 &|this| this.parse_record_constructor(),
2581 // No separator
2582 None,
2583 )?;
2584 let close_end = self.expect_custom_type_close()?;
2585 (constructors, close_end)
2586 }
2587
2588 // If we see `type Wibble =` then we know we're parsing a type alias.
2589 Some((equal_start, Token::Equal, equal_end)) => {
2590 self.advance();
2591
2592 if opaque {
2593 return parse_error(ParseErrorType::OpaqueTypeAlias, SrcSpan { start, end });
2594 }
2595
2596 if let Some(type_) = self.parse_type()? {
2597 return Ok(Some(Definition::TypeAlias(TypeAlias {
2598 documentation,
2599 location: SrcSpan::new(start, type_.location().end),
2600 publicity: self.publicity(public, attributes.internal)?,
2601 alias: name,
2602 name_location,
2603 parameters,
2604 type_ast: type_,
2605 type_: (),
2606 deprecation: std::mem::take(&mut attributes.deprecated),
2607 })));
2608 } else {
2609 return parse_error(
2610 ParseErrorType::ExpectedType,
2611 SrcSpan::new(equal_start, equal_end),
2612 );
2613 }
2614 }
2615
2616 token @ (Some(_) | None) => {
2617 self.tok0 = token;
2618 (vec![], end)
2619 }
2620 };
2621
2622 Ok(Some(Definition::CustomType(CustomType {
2623 documentation,
2624 location: SrcSpan { start, end },
2625 end_position,
2626 publicity: self.publicity(public, attributes.internal)?,
2627 opaque,
2628 name,
2629 name_location,
2630 parameters,
2631 constructors,
2632 typed_parameters: vec![],
2633 deprecation: std::mem::take(&mut attributes.deprecated),
2634 external_erlang: std::mem::take(&mut attributes.external_erlang),
2635 external_javascript: std::mem::take(&mut attributes.external_javascript),
2636 })))
2637 }
2638
2639 fn parse_record_constructor(&mut self) -> Result<Option<RecordConstructor<()>>, ParseError> {
2640 // The only attribute supported on constructors is @deprecated
2641 let mut attributes = Attributes::default();
2642 let attr_loc = self.parse_attributes(&mut attributes)?;
2643
2644 if let Some(attr_span) = attr_loc {
2645 // Expecting all but the deprecated atterbutes to be default
2646 if attributes.external_erlang.is_some()
2647 || attributes.external_javascript.is_some()
2648 || attributes.target.is_some()
2649 || attributes.internal != InternalAttribute::Missing
2650 {
2651 return parse_error(ParseErrorType::UnknownAttributeRecordVariant, attr_span);
2652 }
2653 }
2654
2655 match self.maybe_upname() {
2656 Some((name_start, constructor_name, name_end)) => {
2657 let documentation = self.take_documentation(name_start);
2658 let (arguments, arguments_end) = self.parse_record_constructor_arguments()?;
2659
2660 Ok(Some(RecordConstructor {
2661 location: SrcSpan {
2662 start: name_start,
2663 end: arguments_end.max(name_end),
2664 },
2665 name_location: SrcSpan {
2666 start: name_start,
2667 end: name_end,
2668 },
2669 name: constructor_name,
2670 arguments,
2671 documentation,
2672 deprecation: attributes.deprecated,
2673 }))
2674 }
2675 _ => Ok(None),
2676 }
2677 }
2678
2679 /// This takes place when we find a lowercase name as a record constructor
2680 /// variant (that name is passed as an argument here).
2681 /// We want to look at the following tokens to produce a nice error message:
2682 ///
2683 /// ```gleam
2684 /// pub type Wibble {
2685 /// wibble
2686 /// //^^^^^^ Error, this should be uppercase!
2687 /// }
2688 /// ```
2689 ///
2690 /// But if the thing looks like a record definition, we want a specialised
2691 /// error message:
2692 ///
2693 /// ```gleam
2694 /// pub type Wibble {
2695 /// wibble: Int,
2696 /// wobble: String
2697 /// }
2698 /// // Suggest wrapping this in a constructor.
2699 /// ```
2700 ///
2701 fn invalid_record_constructor_error(
2702 &mut self,
2703 type_name: EcoString,
2704 public: bool,
2705 opaque: bool,
2706 name_start: u32,
2707 name_end: u32,
2708 ) -> ParseError {
2709 let fields = self.series_of(
2710 &|this| this.parse_record_constructor_field(),
2711 Some(&Token::Comma),
2712 );
2713
2714 match fields {
2715 // If there's a list of fields right inside the type that means the
2716 // developer might have forgotten to wrap the thing in a constructor.
2717 // Basically writing something like this:
2718 //
2719 // ```gleam
2720 // pub type Wibble {
2721 // String,
2722 // wibble: Int,
2723 // }
2724 // ```
2725 //
2726 // So we want to produce a specialised error message pointing them
2727 // in the right direction.
2728 Ok(fields) if let Some((_, Token::RightBrace, _)) = self.tok0 => ParseError {
2729 location: SrcSpan {
2730 start: fields
2731 .first()
2732 .map_or(name_start, |field| field.location.start),
2733 end: fields.last().map_or(name_end, |field| field.location.end),
2734 },
2735 error: ParseErrorType::ExpectedRecordConstructor {
2736 type_name,
2737 public,
2738 opaque,
2739 fields,
2740 },
2741 },
2742
2743 // Otherwise we fall back to telling them the lowercase name should
2744 // be uppercased!
2745 Ok(_) | Err(_) => ParseError {
2746 error: ParseErrorType::IncorrectUpName,
2747 location: SrcSpan {
2748 start: name_start,
2749 end: name_end,
2750 },
2751 },
2752 }
2753 }
2754
2755 // examples:
2756 // *no args*
2757 // ()
2758 // (a, b)
2759 fn parse_record_constructor_arguments(
2760 &mut self,
2761 ) -> Result<(Vec<RecordConstructorArg<()>>, u32), ParseError> {
2762 if self.maybe_one(&Token::LeftParen).is_some() {
2763 let arguments = self.series_of(
2764 &|this| this.parse_record_constructor_field(),
2765 Some(&Token::Comma),
2766 )?;
2767 let (_, end) = self
2768 .expect_one_following_series(&Token::RightParen, "a constructor argument name")?;
2769 Ok((arguments, end))
2770 } else {
2771 Ok((vec![], 0))
2772 }
2773 }
2774
2775 fn parse_record_constructor_field(
2776 &mut self,
2777 ) -> Result<Option<RecordConstructorArg<()>>, ParseError> {
2778 match (self.tok0.take(), self.tok1.take()) {
2779 (Some((start, Token::Name { name }, name_end)), Some((_, Token::Colon, end))) => {
2780 let _ = self.next_tok();
2781 let _ = self.next_tok();
2782 let doc = self.take_documentation(start);
2783 match self.parse_type()? {
2784 Some(type_ast) => {
2785 let end = type_ast.location().end;
2786 Ok(Some(RecordConstructorArg {
2787 label: Some((SrcSpan::new(start, name_end), name)),
2788 ast: type_ast,
2789 location: SrcSpan { start, end },
2790 type_: (),
2791 doc,
2792 }))
2793 }
2794 None => parse_error(ParseErrorType::ExpectedType, SrcSpan { start, end }),
2795 }
2796 }
2797 (t0, t1) => {
2798 self.tok0 = t0;
2799 self.tok1 = t1;
2800 match self.parse_type()? {
2801 Some(type_ast) => {
2802 let doc = match &self.tok0 {
2803 Some((start, _, _)) => self.take_documentation(*start),
2804 None => None,
2805 };
2806 let type_location = type_ast.location();
2807 Ok(Some(RecordConstructorArg {
2808 label: None,
2809 ast: type_ast,
2810 location: type_location,
2811 type_: (),
2812 doc,
2813 }))
2814 }
2815 None => Ok(None),
2816 }
2817 }
2818 }
2819 }
2820
2821 // examples:
2822 // A
2823 // A(one, two)
2824 fn expect_type_name(
2825 &mut self,
2826 ) -> Result<(u32, EcoString, Vec<SpannedString>, u32, u32), ParseError> {
2827 let (start, upname, end) = self.expect_upname()?;
2828 if let Some((par_s, _)) = self.maybe_one(&Token::LeftParen) {
2829 let arguments = self.series_of(&|this| Ok(this.maybe_name()), Some(&Token::Comma))?;
2830 let (_, par_e) = self.expect_one_following_series(&Token::RightParen, "a name")?;
2831 if arguments.is_empty() {
2832 return parse_error(
2833 ParseErrorType::TypeDefinitionNoArguments,
2834 SrcSpan::new(par_s, par_e),
2835 );
2836 }
2837 let arguments2 = arguments
2838 .into_iter()
2839 .map(|(start, name, end)| (SrcSpan { start, end }, name))
2840 .collect();
2841 Ok((start, upname, arguments2, par_e, end))
2842 } else if let Some((less_start, less_end)) = self.maybe_one(&Token::Less) {
2843 let mut arguments = self.series_of(
2844 &|this|
2845 // Permit either names (`a`) or upnames (`A`) in this error-handling mode,
2846 // as upnames are common in other languages. Convert to lowercase so the
2847 // example is correct whichever was used.
2848 Ok(this.maybe_name()
2849 .or_else(|| this.maybe_upname())
2850 .map(|(_, name, _)| name.to_lowercase())),
2851 Some(&Token::Comma),
2852 )?;
2853
2854 // If no type arguments were parsed, fall back to a dummy type argument as an example,
2855 // because `Type()` would be invalid
2856 if arguments.is_empty() {
2857 arguments = vec!["value".into()];
2858 }
2859
2860 Err(ParseError {
2861 error: ParseErrorType::TypeDefinitionAngleGenerics {
2862 name: upname,
2863 arguments,
2864 },
2865 location: SrcSpan {
2866 start: less_start,
2867 end: less_end,
2868 },
2869 })
2870 } else {
2871 Ok((start, upname, vec![], end, end))
2872 }
2873 }
2874
2875 //
2876 // Parse Type Annotations
2877 //
2878
2879 // examples:
2880 // :a
2881 // :Int
2882 // :Result(a, _)
2883 // :Result(Result(a, e), #(_, String))
2884 fn parse_type_annotation(&mut self, start_tok: &Token) -> Result<Option<TypeAst>, ParseError> {
2885 if let Some((start, end)) = self.maybe_one(start_tok) {
2886 match self.parse_type() {
2887 Ok(None) => parse_error(ParseErrorType::ExpectedType, SrcSpan { start, end }),
2888 other => other,
2889 }
2890 } else {
2891 Ok(None)
2892 }
2893 }
2894
2895 // Parse the type part of a type annotation, same as `parse_type_annotation` minus the ":"
2896 fn parse_type(&mut self) -> Result<Option<TypeAst>, ParseError> {
2897 match self.tok0.take() {
2898 // Type hole
2899 Some((start, Token::DiscardName { name }, end)) => {
2900 self.advance();
2901 Ok(Some(TypeAst::Hole(TypeAstHole {
2902 location: SrcSpan { start, end },
2903 name,
2904 })))
2905 }
2906
2907 // Tuple
2908 Some((start, Token::Hash, _)) => {
2909 self.advance();
2910 let _ = self.expect_one(&Token::LeftParen)?;
2911 let elements = self.parse_types()?;
2912 let (_, end) = self.expect_one(&Token::RightParen)?;
2913 Ok(Some(TypeAst::Tuple(TypeAstTuple {
2914 location: SrcSpan { start, end },
2915 elements,
2916 })))
2917 }
2918
2919 // Function
2920 Some((start, Token::Fn, _)) => {
2921 self.advance();
2922 let _ = self.expect_one(&Token::LeftParen)?;
2923 let arguments = self.series_of(&|this| this.parse_type(), Some(&Token::Comma))?;
2924 let _ = self.expect_one_following_series(&Token::RightParen, "a type")?;
2925 let (arr_s, arr_e) = self.expect_one(&Token::RArrow)?;
2926 let return_ = self.parse_type()?;
2927 match return_ {
2928 Some(return_) => Ok(Some(TypeAst::Fn(TypeAstFn {
2929 location: SrcSpan {
2930 start,
2931 end: return_.location().end,
2932 },
2933 return_: Box::new(return_),
2934 arguments,
2935 }))),
2936 _ => parse_error(
2937 ParseErrorType::ExpectedType,
2938 SrcSpan {
2939 start: arr_s,
2940 end: arr_e,
2941 },
2942 ),
2943 }
2944 }
2945
2946 // Constructor function
2947 Some((start, Token::UpName { name }, end)) => {
2948 self.advance();
2949 let name = TypeAstConstructorName::Unqualified {
2950 name,
2951 location: SrcSpan::new(start, end),
2952 };
2953 self.parse_type_name_finish(start, end, name)
2954 }
2955
2956 // Constructor Module or type Variable
2957 Some((start, Token::Name { name: module }, end)) => {
2958 self.advance();
2959
2960 if let Some((_, dot_end)) = self.maybe_one(&Token::Dot) {
2961 let module_location = SrcSpan::new(start, end);
2962 match self.maybe_upname() {
2963 Some((name_start, name, name_end)) => {
2964 let name = TypeAstConstructorName::Qualified {
2965 module,
2966 module_location,
2967 dot_location: dot_end,
2968 name: Some((name, SrcSpan::new(name_start, name_end))),
2969 };
2970 self.parse_type_name_finish(start, name_end, name)
2971 }
2972 None => {
2973 let name = TypeAstConstructorName::Qualified {
2974 module,
2975 module_location,
2976 dot_location: dot_end,
2977 name: None,
2978 };
2979 self.parse_type_name_finish(start, dot_end, name)
2980 }
2981 }
2982 } else {
2983 Ok(Some(TypeAst::Var(TypeAstVar {
2984 location: SrcSpan { start, end },
2985 name: module,
2986 })))
2987 }
2988 }
2989
2990 t0 => {
2991 self.tok0 = t0;
2992 Ok(None)
2993 }
2994 }
2995 }
2996
2997 // Parse the '( ... )' of a type name
2998 fn parse_type_name_finish(
2999 &mut self,
3000 start: u32,
3001 end: u32,
3002 name: TypeAstConstructorName,
3003 ) -> Result<Option<TypeAst>, ParseError> {
3004 if let Some((left_paren_start, left_paren_end)) = self.maybe_one(&Token::LeftParen) {
3005 // In case the type is qualified and is missing a name, it doesn't
3006 // make sense to parse a types list: we don't want to accept
3007 // something like `wibble.(a, b)`.
3008 // Instead we want to say that `(` is unexpected and we were
3009 // expecting a type name instead:
3010 if name.name().is_none() {
3011 return Err(ParseError {
3012 error: ParseErrorType::ExpectedUpName,
3013 location: SrcSpan::new(left_paren_start, left_paren_end),
3014 });
3015 }
3016
3017 let arguments = self.parse_types()?;
3018 let (_, right_paren_end) = self.expect_one(&Token::RightParen)?;
3019 Ok(Some(TypeAst::Constructor(TypeAstConstructor {
3020 location: SrcSpan::new(start, right_paren_end),
3021 name,
3022 arguments,
3023 start_parentheses: Some(left_paren_start),
3024 })))
3025 } else if let Some((less_start, less_end)) = self.maybe_one(&Token::Less) {
3026 let location = SrcSpan::new(less_start, less_end);
3027 let (module, name) = match name {
3028 TypeAstConstructorName::Qualified {
3029 module,
3030 name: Some((name, _)),
3031 ..
3032 } => (Some(module), name),
3033 TypeAstConstructorName::Unqualified { name, .. } => (None, name),
3034
3035 // If we're here it means someone has typed something truly
3036 // wrong that looks like this: `wibble.<`.
3037 // In this case the hint about angle brackets wouldn't make much
3038 // sense, so we fallback to just reporting an invalid token
3039 // error saying we were expecting an uppercase name
3040 TypeAstConstructorName::Qualified { name: None, .. } => {
3041 return Err(ParseError {
3042 error: ParseErrorType::ExpectedUpName,
3043 location,
3044 });
3045 }
3046 };
3047
3048 // Otherwise we try and report a nicer error, suggesting one should
3049 // use `(a, b)` instead of `<a, b>`.
3050 let arguments = self.parse_types()?;
3051 Err(ParseError {
3052 location,
3053 error: ParseErrorType::TypeUsageAngleGenerics {
3054 name,
3055 module,
3056 arguments,
3057 },
3058 })
3059 } else {
3060 Ok(Some(TypeAst::Constructor(TypeAstConstructor {
3061 location: SrcSpan { start, end },
3062 name,
3063 arguments: vec![],
3064 start_parentheses: None,
3065 })))
3066 }
3067 }
3068
3069 // For parsing a comma separated "list" of types, for tuple, constructor, and function
3070 fn parse_types(&mut self) -> Result<Vec<TypeAst>, ParseError> {
3071 let elements = self.series_of(&|this| this.parse_type(), Some(&Token::Comma))?;
3072 Ok(elements)
3073 }
3074
3075 //
3076 // Parse Imports
3077 //
3078
3079 // examples:
3080 // import a
3081 // import a/b
3082 // import a/b.{c}
3083 // import a/b.{c as d} as e
3084 fn parse_import(&mut self, import_start: u32) -> Result<Option<UntypedDefinition>, ParseError> {
3085 let mut start = 0;
3086 let mut end;
3087 let mut module = EcoString::new();
3088 let mut last_segment_end;
3089
3090 // Gather module names
3091 loop {
3092 let (s, name, e) = self.expect_name(IncorrectNamePosition::Module)?;
3093 if module.is_empty() {
3094 start = s;
3095 } else {
3096 module.push('/');
3097 }
3098 module.push_str(&name);
3099 end = e;
3100 last_segment_end = e;
3101
3102 // Useful error for : import a/.{b}
3103 if let Some((s, _)) = self.maybe_one(&Token::SlashDot) {
3104 return parse_error(
3105 ParseErrorType::ExpectedName,
3106 SrcSpan {
3107 start: s + 1,
3108 end: s + 1,
3109 },
3110 );
3111 }
3112
3113 // break if there's no trailing slash
3114 if self.maybe_one(&Token::Slash).is_none() {
3115 break;
3116 }
3117 }
3118
3119 let (_, documentation) = self.take_documentation(start).unzip();
3120
3121 // Gather imports
3122 let mut unqualified_values = vec![];
3123 let mut unqualified_types = vec![];
3124
3125 if let Some((dot_start, dot_end)) = self.maybe_one(&Token::Dot) {
3126 if let Err(e) = self.expect_one(&Token::LeftBrace) {
3127 // If the module does contain a '/', then it's unlikely that the user
3128 // intended for the import to be pythonic, so skip this.
3129 if module.contains('/') {
3130 return Err(e);
3131 }
3132
3133 // Catch `import gleam.io` and provide a more helpful error...
3134 let ParseErrorType::UnexpectedToken {
3135 token: Token::Name { name } | Token::UpName { name },
3136 ..
3137 } = &e.error
3138 else {
3139 return Err(e);
3140 };
3141
3142 return Err(ParseError {
3143 error: ParseErrorType::IncorrectImportModuleSeparator {
3144 module,
3145 item: name.clone(),
3146 },
3147 location: SrcSpan::new(dot_start, dot_end),
3148 });
3149 }
3150
3151 let parsed = self.parse_unqualified_imports()?;
3152 unqualified_types = parsed.types;
3153 unqualified_values = parsed.values;
3154 let (_, e) = self.expect_one(&Token::RightBrace)?;
3155 end = e;
3156 }
3157
3158 // Parse as_name
3159 let mut as_name = None;
3160 if let Some((as_start, _)) = self.maybe_one(&Token::As) {
3161 let (_, name, e) = self.expect_assign_name()?;
3162
3163 end = e;
3164 as_name = Some((
3165 name,
3166 SrcSpan {
3167 start: as_start,
3168 end,
3169 },
3170 ));
3171 }
3172
3173 Ok(Some(Definition::Import(Import {
3174 documentation,
3175 location: SrcSpan {
3176 start: import_start,
3177 end,
3178 },
3179 module_location: SrcSpan {
3180 start,
3181 end: last_segment_end,
3182 },
3183 unqualified_values,
3184 unqualified_types,
3185 module,
3186 as_name,
3187 package: (),
3188 })))
3189 }
3190
3191 // [Name (as Name)? | UpName (as Name)? ](, [Name (as Name)? | UpName (as Name)?])*,?
3192 fn parse_unqualified_imports(&mut self) -> Result<ParsedUnqualifiedImports, ParseError> {
3193 let mut imports = ParsedUnqualifiedImports::default();
3194 loop {
3195 // parse imports
3196 match self.tok0.take() {
3197 Some((start, Token::Name { name }, end)) => {
3198 self.advance();
3199 let location = SrcSpan { start, end };
3200 let mut import = UnqualifiedImport {
3201 name,
3202 location,
3203 name_position: location.start,
3204 as_name: None,
3205 };
3206 if self.maybe_one(&Token::As).is_some() {
3207 let (_, as_name, end) =
3208 self.expect_name(IncorrectNamePosition::AsPattern)?;
3209 import.as_name = Some(as_name);
3210 import.location.end = end;
3211 }
3212 imports.values.push(import);
3213 }
3214
3215 Some((start, Token::UpName { name }, end)) => {
3216 self.advance();
3217 let location = SrcSpan { start, end };
3218 let mut import = UnqualifiedImport {
3219 name,
3220 location,
3221 name_position: location.start,
3222 as_name: None,
3223 };
3224 if self.maybe_one(&Token::As).is_some() {
3225 let (_, as_name, end) = self.expect_upname()?;
3226 import.as_name = Some(as_name);
3227 import.location.end = end;
3228 }
3229 imports.values.push(import);
3230 }
3231
3232 Some((start, Token::Type, _)) => {
3233 self.advance();
3234 let (name_start, name, end) = self.expect_upname()?;
3235 let location = SrcSpan { start, end };
3236 let mut import = UnqualifiedImport {
3237 name,
3238 location,
3239 name_position: name_start,
3240 as_name: None,
3241 };
3242 if self.maybe_one(&Token::As).is_some() {
3243 let (_, as_name, end) = self.expect_upname()?;
3244 import.as_name = Some(as_name);
3245 import.location.end = end;
3246 }
3247 imports.types.push(import);
3248 }
3249
3250 t0 => {
3251 self.tok0 = t0;
3252 break;
3253 }
3254 }
3255 // parse comma
3256 match self.tok0 {
3257 Some((_, Token::Comma, _)) => {
3258 self.advance();
3259 }
3260 _ => break,
3261 }
3262 }
3263 Ok(imports)
3264 }
3265
3266 //
3267 // Parse Constants
3268 //
3269
3270 // examples:
3271 // const a = 1
3272 // const a:Int = 1
3273 // pub const a:Int = 1
3274 fn parse_module_const(
3275 &mut self,
3276 start: u32,
3277 public: bool,
3278 attributes: &Attributes,
3279 ) -> Result<Option<UntypedDefinition>, ParseError> {
3280 let (name_start, name, name_end) = self.expect_name(IncorrectNamePosition::Constant)?;
3281 let documentation = self.take_documentation(name_start);
3282
3283 let annotation = self.parse_type_annotation(&Token::Colon)?;
3284
3285 let (eq_s, eq_e) = self.expect_one(&Token::Equal)?;
3286 match self.parse_const_value()? {
3287 Some(value) => {
3288 Ok(Some(Definition::ModuleConstant(ModuleConstant {
3289 documentation,
3290 location: SrcSpan {
3291 start,
3292
3293 // End after the type annotation if it's there, otherwise after the name
3294 end: annotation
3295 .as_ref()
3296 .map(|annotation| annotation.location().end)
3297 .unwrap_or(0)
3298 .max(name_end),
3299 },
3300 publicity: self.publicity(public, attributes.internal)?,
3301 name,
3302 name_location: SrcSpan::new(name_start, name_end),
3303 annotation,
3304 value: Box::new(value),
3305 type_: (),
3306 deprecation: attributes.deprecated.clone(),
3307 implementations: Implementations {
3308 gleam: true,
3309 can_run_on_erlang: true,
3310 can_run_on_javascript: true,
3311 can_run_on_cranelift: true,
3312 uses_erlang_externals: false,
3313 uses_javascript_externals: false,
3314 uses_cranelift_externals: false,
3315 },
3316 })))
3317 }
3318 _ => parse_error(
3319 ParseErrorType::NoValueAfterEqual,
3320 SrcSpan {
3321 start: eq_s,
3322 end: eq_e,
3323 },
3324 ),
3325 }
3326 }
3327
3328 // examples:
3329 // 1
3330 // "hi"
3331 // True
3332 // [1,2,3]
3333 // wibble <> "wobble"
3334 fn parse_const_value(&mut self) -> Result<Option<UntypedConstant>, ParseError> {
3335 let constant_result = self.parse_const_value_unit();
3336 match constant_result {
3337 Ok(Some(constant)) => self.parse_const_maybe_concatenation(constant),
3338 _ => constant_result,
3339 }
3340 }
3341
3342 fn parse_const_value_unit(&mut self) -> Result<Option<UntypedConstant>, ParseError> {
3343 match self.tok0.take() {
3344 Some((start, Token::Todo, end)) => {
3345 self.advance();
3346 let message = self.maybe_parse_constant_as_message()?;
3347 let end = message
3348 .as_ref()
3349 .map_or(end, |message| message.location().end);
3350 Ok(Some(Constant::Todo {
3351 location: SrcSpan { start, end },
3352 type_: (),
3353 message,
3354 }))
3355 }
3356
3357 Some((start, Token::String { value }, end)) => {
3358 self.advance();
3359 Ok(Some(Constant::String {
3360 value,
3361 location: SrcSpan { start, end },
3362 }))
3363 }
3364
3365 Some((start, Token::Float { value, float_value }, end)) => {
3366 self.advance();
3367 Ok(Some(Constant::Float {
3368 value,
3369 location: SrcSpan { start, end },
3370 float_value,
3371 }))
3372 }
3373
3374 Some((start, Token::Int { value, int_value }, end)) => {
3375 self.advance();
3376 Ok(Some(Constant::Int {
3377 value,
3378 int_value,
3379 location: SrcSpan { start, end },
3380 }))
3381 }
3382
3383 Some((start, Token::Hash, _)) => {
3384 self.advance();
3385 let _ = self.expect_one(&Token::LeftParen)?;
3386 let elements = self.series_of(&Parser::parse_const_value, Some(&Token::Comma))?;
3387 let (_, end) =
3388 self.expect_one_following_series(&Token::RightParen, "a constant value")?;
3389 Ok(Some(Constant::Tuple {
3390 elements,
3391 location: SrcSpan { start, end },
3392 type_: (),
3393 }))
3394 }
3395
3396 Some((start, Token::LeftSquare, _)) => {
3397 self.advance();
3398
3399 let (elements, elements_end_with_comma) = self.series_of_has_trailing_separator(
3400 &Parser::parse_const_value,
3401 Some(&Token::Comma),
3402 )?;
3403
3404 // Parse an optional tail
3405 let mut tail = None;
3406 let mut elements_after_tail = None;
3407 let mut dot_dot_location = None;
3408
3409 // If there are no elements, we still want to parse a tail so
3410 // that we can report a better error message.
3411 if (elements_end_with_comma || elements.is_empty())
3412 && let Some((start, end)) = self.maybe_one(&Token::DotDot)
3413 {
3414 dot_dot_location = Some((start, end));
3415 tail = self.parse_const_value()?.map(Box::new);
3416 if self.maybe_one(&Token::Comma).is_some() {
3417 // See if there's a list of items after the tail,
3418 // like `[..wibble, wobble, wabble]`
3419 let elements =
3420 self.series_of(&Parser::parse_const_value, Some(&Token::Comma));
3421 match elements {
3422 Err(_) => {}
3423 Ok(elements) => {
3424 elements_after_tail = Some(elements);
3425 }
3426 }
3427 }
3428
3429 if tail.is_some() {
3430 // Give a better error when there are two lists being
3431 // concatenated like `[..wibble, ..wabble, woo]`, or if
3432 // there are elements after the tail.
3433 if let Some((second_start, second_end)) = self.maybe_one(&Token::DotDot) {
3434 let _second_tail = self.parse_const_value();
3435
3436 if elements_after_tail.is_none()
3437 || elements_after_tail
3438 .as_ref()
3439 .is_some_and(|vec| vec.is_empty())
3440 {
3441 return parse_error(
3442 ParseErrorType::ListSpreadWithAnotherSpread {
3443 first_spread_location: SrcSpan { start, end },
3444 },
3445 SrcSpan {
3446 start: second_start,
3447 end: second_end,
3448 },
3449 );
3450 }
3451 }
3452 }
3453 }
3454
3455 let (_, end) =
3456 self.expect_one_following_series(&Token::RightSquare, "a constant value")?;
3457
3458 // Return errors for malformed lists
3459 match dot_dot_location {
3460 Some((start, end)) if tail.is_none() => {
3461 return parse_error(
3462 ParseErrorType::ListSpreadWithoutTail,
3463 SrcSpan { start, end },
3464 );
3465 }
3466 _ => {}
3467 }
3468 if tail.is_some()
3469 && elements.is_empty()
3470 && elements_after_tail.as_ref().is_none_or(|e| e.is_empty())
3471 {
3472 return parse_error(
3473 ParseErrorType::ListSpreadWithoutElements,
3474 SrcSpan { start, end },
3475 );
3476 }
3477
3478 match elements_after_tail {
3479 Some(elements) if !elements.is_empty() => {
3480 let (start, end) = match (dot_dot_location, tail) {
3481 (Some((start, _)), Some(tail)) => (start, tail.location().end),
3482 (_, _) => (start, end),
3483 };
3484 return parse_error(
3485 ParseErrorType::ListSpreadFollowedByElements,
3486 SrcSpan { start, end },
3487 );
3488 }
3489 _ => {}
3490 }
3491
3492 Ok(Some(Constant::List {
3493 elements,
3494 location: SrcSpan { start, end },
3495 type_: (),
3496 tail,
3497 }))
3498 }
3499 // BitArray
3500 Some((start, Token::LtLt, _)) => {
3501 self.advance();
3502 let segments = self.series_of(
3503 &|this| {
3504 this.parse_bit_array_segment(
3505 &Parser::parse_const_value,
3506 &Parser::expect_const_int,
3507 &bit_array_const_int,
3508 )
3509 },
3510 Some(&Token::Comma),
3511 )?;
3512 let (_, end) =
3513 self.expect_one_following_series(&Token::GtGt, "a bit array segment")?;
3514 Ok(Some(Constant::BitArray {
3515 location: SrcSpan { start, end },
3516 segments,
3517 }))
3518 }
3519
3520 Some((start, Token::UpName { name }, end)) => {
3521 self.advance();
3522 self.parse_const_record_finish(start, None, name, end)
3523 }
3524
3525 Some((start, Token::Name { name }, module_end))
3526 if self.peek_tok1() == Some(&Token::Dot) =>
3527 {
3528 self.advance(); // name
3529 self.advance(); // dot
3530
3531 match self.tok0.take() {
3532 Some((_, Token::UpName { name: upname }, end)) => {
3533 self.advance(); // upname
3534 self.parse_const_record_finish(
3535 start,
3536 Some((name, SrcSpan::new(start, module_end))),
3537 upname,
3538 end,
3539 )
3540 }
3541 Some((_, Token::Name { name: end_name }, end)) => {
3542 self.advance(); // name
3543
3544 match self.tok0 {
3545 Some((_, Token::LeftParen, _)) => parse_error(
3546 ParseErrorType::UnexpectedFunction,
3547 SrcSpan {
3548 start,
3549 end: end + 1,
3550 },
3551 ),
3552 _ => Ok(Some(Constant::Var {
3553 location: SrcSpan { start, end },
3554 module: Some((name, SrcSpan::new(start, module_end))),
3555 name: end_name,
3556 constructor: None,
3557 type_: (),
3558 })),
3559 }
3560 }
3561 Some((start, token, end)) => parse_error(
3562 ParseErrorType::UnexpectedToken {
3563 token,
3564 expected: vec!["UpName".into(), "Name".into()],
3565 hint: None,
3566 },
3567 SrcSpan { start, end },
3568 ),
3569 None => {
3570 parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 })
3571 }
3572 }
3573 }
3574
3575 Some((start, Token::Name { name }, end)) => {
3576 self.advance(); // name
3577
3578 match self.tok0 {
3579 Some((_, Token::LeftParen, _)) => parse_error(
3580 ParseErrorType::UnexpectedFunction,
3581 SrcSpan {
3582 start,
3583 end: end + 1,
3584 },
3585 ),
3586 _ => Ok(Some(Constant::Var {
3587 location: SrcSpan { start, end },
3588 module: None,
3589 name,
3590 constructor: None,
3591 type_: (),
3592 })),
3593 }
3594 }
3595
3596 // Helpful error for fn
3597 Some((start, Token::Fn, end)) => {
3598 parse_error(ParseErrorType::NotConstType, SrcSpan { start, end })
3599 }
3600
3601 t0 => {
3602 self.tok0 = t0;
3603 Ok(None)
3604 }
3605 }
3606 }
3607
3608 fn parse_const_maybe_concatenation(
3609 &mut self,
3610 left: UntypedConstant,
3611 ) -> Result<Option<UntypedConstant>, ParseError> {
3612 match self.tok0.take() {
3613 Some((op_start, Token::Concatenate, op_end)) => {
3614 self.advance();
3615
3616 match self.parse_const_value() {
3617 Ok(Some(right_constant_value)) => Ok(Some(Constant::StringConcatenation {
3618 location: SrcSpan {
3619 start: left.location().start,
3620 end: right_constant_value.location().end,
3621 },
3622 left: Box::new(left),
3623 right: Box::new(right_constant_value),
3624 })),
3625 _ => parse_error(
3626 ParseErrorType::OpNakedRight,
3627 SrcSpan {
3628 start: op_start,
3629 end: op_end,
3630 },
3631 ),
3632 }
3633 }
3634 t0 => {
3635 self.tok0 = t0;
3636 Ok(Some(left))
3637 }
3638 }
3639 }
3640
3641 // Parse the '( .. )' of a const type constructor
3642 fn parse_const_record_finish(
3643 &mut self,
3644 start: u32,
3645 module: Option<(EcoString, SrcSpan)>,
3646 name: EcoString,
3647 end: u32,
3648 ) -> Result<Option<UntypedConstant>, ParseError> {
3649 match self.maybe_one(&Token::LeftParen) {
3650 Some((par_s, _)) => {
3651 if let Some((dot_dot_start, _)) = self.maybe_one(&Token::DotDot) {
3652 let record = match self.parse_const_value()? {
3653 Some(value) => RecordBeingUpdated {
3654 location: SrcSpan::new(dot_dot_start, value.location().end),
3655 base: Box::new(value),
3656 },
3657 None => {
3658 return parse_error(
3659 ParseErrorType::UnexpectedEof,
3660 SrcSpan::new(par_s, par_s + 2),
3661 );
3662 }
3663 };
3664
3665 let mut update_arguments = vec![];
3666 if self.maybe_one(&Token::Comma).is_some() {
3667 update_arguments = self.series_of(
3668 &Parser::parse_const_record_update_arg,
3669 Some(&Token::Comma),
3670 )?;
3671 }
3672
3673 let (_, par_e) = self.expect_one_following_series(
3674 &Token::RightParen,
3675 "a constant record update argument",
3676 )?;
3677
3678 let constructor_location = SrcSpan { start, end };
3679
3680 Ok(Some(Constant::RecordUpdate {
3681 location: SrcSpan { start, end: par_e },
3682 constructor_location,
3683 module,
3684 name,
3685 record,
3686 arguments: update_arguments,
3687 type_: (),
3688 field_map: Inferred::Unknown,
3689 }))
3690 } else {
3691 let arguments =
3692 self.series_of(&Parser::parse_const_record_arg, Some(&Token::Comma))?;
3693
3694 let (_, par_e) = self.expect_one_following_series(
3695 &Token::RightParen,
3696 "a constant record argument",
3697 )?;
3698
3699 Ok(Some(Constant::Record {
3700 location: SrcSpan { start, end: par_e },
3701 module,
3702 name,
3703 arguments: Some(arguments),
3704 type_: (),
3705 field_map: Inferred::Unknown,
3706 record_constructor: None,
3707 }))
3708 }
3709 }
3710 _ => Ok(Some(Constant::Record {
3711 location: SrcSpan { start, end },
3712 module,
3713 name,
3714 arguments: None,
3715 type_: (),
3716 field_map: Inferred::Unknown,
3717 record_constructor: None,
3718 })),
3719 }
3720 }
3721
3722 // examples:
3723 // name: const
3724 // const
3725 // name:
3726 fn parse_const_record_arg(&mut self) -> Result<Option<CallArg<UntypedConstant>>, ParseError> {
3727 let label = match (self.tok0.take(), self.tok1.take()) {
3728 // Named arg
3729 (Some((start, Token::Name { name }, _)), Some((_, Token::Colon, end))) => {
3730 self.advance();
3731 self.advance();
3732 Some((start, name, end))
3733 }
3734
3735 // Unnamed arg
3736 (t0, t1) => {
3737 self.tok0 = t0;
3738 self.tok1 = t1;
3739 None
3740 }
3741 };
3742
3743 match self.parse_const_value()? {
3744 Some(value) => match label {
3745 Some((start, label, _)) => Ok(Some(CallArg {
3746 implicit: None,
3747 location: SrcSpan {
3748 start,
3749 end: value.location().end,
3750 },
3751 value,
3752 label: Some(label),
3753 })),
3754 _ => Ok(Some(CallArg {
3755 implicit: None,
3756 location: value.location(),
3757 value,
3758 label: None,
3759 })),
3760 },
3761 _ => {
3762 match label {
3763 Some((start, label, end)) => {
3764 // Argument supplied with a label shorthand.
3765 Ok(Some(CallArg {
3766 implicit: None,
3767 location: SrcSpan { start, end },
3768 label: Some(label.clone()),
3769 value: UntypedConstant::Var {
3770 location: SrcSpan { start, end },
3771 constructor: None,
3772 module: None,
3773 name: label,
3774 type_: (),
3775 },
3776 }))
3777 }
3778 _ => Ok(None),
3779 }
3780 }
3781 }
3782 }
3783
3784 fn parse_const_record_update_arg(
3785 &mut self,
3786 ) -> Result<Option<RecordUpdateArg<UntypedConstant>>, ParseError> {
3787 let (start, label, label_end) = match (self.tok0.take(), self.tok1.take()) {
3788 // Named arg - required for record updates
3789 (Some((start, Token::Name { name }, _)), Some((_, Token::Colon, end))) => {
3790 self.advance();
3791 self.advance();
3792 (start, name, end)
3793 }
3794
3795 // Unnamed arg or other - return error since record updates require labels
3796 (Some((start, Token::Name { name }, end)), t1) => {
3797 self.tok0 = Some((start, Token::Name { name: name.clone() }, end));
3798 self.tok1 = t1;
3799
3800 // Check if this is label shorthand (name without colon)
3801 // In this case, use the name as both label and value
3802 match self.parse_const_value()? {
3803 Some(value) if value.location() == SrcSpan { start, end } => {
3804 return Ok(Some(RecordUpdateArg {
3805 label: name,
3806 location: SrcSpan { start, end },
3807 value,
3808 }));
3809 }
3810 _ => {
3811 self.tok0 = Some((start, Token::Name { name }, end));
3812 return parse_error(ParseErrorType::ExpectedName, SrcSpan { start, end });
3813 }
3814 }
3815 }
3816
3817 (t0, t1) => {
3818 self.tok0 = t0;
3819 self.tok1 = t1;
3820 return Ok(None);
3821 }
3822 };
3823
3824 match self.parse_const_value()? {
3825 Some(value) => Ok(Some(RecordUpdateArg {
3826 label,
3827 location: SrcSpan {
3828 start,
3829 end: value.location().end,
3830 },
3831 value,
3832 })),
3833 _ => {
3834 // Label shorthand: field without value means field: field
3835 Ok(Some(RecordUpdateArg {
3836 label: label.clone(),
3837 location: SrcSpan {
3838 start,
3839 end: label_end,
3840 },
3841 value: UntypedConstant::Var {
3842 location: SrcSpan {
3843 start,
3844 end: label_end,
3845 },
3846 constructor: None,
3847 module: None,
3848 name: label,
3849 type_: (),
3850 },
3851 }))
3852 }
3853 }
3854 }
3855
3856 //
3857 // Bit String parsing
3858 //
3859
3860 // The structure is roughly the same for pattern, const, and expr
3861 // that's why these functions take functions
3862 //
3863 // pattern (: option)?
3864 fn parse_bit_array_segment<A>(
3865 &mut self,
3866 value_parser: &impl Fn(&mut Self) -> Result<Option<A>, ParseError>,
3867 arg_parser: &impl Fn(&mut Self) -> Result<A, ParseError>,
3868 to_int_segment: &impl Fn(EcoString, BigInt, u32, u32) -> A,
3869 ) -> Result<Option<BitArraySegment<A, ()>>, ParseError>
3870 where
3871 A: HasLocation + std::fmt::Debug,
3872 {
3873 match value_parser(self)? {
3874 Some(value) => {
3875 let options = if self.maybe_one(&Token::Colon).is_some() {
3876 self.series_of(
3877 &|this| this.parse_bit_array_option(&arg_parser, &to_int_segment),
3878 Some(&Token::Minus),
3879 )?
3880 } else {
3881 vec![]
3882 };
3883 let end = options
3884 .last()
3885 .map(|option| option.location().end)
3886 .unwrap_or_else(|| value.location().end);
3887 Ok(Some(BitArraySegment {
3888 location: SrcSpan {
3889 start: value.location().start,
3890 end,
3891 },
3892 value: Box::new(value),
3893 type_: (),
3894 options,
3895 }))
3896 }
3897 _ => Ok(None),
3898 }
3899 }
3900
3901 // examples:
3902 // 1
3903 // size(1)
3904 // size(five)
3905 // utf8
3906 fn parse_bit_array_option<A: std::fmt::Debug>(
3907 &mut self,
3908 arg_parser: &impl Fn(&mut Self) -> Result<A, ParseError>,
3909 to_int_segment: &impl Fn(EcoString, BigInt, u32, u32) -> A,
3910 ) -> Result<Option<BitArrayOption<A>>, ParseError> {
3911 match self.tok0.take() {
3912 // named segment
3913 Some((start, Token::Name { name }, end)) => {
3914 self.advance();
3915 if self.maybe_one(&Token::LeftParen).is_some() {
3916 // named function segment
3917 match name.as_str() {
3918 "unit" => match self.tok0.take() {
3919 Some((int_s, Token::Int { value, .. }, int_e)) => {
3920 self.advance();
3921 let (_, end) = self.expect_one(&Token::RightParen)?;
3922 let v = value.replace("_", "");
3923 match u8::from_str(&v) {
3924 Ok(units) if units > 0 => Ok(Some(BitArrayOption::Unit {
3925 location: SrcSpan { start, end },
3926 value: units,
3927 })),
3928
3929 _ => Err(ParseError {
3930 error: ParseErrorType::InvalidBitArrayUnit,
3931 location: SrcSpan {
3932 start: int_s,
3933 end: int_e,
3934 },
3935 }),
3936 }
3937 }
3938 tok0 => {
3939 self.tok0 = tok0;
3940 self.next_tok_unexpected(vec!["A positive int".into()])
3941 }
3942 },
3943
3944 "size" => {
3945 let value = arg_parser(self)?;
3946 let (_, end) = self.expect_one(&Token::RightParen)?;
3947 Ok(Some(BitArrayOption::Size {
3948 location: SrcSpan { start, end },
3949 value: Box::new(value),
3950 short_form: false,
3951 }))
3952 }
3953 _ => parse_error(
3954 ParseErrorType::InvalidBitArraySegment,
3955 SrcSpan { start, end },
3956 ),
3957 }
3958 } else {
3959 str_to_bit_array_option(&name, SrcSpan { start, end })
3960 .ok_or(ParseError {
3961 error: ParseErrorType::InvalidBitArraySegment,
3962 location: SrcSpan { start, end },
3963 })
3964 .map(Some)
3965 }
3966 }
3967 // int segment
3968 Some((start, Token::Int { value, int_value }, end)) => {
3969 self.advance();
3970 Ok(Some(BitArrayOption::Size {
3971 location: SrcSpan { start, end },
3972 value: Box::new(to_int_segment(value, int_value, start, end)),
3973 short_form: true,
3974 }))
3975 }
3976 // invalid
3977 tok0 => {
3978 self.tok0 = tok0;
3979 self.next_tok_unexpected(vec![
3980 "A valid bit array segment type".into(),
3981 "See: https://tour.gleam.run/data-types/bit-arrays/".into(),
3982 ])
3983 }
3984 }
3985 }
3986
3987 fn expect_bit_array_pattern_segment_arg(&mut self) -> Result<UntypedPattern, ParseError> {
3988 Ok(Pattern::BitArraySize(self.expect_bit_array_size()?))
3989 }
3990
3991 fn expect_bit_array_size(&mut self) -> Result<BitArraySize<()>, ParseError> {
3992 let mut opstack = vec![];
3993 let mut estack: Vec<BitArraySize<()>> = vec![];
3994
3995 estack.push(self.parse_bit_array_size_unit()?);
3996
3997 loop {
3998 let Some((op_s, token, op_e)) = self.tok0.take() else {
3999 break;
4000 };
4001 let Some(prec) = token_to_bit_array_size_operator(&token).map(|op| op.precedence())
4002 else {
4003 self.tok0 = Some((op_s, token, op_e));
4004 break;
4005 };
4006
4007 self.advance();
4008 let _ = handle_op(
4009 Some(((op_s, token, op_e), prec)),
4010 &mut opstack,
4011 &mut estack,
4012 &reduce_bit_array_size,
4013 );
4014
4015 estack.push(self.parse_bit_array_size_unit()?);
4016 }
4017
4018 Ok(
4019 handle_op(None, &mut opstack, &mut estack, &reduce_bit_array_size)
4020 .expect("bit array size expression stack should not be empty"),
4021 )
4022 }
4023
4024 fn parse_bit_array_size_unit(&mut self) -> Result<BitArraySize<()>, ParseError> {
4025 match self.tok0.take() {
4026 Some((start, Token::Name { name }, end)) => {
4027 self.advance();
4028 Ok(BitArraySize::Variable {
4029 location: SrcSpan { start, end },
4030 name,
4031 constructor: None,
4032 type_: (),
4033 })
4034 }
4035 Some((start, Token::Int { value, int_value }, end)) => {
4036 self.advance();
4037 Ok(BitArraySize::Int {
4038 location: SrcSpan { start, end },
4039 value,
4040 int_value,
4041 })
4042 }
4043 Some((start, Token::LeftBrace, _)) => {
4044 self.advance();
4045 let inner = self.expect_bit_array_size()?;
4046 let (_, end) = self.expect_one(&Token::RightBrace)?;
4047
4048 Ok(BitArraySize::Block {
4049 location: SrcSpan { start, end },
4050 inner: Box::new(inner),
4051 })
4052 }
4053 tok0 => {
4054 self.tok0 = tok0;
4055 self.next_tok_unexpected(vec!["A variable name or an int".into()])
4056 }
4057 }
4058 }
4059
4060 fn expect_const_int(&mut self) -> Result<UntypedConstant, ParseError> {
4061 match self.tok0.take() {
4062 Some((start, Token::Int { value, int_value }, end)) => {
4063 self.advance();
4064 Ok(Constant::Int {
4065 location: SrcSpan { start, end },
4066 value,
4067 int_value,
4068 })
4069 }
4070 tok0 => {
4071 self.tok0 = tok0;
4072 self.next_tok_unexpected(vec!["An int".into()])
4073 }
4074 }
4075 }
4076
4077 fn expect_expression(&mut self) -> Result<UntypedExpr, ParseError> {
4078 match self.parse_expression()? {
4079 Some(e) => Ok(e),
4080 _ => self.next_tok_unexpected(vec!["An expression".into()]),
4081 }
4082 }
4083
4084 fn expect_expression_unit(
4085 &mut self,
4086 context: ExpressionUnitContext,
4087 ) -> Result<UntypedExpr, ParseError> {
4088 if let Some(e) = self.parse_expression_unit(context)? {
4089 Ok(e)
4090 } else {
4091 self.next_tok_unexpected(vec!["An expression".into()])
4092 }
4093 }
4094
4095 //
4096 // Parse Helpers
4097 //
4098
4099 /// Expect a particular token, advances the token stream
4100 fn expect_one(&mut self, wanted: &Token) -> Result<(u32, u32), ParseError> {
4101 match self.maybe_one(wanted) {
4102 Some((start, end)) => Ok((start, end)),
4103 None => self.next_tok_unexpected(vec![wanted.to_string().into()]),
4104 }
4105 }
4106
4107 // Expect a particular token after having parsed a series, advances the token stream
4108 // Used for giving a clearer error message in cases where the series item is what failed to parse
4109 fn expect_one_following_series(
4110 &mut self,
4111 wanted: &Token,
4112 series: &'static str,
4113 ) -> Result<(u32, u32), ParseError> {
4114 match self.maybe_one(wanted) {
4115 Some((start, end)) => Ok((start, end)),
4116 None => self.next_tok_unexpected(vec![wanted.to_string().into(), series.into()]),
4117 }
4118 }
4119
4120 /// Expect the end to a custom type definiton or handle an incorrect
4121 /// record constructor definition.
4122 fn expect_custom_type_close(&mut self) -> Result<u32, ParseError> {
4123 match self.maybe_one(&Token::RightBrace) {
4124 Some((_, end)) => Ok(end),
4125 None => match self.next_tok() {
4126 None => parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }),
4127 Some((start, token, end)) => {
4128 let hint = match (&token, self.tok0.take()) {
4129 (&Token::Fn, _) | (&Token::Pub, Some((_, Token::Fn, _))) => {
4130 let text = "Gleam is not an object oriented programming language so
4131functions are declared separately from types.";
4132 Some(wrap(text).into())
4133 }
4134 (_, _) => None,
4135 };
4136
4137 parse_error(
4138 ParseErrorType::UnexpectedToken {
4139 token,
4140 expected: vec![
4141 Token::RightBrace.to_string().into(),
4142 "a record constructor".into(),
4143 ],
4144 hint,
4145 },
4146 SrcSpan { start, end },
4147 )
4148 }
4149 },
4150 }
4151 }
4152
4153 // Expect a Name else a token dependent helpful error
4154 fn expect_name(
4155 &mut self,
4156 kind: IncorrectNamePosition,
4157 ) -> Result<(u32, EcoString, u32), ParseError> {
4158 let (start, token, end) = self.expect_assign_name()?;
4159 match token {
4160 AssignName::Variable(name) => Ok((start, name, end)),
4161 AssignName::Discard(_) => parse_error(
4162 ParseErrorType::IncorrectName { kind },
4163 SrcSpan { start, end },
4164 ),
4165 }
4166 }
4167
4168 fn expect_assign_name(&mut self) -> Result<(u32, AssignName, u32), ParseError> {
4169 let t = self.next_tok();
4170 match t {
4171 Some((start, tok, end)) => match tok {
4172 Token::Name { name } => Ok((start, AssignName::Variable(name), end)),
4173 Token::DiscardName { name, .. } => Ok((start, AssignName::Discard(name), end)),
4174 Token::UpName { .. } => parse_error(
4175 ParseErrorType::IncorrectName {
4176 kind: IncorrectNamePosition::Variable,
4177 },
4178 SrcSpan { start, end },
4179 ),
4180 _ if tok.is_reserved_word() => parse_error(
4181 ParseErrorType::UnexpectedReservedWord,
4182 SrcSpan { start, end },
4183 ),
4184 Token::Int { .. }
4185 | Token::Float { .. }
4186 | Token::String { .. }
4187 | Token::CommentDoc { .. }
4188 | Token::LeftParen
4189 | Token::RightParen
4190 | Token::LeftSquare
4191 | Token::RightSquare
4192 | Token::LeftBrace
4193 | Token::RightBrace
4194 | Token::Plus
4195 | Token::Minus
4196 | Token::Star
4197 | Token::Slash
4198 | Token::Less
4199 | Token::Greater
4200 | Token::LessEqual
4201 | Token::GreaterEqual
4202 | Token::Percent
4203 | Token::PlusDot
4204 | Token::MinusDot
4205 | Token::StarDot
4206 | Token::SlashDot
4207 | Token::LessDot
4208 | Token::GreaterDot
4209 | Token::LessEqualDot
4210 | Token::GreaterEqualDot
4211 | Token::Concatenate
4212 | Token::Colon
4213 | Token::Comma
4214 | Token::Hash
4215 | Token::Bang
4216 | Token::Equal
4217 | Token::EqualEqual
4218 | Token::NotEqual
4219 | Token::Vbar
4220 | Token::VbarVbar
4221 | Token::AmperAmper
4222 | Token::LtLt
4223 | Token::GtGt
4224 | Token::Pipe
4225 | Token::Dot
4226 | Token::RArrow
4227 | Token::LArrow
4228 | Token::DotDot
4229 | Token::At
4230 | Token::EndOfFile
4231 | Token::CommentNormal
4232 | Token::CommentModule
4233 | Token::NewLine
4234 | Token::As
4235 | Token::Assert
4236 | Token::Auto
4237 | Token::Case
4238 | Token::Const
4239 | Token::Delegate
4240 | Token::Derive
4241 | Token::Echo
4242 | Token::Else
4243 | Token::Fn
4244 | Token::If
4245 | Token::Implement
4246 | Token::Import
4247 | Token::Let
4248 | Token::Macro
4249 | Token::Opaque
4250 | Token::Panic
4251 | Token::Pub
4252 | Token::Test
4253 | Token::Todo
4254 | Token::Type
4255 | Token::Use => parse_error(ParseErrorType::ExpectedName, SrcSpan { start, end }),
4256 },
4257 None => parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }),
4258 }
4259 }
4260
4261 // Expect an UpName else a token dependent helpful error
4262 fn expect_upname(&mut self) -> Result<(u32, EcoString, u32), ParseError> {
4263 let t = self.next_tok();
4264 match t {
4265 Some((start, tok, end)) => match tok {
4266 Token::Name { .. } | Token::DiscardName { .. } => {
4267 parse_error(ParseErrorType::IncorrectUpName, SrcSpan { start, end })
4268 }
4269 Token::UpName { name } => Ok((start, name, end)),
4270 Token::Int { .. }
4271 | Token::Float { .. }
4272 | Token::String { .. }
4273 | Token::CommentDoc { .. }
4274 | Token::LeftParen
4275 | Token::RightParen
4276 | Token::LeftSquare
4277 | Token::RightSquare
4278 | Token::LeftBrace
4279 | Token::RightBrace
4280 | Token::Plus
4281 | Token::Minus
4282 | Token::Star
4283 | Token::Slash
4284 | Token::Less
4285 | Token::Greater
4286 | Token::LessEqual
4287 | Token::GreaterEqual
4288 | Token::Percent
4289 | Token::PlusDot
4290 | Token::MinusDot
4291 | Token::StarDot
4292 | Token::SlashDot
4293 | Token::LessDot
4294 | Token::GreaterDot
4295 | Token::LessEqualDot
4296 | Token::GreaterEqualDot
4297 | Token::Concatenate
4298 | Token::Colon
4299 | Token::Comma
4300 | Token::Hash
4301 | Token::Bang
4302 | Token::Equal
4303 | Token::EqualEqual
4304 | Token::NotEqual
4305 | Token::Vbar
4306 | Token::VbarVbar
4307 | Token::AmperAmper
4308 | Token::LtLt
4309 | Token::GtGt
4310 | Token::Pipe
4311 | Token::Dot
4312 | Token::RArrow
4313 | Token::LArrow
4314 | Token::DotDot
4315 | Token::At
4316 | Token::EndOfFile
4317 | Token::CommentNormal
4318 | Token::CommentModule
4319 | Token::NewLine
4320 | Token::As
4321 | Token::Assert
4322 | Token::Auto
4323 | Token::Case
4324 | Token::Const
4325 | Token::Delegate
4326 | Token::Derive
4327 | Token::Echo
4328 | Token::Else
4329 | Token::Fn
4330 | Token::If
4331 | Token::Implement
4332 | Token::Import
4333 | Token::Let
4334 | Token::Macro
4335 | Token::Opaque
4336 | Token::Panic
4337 | Token::Pub
4338 | Token::Test
4339 | Token::Todo
4340 | Token::Type
4341 | Token::Use => parse_error(ParseErrorType::ExpectedUpName, SrcSpan { start, end }),
4342 },
4343 None => parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }),
4344 }
4345 }
4346
4347 // Expect a target name. e.g. `javascript` or `erlang`.
4348 // The location of the preceding left parenthesis is required
4349 // to give the correct error span in case the target name is missing.
4350 fn expect_target(&mut self, paren_location: SrcSpan) -> Result<Target, ParseError> {
4351 let (start, t, end) = match self.next_tok() {
4352 Some(t) => t,
4353 None => {
4354 return parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 });
4355 }
4356 };
4357 if let Token::Name { name } = t {
4358 match name.as_str() {
4359 "javascript" => Ok(Target::JavaScript),
4360 "erlang" => Ok(Target::Erlang),
4361 "js" => {
4362 self.warnings
4363 .push(DeprecatedSyntaxWarning::DeprecatedTargetShorthand {
4364 location: SrcSpan::new(start, end),
4365 target: Target::JavaScript,
4366 });
4367 Ok(Target::JavaScript)
4368 }
4369 "erl" => {
4370 self.warnings
4371 .push(DeprecatedSyntaxWarning::DeprecatedTargetShorthand {
4372 location: SrcSpan::new(start, end),
4373 target: Target::Erlang,
4374 });
4375 Ok(Target::Erlang)
4376 }
4377 _ => parse_error(ParseErrorType::UnknownTarget, SrcSpan::new(start, end)),
4378 }
4379 } else {
4380 parse_error(ParseErrorType::ExpectedTargetName, paren_location)
4381 }
4382 }
4383
4384 // Expect a String else error
4385 fn expect_string(&mut self) -> Result<(u32, EcoString, u32), ParseError> {
4386 match self.tok0.take() {
4387 Some((start, Token::String { value }, end)) => {
4388 self.advance();
4389 Ok((start, value, end))
4390 }
4391 tok0 => {
4392 self.tok0 = tok0;
4393 self.next_tok_unexpected(vec!["a string".into()])
4394 }
4395 }
4396 }
4397
4398 fn peek_tok1(&mut self) -> Option<&Token> {
4399 self.tok1.as_ref().map(|(_, token, _)| token)
4400 }
4401
4402 // If the next token matches the requested, consume it and return (start, end)
4403 fn maybe_one(&mut self, tok: &Token) -> Option<(u32, u32)> {
4404 match self.tok0.take() {
4405 Some((s, t, e)) if t == *tok => {
4406 self.advance();
4407 Some((s, e))
4408 }
4409
4410 t0 => {
4411 self.tok0 = t0;
4412 None
4413 }
4414 }
4415 }
4416
4417 // Parse a series by repeating a parser, and possibly a separator
4418 fn series_of<A>(
4419 &mut self,
4420 parser: &impl Fn(&mut Self) -> Result<Option<A>, ParseError>,
4421 sep: Option<&Token>,
4422 ) -> Result<Vec<A>, ParseError> {
4423 let (res, _) = self.series_of_has_trailing_separator(parser, sep)?;
4424 Ok(res)
4425 }
4426
4427 /// Parse a series by repeating a parser, and a separator. Returns true if
4428 /// the series ends with the trailing separator.
4429 fn series_of_has_trailing_separator<A>(
4430 &mut self,
4431 parser: &impl Fn(&mut Self) -> Result<Option<A>, ParseError>,
4432 sep: Option<&Token>,
4433 ) -> Result<(Vec<A>, bool), ParseError> {
4434 let mut results = vec![];
4435 let mut final_separator = None;
4436 while let Some(result) = parser(self)? {
4437 results.push(result);
4438 if let Some(sep) = sep {
4439 if let Some(separator) = self.maybe_one(sep) {
4440 final_separator = Some(separator);
4441 } else {
4442 final_separator = None;
4443 break;
4444 }
4445
4446 // Helpful error if extra separator
4447 if let Some((start, end)) = self.maybe_one(sep) {
4448 return parse_error(ParseErrorType::ExtraSeparator, SrcSpan { start, end });
4449 }
4450 }
4451 }
4452
4453 // If the sequence ends with a trailing comma we want to keep track of
4454 // its position.
4455 if let (Some(Token::Comma), Some((_, end))) = (sep, final_separator) {
4456 self.extra.trailing_commas.push(end);
4457 }
4458
4459 Ok((results, final_separator.is_some()))
4460 }
4461
4462 // If next token is a Name, consume it and return relevant info, otherwise, return none
4463 fn maybe_name(&mut self) -> Option<(u32, EcoString, u32)> {
4464 match self.tok0.take() {
4465 Some((s, Token::Name { name }, e)) => {
4466 self.advance();
4467 Some((s, name, e))
4468 }
4469 t0 => {
4470 self.tok0 = t0;
4471 None
4472 }
4473 }
4474 }
4475
4476 // if next token is an UpName, consume it and return relevant info, otherwise, return none
4477 fn maybe_upname(&mut self) -> Option<(u32, EcoString, u32)> {
4478 match self.tok0.take() {
4479 Some((s, Token::UpName { name }, e)) => {
4480 self.advance();
4481 Some((s, name, e))
4482 }
4483 t0 => {
4484 self.tok0 = t0;
4485 None
4486 }
4487 }
4488 }
4489
4490 // if next token is a DiscardName, consume it and return relevant info, otherwise, return none
4491 fn maybe_discard_name(&mut self) -> Option<(u32, EcoString, u32)> {
4492 match self.tok0.take() {
4493 Some((s, Token::DiscardName { name }, e)) => {
4494 self.advance();
4495 Some((s, name, e))
4496 }
4497 t0 => {
4498 self.tok0 = t0;
4499 None
4500 }
4501 }
4502 }
4503
4504 // Unexpected token error on the next token or EOF
4505 fn next_tok_unexpected<A>(&mut self, expected: Vec<EcoString>) -> Result<A, ParseError> {
4506 match self.next_tok() {
4507 None => parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }),
4508 Some((start, token, end)) => parse_error(
4509 ParseErrorType::UnexpectedToken {
4510 token,
4511 expected,
4512 hint: None,
4513 },
4514 SrcSpan { start, end },
4515 ),
4516 }
4517 }
4518
4519 // Moves the token stream forward
4520 fn advance(&mut self) {
4521 let _ = self.next_tok();
4522 }
4523
4524 // Moving the token stream forward
4525 // returns old tok0
4526 fn next_tok(&mut self) -> Option<Spanned> {
4527 let t = self.tok0.take();
4528 let mut previous_newline = None;
4529 let mut nxt;
4530 loop {
4531 match self.tokens.next() {
4532 // gather and skip extra
4533 Some(Ok((start, Token::CommentNormal, end))) => {
4534 self.extra.comments.push(SrcSpan { start, end });
4535 previous_newline = None;
4536 }
4537 Some(Ok((start, Token::CommentDoc { content }, end))) => {
4538 self.extra.doc_comments.push(SrcSpan::new(start, end));
4539 self.doc_comments.push_back((start, content));
4540 previous_newline = None;
4541 }
4542 Some(Ok((start, Token::CommentModule, end))) => {
4543 self.extra.module_comments.push(SrcSpan { start, end });
4544 previous_newline = None;
4545 }
4546 Some(Ok((start, Token::NewLine, _))) => {
4547 self.extra.new_lines.push(start);
4548 // If the previous token is a newline as well that means we
4549 // have run into an empty line.
4550 if let Some(start) = previous_newline {
4551 // We increase the byte position so that newline's start
4552 // doesn't overlap with the previous token's end.
4553 self.extra.empty_lines.push(start + 1);
4554 }
4555 previous_newline = Some(start);
4556 }
4557
4558 // die on lex error
4559 Some(Err(err)) => {
4560 nxt = None;
4561 self.lex_errors.push(err);
4562 break;
4563 }
4564
4565 Some(Ok(tok)) => {
4566 nxt = Some(tok);
4567 break;
4568 }
4569 None => {
4570 nxt = None;
4571 break;
4572 }
4573 }
4574 }
4575 self.tok0 = self.tok1.take();
4576 self.tok1 = nxt.take();
4577 t
4578 }
4579
4580 fn take_documentation(&mut self, until: u32) -> Option<(u32, EcoString)> {
4581 let mut content = String::new();
4582 let mut doc_start = u32::MAX;
4583 while let Some((start, line)) = self.doc_comments.front() {
4584 if *start < doc_start {
4585 doc_start = *start;
4586 }
4587 if *start >= until {
4588 break;
4589 }
4590
4591 if self.extra.has_comment_between(*start, until) {
4592 // We ignore doc comments that come before a regular comment.
4593 let location = SrcSpan::new(*start, start + line.len() as u32);
4594 _ = self.doc_comments.pop_front();
4595 self.detached_doc_comments.push(location);
4596 continue;
4597 }
4598
4599 content.push_str(line);
4600 content.push('\n');
4601 _ = self.doc_comments.pop_front();
4602 }
4603 if content.is_empty() {
4604 None
4605 } else {
4606 Some((doc_start, content.into()))
4607 }
4608 }
4609
4610 fn parse_attributes(
4611 &mut self,
4612 attributes: &mut Attributes,
4613 ) -> Result<Option<SrcSpan>, ParseError> {
4614 let mut attributes_span = None;
4615
4616 while let Some((start, end)) = self.maybe_one(&Token::At) {
4617 if attributes_span.is_none() {
4618 attributes_span = Some(SrcSpan { start, end });
4619 }
4620
4621 let end = self.parse_attribute(start, attributes)?;
4622 attributes_span = attributes_span.map(|span| SrcSpan {
4623 start: span.start,
4624 end,
4625 });
4626 }
4627
4628 Ok(attributes_span)
4629 }
4630
4631 fn parse_attribute(
4632 &mut self,
4633 start: u32,
4634 attributes: &mut Attributes,
4635 ) -> Result<u32, ParseError> {
4636 // Parse the name of the attribute.
4637
4638 let (_, name, end) = self.expect_name(IncorrectNamePosition::Attribute)?;
4639
4640 let end = match name.as_str() {
4641 "external" => {
4642 let _ = self.maybe_one(&Token::LeftParen).ok_or(ParseError {
4643 error: ParseErrorType::ExpectedExternalArguments,
4644 location: SrcSpan { start, end },
4645 })?;
4646 self.parse_external_attribute(start, end, attributes)
4647 }
4648 "target" => self.parse_target_attribute(start, end, attributes),
4649 "deprecated" => self.parse_deprecated_attribute(start, end, attributes),
4650 "internal" => self.parse_internal_attribute(start, end, attributes),
4651 _ => parse_error(ParseErrorType::UnknownAttribute, SrcSpan { start, end }),
4652 }?;
4653
4654 Ok(end)
4655 }
4656
4657 fn parse_target_attribute(
4658 &mut self,
4659 start: u32,
4660 end: u32,
4661 attributes: &mut Attributes,
4662 ) -> Result<u32, ParseError> {
4663 let (paren_start, paren_end) = self.expect_one(&Token::LeftParen)?;
4664 let target = self.expect_target(SrcSpan::new(paren_start, paren_end))?;
4665 if attributes.target.is_some() {
4666 return parse_error(ParseErrorType::DuplicateAttribute, SrcSpan { start, end });
4667 }
4668 let (_, end) = self.expect_one(&Token::RightParen)?;
4669 if attributes.target.is_some() {
4670 return parse_error(ParseErrorType::DuplicateAttribute, SrcSpan { start, end });
4671 }
4672 attributes.target = Some(target);
4673 Ok(end)
4674 }
4675
4676 fn parse_external_attribute(
4677 &mut self,
4678 start: u32,
4679 end: u32,
4680 attributes: &mut Attributes,
4681 ) -> Result<u32, ParseError> {
4682 let (_, target, _) = self.expect_name(IncorrectNamePosition::Target)?;
4683
4684 let target = match target.as_str() {
4685 "erlang" => Target::Erlang,
4686 "javascript" => Target::JavaScript,
4687 _ => return parse_error(ParseErrorType::UnknownTarget, SrcSpan::new(start, end)),
4688 };
4689
4690 let _ = self.expect_one(&Token::Comma)?;
4691 let (_, module, _) = self.expect_string()?;
4692 let _ = self.expect_one(&Token::Comma)?;
4693 let (_, function, _) = self.expect_string()?;
4694 let _ = self.maybe_one(&Token::Comma);
4695 let (_, end) = self.expect_one(&Token::RightParen)?;
4696
4697 if attributes.has_external_for(target) {
4698 return parse_error(ParseErrorType::DuplicateAttribute, SrcSpan { start, end });
4699 }
4700
4701 attributes.set_external_for(target, Some((module, function, SrcSpan { start, end })));
4702 Ok(end)
4703 }
4704
4705 fn parse_deprecated_attribute(
4706 &mut self,
4707 start: u32,
4708 end: u32,
4709 attributes: &mut Attributes,
4710 ) -> Result<u32, ParseError> {
4711 let _ = self.expect_one(&Token::LeftParen).map_err(|_| ParseError {
4712 error: ParseErrorType::ExpectedDeprecationMessage,
4713 location: SrcSpan { start, end },
4714 })?;
4715 if attributes.deprecated.is_deprecated() {
4716 return parse_error(ParseErrorType::DuplicateAttribute, SrcSpan::new(start, end));
4717 }
4718 let (_, message, _) = self.expect_string().map_err(|_| ParseError {
4719 error: ParseErrorType::ExpectedDeprecationMessage,
4720 location: SrcSpan { start, end },
4721 })?;
4722 let (_, end) = self.expect_one(&Token::RightParen)?;
4723 attributes.deprecated = Deprecation::Deprecated { message };
4724 Ok(end)
4725 }
4726
4727 fn parse_internal_attribute(
4728 &mut self,
4729 start: u32,
4730 end: u32,
4731 attributes: &mut Attributes,
4732 ) -> Result<u32, ParseError> {
4733 match attributes.internal {
4734 // If `internal` is present that means that we have already run into
4735 // another `@internal` annotation, so it results in a `DuplicateAttribute`
4736 // error.
4737 InternalAttribute::Present(_) => {
4738 parse_error(ParseErrorType::DuplicateAttribute, SrcSpan::new(start, end))
4739 }
4740 InternalAttribute::Missing => {
4741 attributes.internal = InternalAttribute::Present(SrcSpan::new(start, end));
4742 Ok(end)
4743 }
4744 }
4745 }
4746}
4747
4748fn concat_pattern_variable_left_hand_side_error<T>(start: u32, end: u32) -> Result<T, ParseError> {
4749 Err(ParseError {
4750 error: ParseErrorType::ConcatPatternVariableLeftHandSide,
4751 location: SrcSpan::new(start, end),
4752 })
4753}
4754
4755fn concat_pattern_variable_with_suffix<T>(
4756 start: u32,
4757 name: EcoString,
4758 end: u32,
4759) -> Result<T, ParseError> {
4760 Err(ParseError {
4761 error: ParseErrorType::ConcatPatternVariableWithSuffix { name },
4762 location: SrcSpan::new(start, end),
4763 })
4764}
4765
4766// Operator Precedence Parsing
4767//
4768// Higher number means higher precedence.
4769// All operators are left associative.
4770
4771/// Simple-Precedence-Parser, handle seeing an operator or end
4772fn handle_op<A>(
4773 next_op: Option<(Spanned, u8)>,
4774 opstack: &mut Vec<(Spanned, u8)>,
4775 estack: &mut Vec<A>,
4776 do_reduce: &impl Fn(Spanned, &mut Vec<A>),
4777) -> Option<A> {
4778 let mut next_op = next_op;
4779 loop {
4780 match (opstack.pop(), next_op.take()) {
4781 (None, None) => match estack.pop() {
4782 Some(fin) => {
4783 if estack.is_empty() {
4784 return Some(fin);
4785 } else {
4786 panic!("Expression not fully reduced.")
4787 }
4788 }
4789 _ => {
4790 return None;
4791 }
4792 },
4793
4794 (None, Some(op)) => {
4795 opstack.push(op);
4796 break;
4797 }
4798
4799 (Some((op, _)), None) => do_reduce(op, estack),
4800
4801 (Some((opl, pl)), Some((opr, pr))) => {
4802 match pl.cmp(&pr) {
4803 // all ops are left associative
4804 Ordering::Greater | Ordering::Equal => {
4805 do_reduce(opl, estack);
4806 next_op = Some((opr, pr));
4807 }
4808 Ordering::Less => {
4809 opstack.push((opl, pl));
4810 opstack.push((opr, pr));
4811 break;
4812 }
4813 }
4814 }
4815 }
4816 }
4817 None
4818}
4819
4820fn precedence(t: &Token) -> Option<u8> {
4821 if t == &Token::Pipe {
4822 return Some(6);
4823 }
4824 tok_to_binop(t).map(|op| op.precedence())
4825}
4826
4827fn tok_to_binop(t: &Token) -> Option<BinOp> {
4828 match t {
4829 Token::VbarVbar => Some(BinOp::Or),
4830 Token::AmperAmper => Some(BinOp::And),
4831 Token::EqualEqual => Some(BinOp::Eq),
4832 Token::NotEqual => Some(BinOp::NotEq),
4833 Token::Less => Some(BinOp::LtInt),
4834 Token::LessEqual => Some(BinOp::LtEqInt),
4835 Token::Greater => Some(BinOp::GtInt),
4836 Token::GreaterEqual => Some(BinOp::GtEqInt),
4837 Token::LessDot => Some(BinOp::LtFloat),
4838 Token::LessEqualDot => Some(BinOp::LtEqFloat),
4839 Token::GreaterDot => Some(BinOp::GtFloat),
4840 Token::GreaterEqualDot => Some(BinOp::GtEqFloat),
4841 Token::Plus => Some(BinOp::AddInt),
4842 Token::Minus => Some(BinOp::SubInt),
4843 Token::PlusDot => Some(BinOp::AddFloat),
4844 Token::MinusDot => Some(BinOp::SubFloat),
4845 Token::Percent => Some(BinOp::RemainderInt),
4846 Token::Star => Some(BinOp::MultInt),
4847 Token::StarDot => Some(BinOp::MultFloat),
4848 Token::Slash => Some(BinOp::DivInt),
4849 Token::SlashDot => Some(BinOp::DivFloat),
4850 Token::Concatenate => Some(BinOp::Concatenate),
4851 Token::Name { .. }
4852 | Token::UpName { .. }
4853 | Token::DiscardName { .. }
4854 | Token::Int { .. }
4855 | Token::Float { .. }
4856 | Token::String { .. }
4857 | Token::CommentDoc { .. }
4858 | Token::LeftParen
4859 | Token::RightParen
4860 | Token::LeftSquare
4861 | Token::RightSquare
4862 | Token::LeftBrace
4863 | Token::RightBrace
4864 | Token::Colon
4865 | Token::Comma
4866 | Token::Hash
4867 | Token::Bang
4868 | Token::Equal
4869 | Token::Vbar
4870 | Token::LtLt
4871 | Token::GtGt
4872 | Token::Pipe
4873 | Token::Dot
4874 | Token::RArrow
4875 | Token::LArrow
4876 | Token::DotDot
4877 | Token::At
4878 | Token::EndOfFile
4879 | Token::CommentNormal
4880 | Token::CommentModule
4881 | Token::NewLine
4882 | Token::As
4883 | Token::Assert
4884 | Token::Auto
4885 | Token::Case
4886 | Token::Const
4887 | Token::Delegate
4888 | Token::Derive
4889 | Token::Echo
4890 | Token::Else
4891 | Token::Fn
4892 | Token::If
4893 | Token::Implement
4894 | Token::Import
4895 | Token::Let
4896 | Token::Macro
4897 | Token::Opaque
4898 | Token::Panic
4899 | Token::Pub
4900 | Token::Test
4901 | Token::Todo
4902 | Token::Type
4903 | Token::Use => None,
4904 }
4905}
4906
4907fn token_to_bit_array_size_operator(t: &Token) -> Option<IntOperator> {
4908 match t {
4909 Token::Plus => Some(IntOperator::Add),
4910 Token::Minus => Some(IntOperator::Subtract),
4911 Token::Star => Some(IntOperator::Multiply),
4912 Token::Slash => Some(IntOperator::Divide),
4913 Token::Percent => Some(IntOperator::Remainder),
4914 Token::Name { .. }
4915 | Token::UpName { .. }
4916 | Token::DiscardName { .. }
4917 | Token::Int { .. }
4918 | Token::Float { .. }
4919 | Token::String { .. }
4920 | Token::CommentDoc { .. }
4921 | Token::LeftParen
4922 | Token::RightParen
4923 | Token::LeftSquare
4924 | Token::RightSquare
4925 | Token::LeftBrace
4926 | Token::RightBrace
4927 | Token::Less
4928 | Token::Greater
4929 | Token::LessEqual
4930 | Token::GreaterEqual
4931 | Token::PlusDot
4932 | Token::MinusDot
4933 | Token::StarDot
4934 | Token::SlashDot
4935 | Token::LessDot
4936 | Token::GreaterDot
4937 | Token::LessEqualDot
4938 | Token::GreaterEqualDot
4939 | Token::Concatenate
4940 | Token::Colon
4941 | Token::Comma
4942 | Token::Hash
4943 | Token::Bang
4944 | Token::Equal
4945 | Token::EqualEqual
4946 | Token::NotEqual
4947 | Token::Vbar
4948 | Token::VbarVbar
4949 | Token::AmperAmper
4950 | Token::LtLt
4951 | Token::GtGt
4952 | Token::Pipe
4953 | Token::Dot
4954 | Token::RArrow
4955 | Token::LArrow
4956 | Token::DotDot
4957 | Token::At
4958 | Token::EndOfFile
4959 | Token::CommentNormal
4960 | Token::CommentModule
4961 | Token::NewLine
4962 | Token::As
4963 | Token::Assert
4964 | Token::Auto
4965 | Token::Case
4966 | Token::Const
4967 | Token::Delegate
4968 | Token::Derive
4969 | Token::Echo
4970 | Token::Else
4971 | Token::Fn
4972 | Token::If
4973 | Token::Implement
4974 | Token::Import
4975 | Token::Let
4976 | Token::Macro
4977 | Token::Opaque
4978 | Token::Panic
4979 | Token::Pub
4980 | Token::Test
4981 | Token::Todo
4982 | Token::Type
4983 | Token::Use => None,
4984 }
4985}
4986
4987/// Simple-Precedence-Parser, perform reduction for expression
4988fn do_reduce_expression(op: Spanned, estack: &mut Vec<UntypedExpr>) {
4989 match (estack.pop(), estack.pop()) {
4990 (Some(er), Some(el)) => {
4991 let new_e = expr_op_reduction(op, el, er);
4992 estack.push(new_e);
4993 }
4994 _ => panic!("Tried to reduce without 2 expressions"),
4995 }
4996}
4997
4998/// Simple-Precedence-Parser, perform reduction for clause guard
4999fn do_reduce_clause_guard(op: Spanned, estack: &mut Vec<UntypedClauseGuard>) {
5000 match (estack.pop(), estack.pop()) {
5001 (Some(er), Some(el)) => {
5002 let new_e = clause_guard_reduction(op, el, er);
5003 estack.push(new_e);
5004 }
5005 _ => panic!("Tried to reduce without 2 guards"),
5006 }
5007}
5008
5009/// Simple-Precedence-Parser, perform reduction for bit array size expressions
5010fn reduce_bit_array_size((_, token, _): Spanned, estack: &mut Vec<BitArraySize<()>>) {
5011 let operator = token_to_bit_array_size_operator(&token)
5012 .expect("only operator tokens are pushed onto the bit array size opstack");
5013 match (estack.pop(), estack.pop()) {
5014 (Some(right), Some(left)) => {
5015 let location = SrcSpan {
5016 start: left.location().start,
5017 end: right.location().end,
5018 };
5019 estack.push(BitArraySize::BinaryOperator {
5020 left: Box::new(left),
5021 right: Box::new(right),
5022 operator,
5023 location,
5024 });
5025 }
5026 _ => panic!("Tried to reduce bit array size without 2 operands"),
5027 }
5028}
5029
5030fn expr_op_reduction(
5031 (token_start, token, _token_end): Spanned,
5032 left: UntypedExpr,
5033 right: UntypedExpr,
5034) -> UntypedExpr {
5035 if token == Token::Pipe {
5036 let expressions = if let UntypedExpr::PipeLine { mut expressions } = left {
5037 expressions.push(right);
5038 expressions
5039 } else {
5040 vec1![left, right]
5041 };
5042 UntypedExpr::PipeLine { expressions }
5043 } else {
5044 match tok_to_binop(&token) {
5045 Some(operator) => UntypedExpr::BinOp {
5046 location: SrcSpan {
5047 start: left.location().start,
5048 end: right.location().end,
5049 },
5050 operator,
5051 operator_start: token_start,
5052 left: Box::new(left),
5053 right: Box::new(right),
5054 },
5055 _ => {
5056 panic!("Token could not be converted to binop.")
5057 }
5058 }
5059 }
5060}
5061
5062fn clause_guard_reduction(
5063 (start, token, _end): Spanned,
5064 left: UntypedClauseGuard,
5065 right: UntypedClauseGuard,
5066) -> UntypedClauseGuard {
5067 let location = SrcSpan {
5068 start: left.location().start,
5069 end: right.location().end,
5070 };
5071 let left = Box::new(left);
5072 let right = Box::new(right);
5073 let operator = tok_to_binop(&token).expect("Token could not be converted to binop.");
5074 UntypedClauseGuard::BinaryOperator {
5075 location,
5076 operator,
5077 operator_start: start,
5078 left,
5079 right,
5080 }
5081}
5082
5083// BitArray Parse Helpers
5084//
5085// BitArrays in patterns, guards, and expressions have a very similar structure
5086// but need specific types. These are helpers for that. There is probably a
5087// rustier way to do this :)
5088fn bit_array_size_int(value: EcoString, int_value: BigInt, start: u32, end: u32) -> UntypedPattern {
5089 Pattern::BitArraySize(BitArraySize::Int {
5090 location: SrcSpan { start, end },
5091 value,
5092 int_value,
5093 })
5094}
5095
5096fn bit_array_expr_int(value: EcoString, int_value: BigInt, start: u32, end: u32) -> UntypedExpr {
5097 UntypedExpr::Int {
5098 location: SrcSpan { start, end },
5099 value,
5100 int_value,
5101 }
5102}
5103
5104fn bit_array_const_int(
5105 value: EcoString,
5106 int_value: BigInt,
5107 start: u32,
5108 end: u32,
5109) -> UntypedConstant {
5110 Constant::Int {
5111 location: SrcSpan { start, end },
5112 value,
5113 int_value,
5114 }
5115}
5116
5117fn str_to_bit_array_option<A>(lit: &str, location: SrcSpan) -> Option<BitArrayOption<A>> {
5118 match lit {
5119 "bytes" => Some(BitArrayOption::Bytes { location }),
5120 "int" => Some(BitArrayOption::Int { location }),
5121 "float" => Some(BitArrayOption::Float { location }),
5122 "bits" => Some(BitArrayOption::Bits { location }),
5123 "utf8" => Some(BitArrayOption::Utf8 { location }),
5124 "utf16" => Some(BitArrayOption::Utf16 { location }),
5125 "utf32" => Some(BitArrayOption::Utf32 { location }),
5126 "utf8_codepoint" => Some(BitArrayOption::Utf8Codepoint { location }),
5127 "utf16_codepoint" => Some(BitArrayOption::Utf16Codepoint { location }),
5128 "utf32_codepoint" => Some(BitArrayOption::Utf32Codepoint { location }),
5129 "signed" => Some(BitArrayOption::Signed { location }),
5130 "unsigned" => Some(BitArrayOption::Unsigned { location }),
5131 "big" => Some(BitArrayOption::Big { location }),
5132 "little" => Some(BitArrayOption::Little { location }),
5133 "native" => Some(BitArrayOption::Native { location }),
5134 _ => None,
5135 }
5136}
5137
5138//
5139// Error Helpers
5140//
5141fn parse_error<T>(error: ParseErrorType, location: SrcSpan) -> Result<T, ParseError> {
5142 Err(ParseError { error, location })
5143}
5144
5145//
5146// Misc Helpers
5147//
5148
5149// Parsing a function call into the appropriate structure
5150#[derive(Debug)]
5151pub enum ParserArg {
5152 Arg(Box<CallArg<UntypedExpr>>),
5153 Hole {
5154 name: EcoString,
5155 /// The whole span of the argument.
5156 arg_location: SrcSpan,
5157 /// Just the span of the ignore name.
5158 discard_location: SrcSpan,
5159 label: Option<EcoString>,
5160 },
5161}
5162
5163pub fn make_call(
5164 fun: UntypedExpr,
5165 arguments: Vec<ParserArg>,
5166 start: u32,
5167 end: u32,
5168 open_parenthesis: u32,
5169) -> Result<UntypedExpr, ParseError> {
5170 let mut hole_location = None;
5171
5172 let arguments = arguments
5173 .into_iter()
5174 .map(|argument| match argument {
5175 ParserArg::Arg(arg) => Ok(*arg),
5176 ParserArg::Hole {
5177 arg_location,
5178 discard_location,
5179 name,
5180 label,
5181 } => {
5182 if hole_location.is_some() {
5183 return parse_error(ParseErrorType::TooManyArgHoles, SrcSpan { start, end });
5184 }
5185
5186 hole_location = Some(discard_location);
5187 if name != "_" {
5188 return parse_error(
5189 ParseErrorType::UnexpectedToken {
5190 token: Token::Name { name },
5191 expected: vec!["An expression".into(), "An underscore".into()],
5192 hint: None,
5193 },
5194 arg_location,
5195 );
5196 }
5197
5198 Ok(CallArg {
5199 implicit: None,
5200 label,
5201 location: arg_location,
5202 value: UntypedExpr::Var {
5203 location: discard_location,
5204 name: CAPTURE_VARIABLE.into(),
5205 },
5206 })
5207 }
5208 })
5209 .collect::<Result<_, _>>()?;
5210
5211 let call = UntypedExpr::Call {
5212 location: SrcSpan { start, end },
5213 fun: Box::new(fun),
5214 arguments,
5215 open_parenthesis,
5216 };
5217
5218 match hole_location {
5219 // A normal call
5220 None => Ok(call),
5221
5222 // An anon function using the capture syntax run(_, 1, 2)
5223 Some(hole_location) => Ok(UntypedExpr::Fn {
5224 location: call.location(),
5225 end_of_head_byte_index: call.location().end,
5226 kind: FunctionLiteralKind::Capture {
5227 hole: hole_location,
5228 },
5229 arguments: vec![Arg {
5230 location: hole_location,
5231 annotation: None,
5232 names: ArgNames::Named {
5233 name: CAPTURE_VARIABLE.into(),
5234 location: hole_location,
5235 },
5236 type_: (),
5237 }],
5238 body: vec1![Statement::Expression(call)],
5239 return_annotation: None,
5240 }),
5241 }
5242}
5243
5244#[derive(Debug, Default)]
5245struct ParsedUnqualifiedImports {
5246 types: Vec<UnqualifiedImport>,
5247 values: Vec<UnqualifiedImport>,
5248}
5249
5250/// Parses an Int value to a bigint.
5251///
5252pub fn parse_int_value(value: &str) -> Option<BigInt> {
5253 let (radix, value) = if let Some(value) = value.strip_prefix("0x") {
5254 (16, value)
5255 } else if let Some(value) = value.strip_prefix("0o") {
5256 (8, value)
5257 } else if let Some(value) = value.strip_prefix("0b") {
5258 (2, value)
5259 } else {
5260 (10, value)
5261 };
5262
5263 let value = value.trim_start_matches('_');
5264
5265 BigInt::parse_bytes(value.as_bytes(), radix)
5266}
5267
5268#[derive(Debug, PartialEq, Clone, Copy)]
5269enum ExpressionUnitContext {
5270 FollowingPipe,
5271 Other,
5272}
5273
5274#[derive(Debug, Clone, Copy)]
5275pub enum PatternPosition {
5276 LetAssignment,
5277 CaseClause,
5278 UsePattern,
5279}
5280
5281impl PatternPosition {
5282 pub fn to_declaration(&self) -> VariableDeclaration {
5283 match self {
5284 PatternPosition::LetAssignment => VariableDeclaration::LetPattern,
5285 PatternPosition::CaseClause => VariableDeclaration::ClausePattern,
5286 PatternPosition::UsePattern => VariableDeclaration::UsePattern,
5287 }
5288 }
5289}
5290
5291/// A thin f64 wrapper that does not permit NaN.
5292/// This allows us to implement `Eq`, which require reflexivity.
5293///
5294/// Used for gleam float literals, which cannot be NaN.
5295///
5296/// While there is no syntax for "infinity", float literals might be too big and
5297/// overflow into infinity. This is still allowed so we can parse big literal
5298/// numbers and the error will be raised during the analysis phase.
5299#[derive(Clone, Copy, Debug, PartialEq)]
5300pub struct LiteralFloatValue(f64);
5301
5302impl LiteralFloatValue {
5303 pub const ONE: Self = LiteralFloatValue(1.0);
5304 pub const ZERO: Self = LiteralFloatValue(0.0);
5305
5306 /// Parse from a string, returning `None` if the string
5307 /// is not a valid f64 or the float is `NaN``
5308 pub fn parse(value: &str) -> Option<Self> {
5309 value
5310 .replace("_", "")
5311 .parse::<f64>()
5312 .ok()
5313 .filter(|float| !float.is_nan())
5314 .map(LiteralFloatValue)
5315 }
5316
5317 pub fn value(&self) -> f64 {
5318 self.0
5319 }
5320}
5321
5322impl Eq for LiteralFloatValue {}
5323
5324impl Ord for LiteralFloatValue {
5325 fn cmp(&self, other: &Self) -> Ordering {
5326 self.0
5327 .partial_cmp(&other.0)
5328 .expect("Only NaN comparisons should fail")
5329 }
5330}
5331
5332impl PartialOrd for LiteralFloatValue {
5333 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
5334 Some(self.cmp(other))
5335 }
5336}
5337
5338impl Hash for LiteralFloatValue {
5339 fn hash<H: Hasher>(&self, state: &mut H) {
5340 self.0.to_bits().hash(state);
5341 }
5342}
5343
5344impl Serialize for LiteralFloatValue {
5345 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
5346 where
5347 S: serde::Serializer,
5348 {
5349 serializer.serialize_f64(self.0)
5350 }
5351}
5352
5353impl<'de> Deserialize<'de> for LiteralFloatValue {
5354 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
5355 where
5356 D: serde::Deserializer<'de>,
5357 {
5358 let value = f64::deserialize(deserializer)?;
5359 if value.is_nan() {
5360 Err(serde::de::Error::custom("NaN is not allowed"))
5361 } else {
5362 Ok(LiteralFloatValue(value))
5363 }
5364 }
5365}