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