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