Fork of daniellemaywood.uk/gleam — Wasm codegen work
193 kB
5259 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 if arguments.is_empty() {
3579 return parse_error(
3580 ParseErrorType::ConstantRecordConstructorNoArguments,
3581 SrcSpan::new(par_s, par_e),
3582 );
3583 }
3584
3585 Ok(Some(Constant::Record {
3586 location: SrcSpan { start, end: par_e },
3587 module,
3588 name,
3589 arguments,
3590 type_: (),
3591 field_map: Inferred::Unknown,
3592 record_constructor: None,
3593 }))
3594 }
3595 }
3596 _ => Ok(Some(Constant::Record {
3597 location: SrcSpan { start, end },
3598 module,
3599 name,
3600 arguments: vec![],
3601 type_: (),
3602 field_map: Inferred::Unknown,
3603 record_constructor: None,
3604 })),
3605 }
3606 }
3607
3608 // examples:
3609 // name: const
3610 // const
3611 // name:
3612 fn parse_const_record_arg(&mut self) -> Result<Option<CallArg<UntypedConstant>>, ParseError> {
3613 let label = match (self.tok0.take(), self.tok1.take()) {
3614 // Named arg
3615 (Some((start, Token::Name { name }, _)), Some((_, Token::Colon, end))) => {
3616 self.advance();
3617 self.advance();
3618 Some((start, name, end))
3619 }
3620
3621 // Unnamed arg
3622 (t0, t1) => {
3623 self.tok0 = t0;
3624 self.tok1 = t1;
3625 None
3626 }
3627 };
3628
3629 match self.parse_const_value()? {
3630 Some(value) => match label {
3631 Some((start, label, _)) => Ok(Some(CallArg {
3632 implicit: None,
3633 location: SrcSpan {
3634 start,
3635 end: value.location().end,
3636 },
3637 value,
3638 label: Some(label),
3639 })),
3640 _ => Ok(Some(CallArg {
3641 implicit: None,
3642 location: value.location(),
3643 value,
3644 label: None,
3645 })),
3646 },
3647 _ => {
3648 match label {
3649 Some((start, label, end)) => {
3650 // Argument supplied with a label shorthand.
3651 Ok(Some(CallArg {
3652 implicit: None,
3653 location: SrcSpan { start, end },
3654 label: Some(label.clone()),
3655 value: UntypedConstant::Var {
3656 location: SrcSpan { start, end },
3657 constructor: None,
3658 module: None,
3659 name: label,
3660 type_: (),
3661 },
3662 }))
3663 }
3664 _ => Ok(None),
3665 }
3666 }
3667 }
3668 }
3669
3670 fn parse_const_record_update_arg(
3671 &mut self,
3672 ) -> Result<Option<RecordUpdateArg<UntypedConstant>>, ParseError> {
3673 let (start, label, label_end) = match (self.tok0.take(), self.tok1.take()) {
3674 // Named arg - required for record updates
3675 (Some((start, Token::Name { name }, _)), Some((_, Token::Colon, end))) => {
3676 self.advance();
3677 self.advance();
3678 (start, name, end)
3679 }
3680
3681 // Unnamed arg or other - return error since record updates require labels
3682 (Some((start, Token::Name { name }, end)), t1) => {
3683 self.tok0 = Some((start, Token::Name { name: name.clone() }, end));
3684 self.tok1 = t1;
3685
3686 // Check if this is label shorthand (name without colon)
3687 // In this case, use the name as both label and value
3688 match self.parse_const_value()? {
3689 Some(value) if value.location() == SrcSpan { start, end } => {
3690 return Ok(Some(RecordUpdateArg {
3691 label: name.clone(),
3692 location: SrcSpan { start, end },
3693 value,
3694 }));
3695 }
3696 _ => {
3697 self.tok0 = Some((start, Token::Name { name }, end));
3698 return parse_error(ParseErrorType::ExpectedName, SrcSpan { start, end });
3699 }
3700 }
3701 }
3702
3703 (t0, t1) => {
3704 self.tok0 = t0;
3705 self.tok1 = t1;
3706 return Ok(None);
3707 }
3708 };
3709
3710 match self.parse_const_value()? {
3711 Some(value) => Ok(Some(RecordUpdateArg {
3712 label,
3713 location: SrcSpan {
3714 start,
3715 end: value.location().end,
3716 },
3717 value,
3718 })),
3719 _ => {
3720 // Label shorthand: field without value means field: field
3721 Ok(Some(RecordUpdateArg {
3722 label: label.clone(),
3723 location: SrcSpan {
3724 start,
3725 end: label_end,
3726 },
3727 value: UntypedConstant::Var {
3728 location: SrcSpan {
3729 start,
3730 end: label_end,
3731 },
3732 constructor: None,
3733 module: None,
3734 name: label,
3735 type_: (),
3736 },
3737 }))
3738 }
3739 }
3740 }
3741
3742 //
3743 // Bit String parsing
3744 //
3745
3746 // The structure is roughly the same for pattern, const, and expr
3747 // that's why these functions take functions
3748 //
3749 // pattern (: option)?
3750 fn parse_bit_array_segment<A>(
3751 &mut self,
3752 value_parser: &impl Fn(&mut Self) -> Result<Option<A>, ParseError>,
3753 arg_parser: &impl Fn(&mut Self) -> Result<A, ParseError>,
3754 to_int_segment: &impl Fn(EcoString, BigInt, u32, u32) -> A,
3755 ) -> Result<Option<BitArraySegment<A, ()>>, ParseError>
3756 where
3757 A: HasLocation + std::fmt::Debug,
3758 {
3759 match value_parser(self)? {
3760 Some(value) => {
3761 let options = if self.maybe_one(&Token::Colon).is_some() {
3762 Parser::series_of(
3763 self,
3764 &|this| this.parse_bit_array_option(&arg_parser, &to_int_segment),
3765 Some(&Token::Minus),
3766 )?
3767 } else {
3768 vec![]
3769 };
3770 let end = options
3771 .last()
3772 .map(|option| option.location().end)
3773 .unwrap_or_else(|| value.location().end);
3774 Ok(Some(BitArraySegment {
3775 location: SrcSpan {
3776 start: value.location().start,
3777 end,
3778 },
3779 value: Box::new(value),
3780 type_: (),
3781 options,
3782 }))
3783 }
3784 _ => Ok(None),
3785 }
3786 }
3787
3788 // examples:
3789 // 1
3790 // size(1)
3791 // size(five)
3792 // utf8
3793 fn parse_bit_array_option<A: std::fmt::Debug>(
3794 &mut self,
3795 arg_parser: &impl Fn(&mut Self) -> Result<A, ParseError>,
3796 to_int_segment: &impl Fn(EcoString, BigInt, u32, u32) -> A,
3797 ) -> Result<Option<BitArrayOption<A>>, ParseError> {
3798 match self.tok0.take() {
3799 // named segment
3800 Some((start, Token::Name { name }, end)) => {
3801 self.advance();
3802 if self.maybe_one(&Token::LeftParen).is_some() {
3803 // named function segment
3804 match name.as_str() {
3805 "unit" => match self.tok0.take() {
3806 Some((int_s, Token::Int { value, .. }, int_e)) => {
3807 self.advance();
3808 let (_, end) = self.expect_one(&Token::RightParen)?;
3809 let v = value.replace("_", "");
3810 match u8::from_str(&v) {
3811 Ok(units) if units > 0 => Ok(Some(BitArrayOption::Unit {
3812 location: SrcSpan { start, end },
3813 value: units,
3814 })),
3815
3816 _ => Err(ParseError {
3817 error: ParseErrorType::InvalidBitArrayUnit,
3818 location: SrcSpan {
3819 start: int_s,
3820 end: int_e,
3821 },
3822 }),
3823 }
3824 }
3825 tok0 => {
3826 self.tok0 = tok0;
3827 self.next_tok_unexpected(vec!["A positive int".into()])
3828 }
3829 },
3830
3831 "size" => {
3832 let value = arg_parser(self)?;
3833 let (_, end) = self.expect_one(&Token::RightParen)?;
3834 Ok(Some(BitArrayOption::Size {
3835 location: SrcSpan { start, end },
3836 value: Box::new(value),
3837 short_form: false,
3838 }))
3839 }
3840 _ => parse_error(
3841 ParseErrorType::InvalidBitArraySegment,
3842 SrcSpan { start, end },
3843 ),
3844 }
3845 } else {
3846 str_to_bit_array_option(&name, SrcSpan { start, end })
3847 .ok_or(ParseError {
3848 error: ParseErrorType::InvalidBitArraySegment,
3849 location: SrcSpan { start, end },
3850 })
3851 .map(Some)
3852 }
3853 }
3854 // int segment
3855 Some((start, Token::Int { value, int_value }, end)) => {
3856 self.advance();
3857 Ok(Some(BitArrayOption::Size {
3858 location: SrcSpan { start, end },
3859 value: Box::new(to_int_segment(value, int_value, start, end)),
3860 short_form: true,
3861 }))
3862 }
3863 // invalid
3864 tok0 => {
3865 self.tok0 = tok0;
3866 self.next_tok_unexpected(vec![
3867 "A valid bit array segment type".into(),
3868 "See: https://tour.gleam.run/data-types/bit-arrays/".into(),
3869 ])
3870 }
3871 }
3872 }
3873
3874 fn expect_bit_array_pattern_segment_arg(&mut self) -> Result<UntypedPattern, ParseError> {
3875 Ok(Pattern::BitArraySize(self.expect_bit_array_size()?))
3876 }
3877
3878 fn expect_bit_array_size(&mut self) -> Result<BitArraySize<()>, ParseError> {
3879 let mut opstack = vec![];
3880 let mut estack: Vec<BitArraySize<()>> = vec![];
3881
3882 estack.push(self.parse_bit_array_size_unit()?);
3883
3884 loop {
3885 let Some((op_s, token, op_e)) = self.tok0.take() else {
3886 break;
3887 };
3888 let Some(prec) = token_to_bit_array_size_operator(&token).map(|op| op.precedence())
3889 else {
3890 self.tok0 = Some((op_s, token, op_e));
3891 break;
3892 };
3893
3894 self.advance();
3895 let _ = handle_op(
3896 Some(((op_s, token, op_e), prec)),
3897 &mut opstack,
3898 &mut estack,
3899 &reduce_bit_array_size,
3900 );
3901
3902 estack.push(self.parse_bit_array_size_unit()?);
3903 }
3904
3905 Ok(
3906 handle_op(None, &mut opstack, &mut estack, &reduce_bit_array_size)
3907 .expect("bit array size expression stack should not be empty"),
3908 )
3909 }
3910
3911 fn parse_bit_array_size_unit(&mut self) -> Result<BitArraySize<()>, ParseError> {
3912 match self.tok0.take() {
3913 Some((start, Token::Name { name }, end)) => {
3914 self.advance();
3915 Ok(BitArraySize::Variable {
3916 location: SrcSpan { start, end },
3917 name,
3918 constructor: None,
3919 type_: (),
3920 })
3921 }
3922 Some((start, Token::Int { value, int_value }, end)) => {
3923 self.advance();
3924 Ok(BitArraySize::Int {
3925 location: SrcSpan { start, end },
3926 value,
3927 int_value,
3928 })
3929 }
3930 Some((start, Token::LeftBrace, _)) => {
3931 self.advance();
3932 let inner = self.expect_bit_array_size()?;
3933 let (_, end) = self.expect_one(&Token::RightBrace)?;
3934
3935 Ok(BitArraySize::Block {
3936 location: SrcSpan { start, end },
3937 inner: Box::new(inner),
3938 })
3939 }
3940 tok0 => {
3941 self.tok0 = tok0;
3942 self.next_tok_unexpected(vec!["A variable name or an int".into()])
3943 }
3944 }
3945 }
3946
3947 fn expect_const_int(&mut self) -> Result<UntypedConstant, ParseError> {
3948 match self.tok0.take() {
3949 Some((start, Token::Int { value, int_value }, end)) => {
3950 self.advance();
3951 Ok(Constant::Int {
3952 location: SrcSpan { start, end },
3953 value,
3954 int_value,
3955 })
3956 }
3957 tok0 => {
3958 self.tok0 = tok0;
3959 self.next_tok_unexpected(vec!["An int".into()])
3960 }
3961 }
3962 }
3963
3964 fn expect_expression(&mut self) -> Result<UntypedExpr, ParseError> {
3965 match self.parse_expression()? {
3966 Some(e) => Ok(e),
3967 _ => self.next_tok_unexpected(vec!["An expression".into()]),
3968 }
3969 }
3970
3971 fn expect_expression_unit(
3972 &mut self,
3973 context: ExpressionUnitContext,
3974 ) -> Result<UntypedExpr, ParseError> {
3975 if let Some(e) = self.parse_expression_unit(context)? {
3976 Ok(e)
3977 } else {
3978 self.next_tok_unexpected(vec!["An expression".into()])
3979 }
3980 }
3981
3982 //
3983 // Parse Helpers
3984 //
3985
3986 /// Expect a particular token, advances the token stream
3987 fn expect_one(&mut self, wanted: &Token) -> Result<(u32, u32), ParseError> {
3988 match self.maybe_one(wanted) {
3989 Some((start, end)) => Ok((start, end)),
3990 None => self.next_tok_unexpected(vec![wanted.to_string().into()]),
3991 }
3992 }
3993
3994 // Expect a particular token after having parsed a series, advances the token stream
3995 // Used for giving a clearer error message in cases where the series item is what failed to parse
3996 fn expect_one_following_series(
3997 &mut self,
3998 wanted: &Token,
3999 series: &'static str,
4000 ) -> Result<(u32, u32), ParseError> {
4001 match self.maybe_one(wanted) {
4002 Some((start, end)) => Ok((start, end)),
4003 None => self.next_tok_unexpected(vec![wanted.to_string().into(), series.into()]),
4004 }
4005 }
4006
4007 /// Expect the end to a custom type definiton or handle an incorrect
4008 /// record constructor definition.
4009 ///
4010 /// Used for mapping to a more specific error type and message.
4011 fn expect_custom_type_close(
4012 &mut self,
4013 name: &EcoString,
4014 public: bool,
4015 opaque: bool,
4016 ) -> Result<(u32, u32), ParseError> {
4017 match self.maybe_one(&Token::RightBrace) {
4018 Some((start, end)) => Ok((start, end)),
4019 None => match self.next_tok() {
4020 None => parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }),
4021 Some((start, token, end)) => {
4022 // If provided a Name, map to a more detailed error
4023 // message to nudge the user.
4024 // Else, handle as an unexpected token.
4025 let field = if let Token::Name { name } = token {
4026 name
4027 } else {
4028 let hint = match (&token, self.tok0.take()) {
4029 (&Token::Fn, _) | (&Token::Pub, Some((_, Token::Fn, _))) => {
4030 let text = "Gleam is not an object oriented programming language so
4031functions are declared separately from types.";
4032 Some(wrap(text).into())
4033 }
4034 (_, _) => None,
4035 };
4036
4037 return parse_error(
4038 ParseErrorType::UnexpectedToken {
4039 token,
4040 expected: vec![
4041 Token::RightBrace.to_string().into(),
4042 "a record constructor".into(),
4043 ],
4044 hint,
4045 },
4046 SrcSpan { start, end },
4047 );
4048 };
4049 let field_type = match self.parse_type_annotation(&Token::Colon) {
4050 Ok(Some(annotation)) => Some(Box::new(annotation)),
4051 _ => None,
4052 };
4053 parse_error(
4054 ParseErrorType::ExpectedRecordConstructor {
4055 name: name.clone(),
4056 public,
4057 opaque,
4058 field,
4059 field_type,
4060 },
4061 SrcSpan { start, end },
4062 )
4063 }
4064 },
4065 }
4066 }
4067
4068 // Expect a Name else a token dependent helpful error
4069 fn expect_name(&mut self) -> Result<(u32, EcoString, u32), ParseError> {
4070 let (start, token, end) = self.expect_assign_name()?;
4071 match token {
4072 AssignName::Variable(name) => Ok((start, name, end)),
4073 AssignName::Discard(_) => {
4074 parse_error(ParseErrorType::IncorrectName, SrcSpan { start, end })
4075 }
4076 }
4077 }
4078
4079 fn expect_assign_name(&mut self) -> Result<(u32, AssignName, u32), ParseError> {
4080 let t = self.next_tok();
4081 match t {
4082 Some((start, tok, end)) => match tok {
4083 Token::Name { name } => Ok((start, AssignName::Variable(name), end)),
4084 Token::DiscardName { name, .. } => Ok((start, AssignName::Discard(name), end)),
4085 Token::UpName { .. } => {
4086 parse_error(ParseErrorType::IncorrectName, SrcSpan { start, end })
4087 }
4088 _ if tok.is_reserved_word() => parse_error(
4089 ParseErrorType::UnexpectedReservedWord,
4090 SrcSpan { start, end },
4091 ),
4092 Token::Int { .. }
4093 | Token::Float { .. }
4094 | Token::String { .. }
4095 | Token::CommentDoc { .. }
4096 | Token::LeftParen
4097 | Token::RightParen
4098 | Token::LeftSquare
4099 | Token::RightSquare
4100 | Token::LeftBrace
4101 | Token::RightBrace
4102 | Token::Plus
4103 | Token::Minus
4104 | Token::Star
4105 | Token::Slash
4106 | Token::Less
4107 | Token::Greater
4108 | Token::LessEqual
4109 | Token::GreaterEqual
4110 | Token::Percent
4111 | Token::PlusDot
4112 | Token::MinusDot
4113 | Token::StarDot
4114 | Token::SlashDot
4115 | Token::LessDot
4116 | Token::GreaterDot
4117 | Token::LessEqualDot
4118 | Token::GreaterEqualDot
4119 | Token::Concatenate
4120 | Token::Colon
4121 | Token::Comma
4122 | Token::Hash
4123 | Token::Bang
4124 | Token::Equal
4125 | Token::EqualEqual
4126 | Token::NotEqual
4127 | Token::Vbar
4128 | Token::VbarVbar
4129 | Token::AmperAmper
4130 | Token::LtLt
4131 | Token::GtGt
4132 | Token::Pipe
4133 | Token::Dot
4134 | Token::RArrow
4135 | Token::LArrow
4136 | Token::DotDot
4137 | Token::At
4138 | Token::EndOfFile
4139 | Token::CommentNormal
4140 | Token::CommentModule
4141 | Token::NewLine
4142 | Token::As
4143 | Token::Assert
4144 | Token::Auto
4145 | Token::Case
4146 | Token::Const
4147 | Token::Delegate
4148 | Token::Derive
4149 | Token::Echo
4150 | Token::Else
4151 | Token::Fn
4152 | Token::If
4153 | Token::Implement
4154 | Token::Import
4155 | Token::Let
4156 | Token::Macro
4157 | Token::Opaque
4158 | Token::Panic
4159 | Token::Pub
4160 | Token::Test
4161 | Token::Todo
4162 | Token::Type
4163 | Token::Use => parse_error(ParseErrorType::ExpectedName, SrcSpan { start, end }),
4164 },
4165 None => parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }),
4166 }
4167 }
4168
4169 // Expect an UpName else a token dependent helpful error
4170 fn expect_upname(&mut self) -> Result<(u32, EcoString, u32), ParseError> {
4171 let t = self.next_tok();
4172 match t {
4173 Some((start, tok, end)) => match tok {
4174 Token::Name { .. } | Token::DiscardName { .. } => {
4175 parse_error(ParseErrorType::IncorrectUpName, SrcSpan { start, end })
4176 }
4177 Token::UpName { name } => Ok((start, name, end)),
4178 Token::Int { .. }
4179 | Token::Float { .. }
4180 | Token::String { .. }
4181 | Token::CommentDoc { .. }
4182 | Token::LeftParen
4183 | Token::RightParen
4184 | Token::LeftSquare
4185 | Token::RightSquare
4186 | Token::LeftBrace
4187 | Token::RightBrace
4188 | Token::Plus
4189 | Token::Minus
4190 | Token::Star
4191 | Token::Slash
4192 | Token::Less
4193 | Token::Greater
4194 | Token::LessEqual
4195 | Token::GreaterEqual
4196 | Token::Percent
4197 | Token::PlusDot
4198 | Token::MinusDot
4199 | Token::StarDot
4200 | Token::SlashDot
4201 | Token::LessDot
4202 | Token::GreaterDot
4203 | Token::LessEqualDot
4204 | Token::GreaterEqualDot
4205 | Token::Concatenate
4206 | Token::Colon
4207 | Token::Comma
4208 | Token::Hash
4209 | Token::Bang
4210 | Token::Equal
4211 | Token::EqualEqual
4212 | Token::NotEqual
4213 | Token::Vbar
4214 | Token::VbarVbar
4215 | Token::AmperAmper
4216 | Token::LtLt
4217 | Token::GtGt
4218 | Token::Pipe
4219 | Token::Dot
4220 | Token::RArrow
4221 | Token::LArrow
4222 | Token::DotDot
4223 | Token::At
4224 | Token::EndOfFile
4225 | Token::CommentNormal
4226 | Token::CommentModule
4227 | Token::NewLine
4228 | Token::As
4229 | Token::Assert
4230 | Token::Auto
4231 | Token::Case
4232 | Token::Const
4233 | Token::Delegate
4234 | Token::Derive
4235 | Token::Echo
4236 | Token::Else
4237 | Token::Fn
4238 | Token::If
4239 | Token::Implement
4240 | Token::Import
4241 | Token::Let
4242 | Token::Macro
4243 | Token::Opaque
4244 | Token::Panic
4245 | Token::Pub
4246 | Token::Test
4247 | Token::Todo
4248 | Token::Type
4249 | Token::Use => parse_error(ParseErrorType::ExpectedUpName, SrcSpan { start, end }),
4250 },
4251 None => parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }),
4252 }
4253 }
4254
4255 // Expect a target name. e.g. `javascript` or `erlang`.
4256 // The location of the preceding left parenthesis is required
4257 // to give the correct error span in case the target name is missing.
4258 fn expect_target(&mut self, paren_location: SrcSpan) -> Result<Target, ParseError> {
4259 let (start, t, end) = match self.next_tok() {
4260 Some(t) => t,
4261 None => {
4262 return parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 });
4263 }
4264 };
4265 if let Token::Name { name } = t {
4266 match name.as_str() {
4267 "javascript" => Ok(Target::JavaScript),
4268 "erlang" => Ok(Target::Erlang),
4269 "js" => {
4270 self.warnings
4271 .push(DeprecatedSyntaxWarning::DeprecatedTargetShorthand {
4272 location: SrcSpan::new(start, end),
4273 target: Target::JavaScript,
4274 });
4275 Ok(Target::JavaScript)
4276 }
4277 "erl" => {
4278 self.warnings
4279 .push(DeprecatedSyntaxWarning::DeprecatedTargetShorthand {
4280 location: SrcSpan::new(start, end),
4281 target: Target::Erlang,
4282 });
4283 Ok(Target::Erlang)
4284 }
4285 _ => parse_error(ParseErrorType::UnknownTarget, SrcSpan::new(start, end)),
4286 }
4287 } else {
4288 parse_error(ParseErrorType::ExpectedTargetName, paren_location)
4289 }
4290 }
4291
4292 // Expect a String else error
4293 fn expect_string(&mut self) -> Result<(u32, EcoString, u32), ParseError> {
4294 match self.tok0.take() {
4295 Some((start, Token::String { value }, end)) => {
4296 self.advance();
4297 Ok((start, value, end))
4298 }
4299 tok0 => {
4300 self.tok0 = tok0;
4301 self.next_tok_unexpected(vec!["a string".into()])
4302 }
4303 }
4304 }
4305
4306 fn peek_tok1(&mut self) -> Option<&Token> {
4307 self.tok1.as_ref().map(|(_, token, _)| token)
4308 }
4309
4310 // If the next token matches the requested, consume it and return (start, end)
4311 fn maybe_one(&mut self, tok: &Token) -> Option<(u32, u32)> {
4312 match self.tok0.take() {
4313 Some((s, t, e)) if t == *tok => {
4314 self.advance();
4315 Some((s, e))
4316 }
4317
4318 t0 => {
4319 self.tok0 = t0;
4320 None
4321 }
4322 }
4323 }
4324
4325 // Parse a series by repeating a parser, and possibly a separator
4326 fn series_of<A>(
4327 &mut self,
4328 parser: &impl Fn(&mut Self) -> Result<Option<A>, ParseError>,
4329 sep: Option<&Token>,
4330 ) -> Result<Vec<A>, ParseError> {
4331 let (res, _) = self.series_of_has_trailing_separator(parser, sep)?;
4332 Ok(res)
4333 }
4334
4335 /// Parse a series by repeating a parser, and a separator. Returns true if
4336 /// the series ends with the trailing separator.
4337 fn series_of_has_trailing_separator<A>(
4338 &mut self,
4339 parser: &impl Fn(&mut Self) -> Result<Option<A>, ParseError>,
4340 sep: Option<&Token>,
4341 ) -> Result<(Vec<A>, bool), ParseError> {
4342 let mut results = vec![];
4343 let mut final_separator = None;
4344 while let Some(result) = parser(self)? {
4345 results.push(result);
4346 if let Some(sep) = sep {
4347 if let Some(separator) = self.maybe_one(sep) {
4348 final_separator = Some(separator);
4349 } else {
4350 final_separator = None;
4351 break;
4352 }
4353
4354 // Helpful error if extra separator
4355 if let Some((start, end)) = self.maybe_one(sep) {
4356 return parse_error(ParseErrorType::ExtraSeparator, SrcSpan { start, end });
4357 }
4358 }
4359 }
4360
4361 // If the sequence ends with a trailing comma we want to keep track of
4362 // its position.
4363 if let (Some(Token::Comma), Some((_, end))) = (sep, final_separator) {
4364 self.extra.trailing_commas.push(end)
4365 };
4366
4367 Ok((results, final_separator.is_some()))
4368 }
4369
4370 // If next token is a Name, consume it and return relevant info, otherwise, return none
4371 fn maybe_name(&mut self) -> Option<(u32, EcoString, u32)> {
4372 match self.tok0.take() {
4373 Some((s, Token::Name { name }, e)) => {
4374 self.advance();
4375 Some((s, name, e))
4376 }
4377 t0 => {
4378 self.tok0 = t0;
4379 None
4380 }
4381 }
4382 }
4383
4384 // if next token is an UpName, consume it and return relevant info, otherwise, return none
4385 fn maybe_upname(&mut self) -> Option<(u32, EcoString, u32)> {
4386 match self.tok0.take() {
4387 Some((s, Token::UpName { name }, e)) => {
4388 self.advance();
4389 Some((s, name, e))
4390 }
4391 t0 => {
4392 self.tok0 = t0;
4393 None
4394 }
4395 }
4396 }
4397
4398 // if next token is a DiscardName, consume it and return relevant info, otherwise, return none
4399 fn maybe_discard_name(&mut self) -> Option<(u32, EcoString, u32)> {
4400 match self.tok0.take() {
4401 Some((s, Token::DiscardName { name }, e)) => {
4402 self.advance();
4403 Some((s, name, e))
4404 }
4405 t0 => {
4406 self.tok0 = t0;
4407 None
4408 }
4409 }
4410 }
4411
4412 // Unexpected token error on the next token or EOF
4413 fn next_tok_unexpected<A>(&mut self, expected: Vec<EcoString>) -> Result<A, ParseError> {
4414 match self.next_tok() {
4415 None => parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }),
4416 Some((start, token, end)) => parse_error(
4417 ParseErrorType::UnexpectedToken {
4418 token,
4419 expected,
4420 hint: None,
4421 },
4422 SrcSpan { start, end },
4423 ),
4424 }
4425 }
4426
4427 // Moves the token stream forward
4428 fn advance(&mut self) {
4429 let _ = self.next_tok();
4430 }
4431
4432 // Moving the token stream forward
4433 // returns old tok0
4434 fn next_tok(&mut self) -> Option<Spanned> {
4435 let t = self.tok0.take();
4436 let mut previous_newline = None;
4437 let mut nxt;
4438 loop {
4439 match self.tokens.next() {
4440 // gather and skip extra
4441 Some(Ok((start, Token::CommentNormal, end))) => {
4442 self.extra.comments.push(SrcSpan { start, end });
4443 previous_newline = None;
4444 }
4445 Some(Ok((start, Token::CommentDoc { content }, end))) => {
4446 self.extra.doc_comments.push(SrcSpan::new(start, end));
4447 self.doc_comments.push_back((start, content));
4448 previous_newline = None;
4449 }
4450 Some(Ok((start, Token::CommentModule, end))) => {
4451 self.extra.module_comments.push(SrcSpan { start, end });
4452 previous_newline = None;
4453 }
4454 Some(Ok((start, Token::NewLine, _))) => {
4455 self.extra.new_lines.push(start);
4456 // If the previous token is a newline as well that means we
4457 // have run into an empty line.
4458 if let Some(start) = previous_newline {
4459 // We increase the byte position so that newline's start
4460 // doesn't overlap with the previous token's end.
4461 self.extra.empty_lines.push(start + 1);
4462 }
4463 previous_newline = Some(start);
4464 }
4465
4466 // die on lex error
4467 Some(Err(err)) => {
4468 nxt = None;
4469 self.lex_errors.push(err);
4470 break;
4471 }
4472
4473 Some(Ok(tok)) => {
4474 nxt = Some(tok);
4475 break;
4476 }
4477 None => {
4478 nxt = None;
4479 break;
4480 }
4481 }
4482 }
4483 self.tok0 = self.tok1.take();
4484 self.tok1 = nxt.take();
4485 t
4486 }
4487
4488 fn take_documentation(&mut self, until: u32) -> Option<(u32, EcoString)> {
4489 let mut content = String::new();
4490 let mut doc_start = u32::MAX;
4491 while let Some((start, line)) = self.doc_comments.front() {
4492 if *start < doc_start {
4493 doc_start = *start;
4494 }
4495 if *start >= until {
4496 break;
4497 }
4498
4499 if self.extra.has_comment_between(*start, until) {
4500 // We ignore doc comments that come before a regular comment.
4501 let location = SrcSpan::new(*start, start + line.len() as u32);
4502 _ = self.doc_comments.pop_front();
4503 self.detached_doc_comments.push(location);
4504 continue;
4505 }
4506
4507 content.push_str(line);
4508 content.push('\n');
4509 _ = self.doc_comments.pop_front();
4510 }
4511 if content.is_empty() {
4512 None
4513 } else {
4514 Some((doc_start, content.into()))
4515 }
4516 }
4517
4518 fn parse_attributes(
4519 &mut self,
4520 attributes: &mut Attributes,
4521 ) -> Result<Option<SrcSpan>, ParseError> {
4522 let mut attributes_span = None;
4523
4524 while let Some((start, end)) = self.maybe_one(&Token::At) {
4525 if attributes_span.is_none() {
4526 attributes_span = Some(SrcSpan { start, end });
4527 }
4528
4529 let end = self.parse_attribute(start, attributes)?;
4530 attributes_span = attributes_span.map(|span| SrcSpan {
4531 start: span.start,
4532 end,
4533 });
4534 }
4535
4536 Ok(attributes_span)
4537 }
4538
4539 fn parse_attribute(
4540 &mut self,
4541 start: u32,
4542 attributes: &mut Attributes,
4543 ) -> Result<u32, ParseError> {
4544 // Parse the name of the attribute.
4545
4546 let (_, name, end) = self.expect_name()?;
4547
4548 let end = match name.as_str() {
4549 "external" => {
4550 let _ = self.expect_one(&Token::LeftParen)?;
4551 self.parse_external_attribute(start, end, attributes)
4552 }
4553 "target" => self.parse_target_attribute(start, end, attributes),
4554 "deprecated" => self.parse_deprecated_attribute(start, end, attributes),
4555 "internal" => self.parse_internal_attribute(start, end, attributes),
4556 _ => parse_error(ParseErrorType::UnknownAttribute, SrcSpan { start, end }),
4557 }?;
4558
4559 Ok(end)
4560 }
4561
4562 fn parse_target_attribute(
4563 &mut self,
4564 start: u32,
4565 end: u32,
4566 attributes: &mut Attributes,
4567 ) -> Result<u32, ParseError> {
4568 let (paren_start, paren_end) = self.expect_one(&Token::LeftParen)?;
4569 let target = self.expect_target(SrcSpan::new(paren_start, paren_end))?;
4570 if attributes.target.is_some() {
4571 return parse_error(ParseErrorType::DuplicateAttribute, SrcSpan { start, end });
4572 }
4573 let (_, end) = self.expect_one(&Token::RightParen)?;
4574 if attributes.target.is_some() {
4575 return parse_error(ParseErrorType::DuplicateAttribute, SrcSpan { start, end });
4576 }
4577 attributes.target = Some(target);
4578 Ok(end)
4579 }
4580
4581 fn parse_external_attribute(
4582 &mut self,
4583 start: u32,
4584 end: u32,
4585 attributes: &mut Attributes,
4586 ) -> Result<u32, ParseError> {
4587 let (_, name, _) = self.expect_name()?;
4588
4589 let target = match name.as_str() {
4590 "erlang" => Target::Erlang,
4591 "javascript" => Target::JavaScript,
4592 _ => return parse_error(ParseErrorType::UnknownTarget, SrcSpan::new(start, end)),
4593 };
4594
4595 let _ = self.expect_one(&Token::Comma)?;
4596 let (_, module, _) = self.expect_string()?;
4597 let _ = self.expect_one(&Token::Comma)?;
4598 let (_, function, _) = self.expect_string()?;
4599 let _ = self.maybe_one(&Token::Comma);
4600 let (_, end) = self.expect_one(&Token::RightParen)?;
4601
4602 if attributes.has_external_for(target) {
4603 return parse_error(ParseErrorType::DuplicateAttribute, SrcSpan { start, end });
4604 }
4605
4606 attributes.set_external_for(target, Some((module, function, SrcSpan { start, end })));
4607 Ok(end)
4608 }
4609
4610 fn parse_deprecated_attribute(
4611 &mut self,
4612 start: u32,
4613 end: u32,
4614 attributes: &mut Attributes,
4615 ) -> Result<u32, ParseError> {
4616 let _ = self.expect_one(&Token::LeftParen).map_err(|_| ParseError {
4617 error: ParseErrorType::ExpectedDeprecationMessage,
4618 location: SrcSpan { start, end },
4619 })?;
4620 if attributes.deprecated.is_deprecated() {
4621 return parse_error(ParseErrorType::DuplicateAttribute, SrcSpan::new(start, end));
4622 }
4623 let (_, message, _) = self.expect_string().map_err(|_| ParseError {
4624 error: ParseErrorType::ExpectedDeprecationMessage,
4625 location: SrcSpan { start, end },
4626 })?;
4627 let (_, end) = self.expect_one(&Token::RightParen)?;
4628 attributes.deprecated = Deprecation::Deprecated { message };
4629 Ok(end)
4630 }
4631
4632 fn parse_internal_attribute(
4633 &mut self,
4634 start: u32,
4635 end: u32,
4636 attributes: &mut Attributes,
4637 ) -> Result<u32, ParseError> {
4638 match attributes.internal {
4639 // If `internal` is present that means that we have already run into
4640 // another `@internal` annotation, so it results in a `DuplicateAttribute`
4641 // error.
4642 InternalAttribute::Present(_) => {
4643 parse_error(ParseErrorType::DuplicateAttribute, SrcSpan::new(start, end))
4644 }
4645 InternalAttribute::Missing => {
4646 attributes.internal = InternalAttribute::Present(SrcSpan::new(start, end));
4647 Ok(end)
4648 }
4649 }
4650 }
4651}
4652
4653fn concat_pattern_variable_left_hand_side_error<T>(start: u32, end: u32) -> Result<T, ParseError> {
4654 Err(ParseError {
4655 error: ParseErrorType::ConcatPatternVariableLeftHandSide,
4656 location: SrcSpan::new(start, end),
4657 })
4658}
4659
4660// Operator Precedence Parsing
4661//
4662// Higher number means higher precedence.
4663// All operators are left associative.
4664
4665/// Simple-Precedence-Parser, handle seeing an operator or end
4666fn handle_op<A>(
4667 next_op: Option<(Spanned, u8)>,
4668 opstack: &mut Vec<(Spanned, u8)>,
4669 estack: &mut Vec<A>,
4670 do_reduce: &impl Fn(Spanned, &mut Vec<A>),
4671) -> Option<A> {
4672 let mut next_op = next_op;
4673 loop {
4674 match (opstack.pop(), next_op.take()) {
4675 (None, None) => match estack.pop() {
4676 Some(fin) => {
4677 if estack.is_empty() {
4678 return Some(fin);
4679 } else {
4680 panic!("Expression not fully reduced.")
4681 }
4682 }
4683 _ => {
4684 return None;
4685 }
4686 },
4687
4688 (None, Some(op)) => {
4689 opstack.push(op);
4690 break;
4691 }
4692
4693 (Some((op, _)), None) => do_reduce(op, estack),
4694
4695 (Some((opl, pl)), Some((opr, pr))) => {
4696 match pl.cmp(&pr) {
4697 // all ops are left associative
4698 Ordering::Greater | Ordering::Equal => {
4699 do_reduce(opl, estack);
4700 next_op = Some((opr, pr));
4701 }
4702 Ordering::Less => {
4703 opstack.push((opl, pl));
4704 opstack.push((opr, pr));
4705 break;
4706 }
4707 }
4708 }
4709 }
4710 }
4711 None
4712}
4713
4714fn precedence(t: &Token) -> Option<u8> {
4715 if t == &Token::Pipe {
4716 return Some(6);
4717 };
4718 tok_to_binop(t).map(|op| op.precedence())
4719}
4720
4721fn tok_to_binop(t: &Token) -> Option<BinOp> {
4722 match t {
4723 Token::VbarVbar => Some(BinOp::Or),
4724 Token::AmperAmper => Some(BinOp::And),
4725 Token::EqualEqual => Some(BinOp::Eq),
4726 Token::NotEqual => Some(BinOp::NotEq),
4727 Token::Less => Some(BinOp::LtInt),
4728 Token::LessEqual => Some(BinOp::LtEqInt),
4729 Token::Greater => Some(BinOp::GtInt),
4730 Token::GreaterEqual => Some(BinOp::GtEqInt),
4731 Token::LessDot => Some(BinOp::LtFloat),
4732 Token::LessEqualDot => Some(BinOp::LtEqFloat),
4733 Token::GreaterDot => Some(BinOp::GtFloat),
4734 Token::GreaterEqualDot => Some(BinOp::GtEqFloat),
4735 Token::Plus => Some(BinOp::AddInt),
4736 Token::Minus => Some(BinOp::SubInt),
4737 Token::PlusDot => Some(BinOp::AddFloat),
4738 Token::MinusDot => Some(BinOp::SubFloat),
4739 Token::Percent => Some(BinOp::RemainderInt),
4740 Token::Star => Some(BinOp::MultInt),
4741 Token::StarDot => Some(BinOp::MultFloat),
4742 Token::Slash => Some(BinOp::DivInt),
4743 Token::SlashDot => Some(BinOp::DivFloat),
4744 Token::Concatenate => Some(BinOp::Concatenate),
4745 Token::Name { .. }
4746 | Token::UpName { .. }
4747 | Token::DiscardName { .. }
4748 | Token::Int { .. }
4749 | Token::Float { .. }
4750 | Token::String { .. }
4751 | Token::CommentDoc { .. }
4752 | Token::LeftParen
4753 | Token::RightParen
4754 | Token::LeftSquare
4755 | Token::RightSquare
4756 | Token::LeftBrace
4757 | Token::RightBrace
4758 | Token::Colon
4759 | Token::Comma
4760 | Token::Hash
4761 | Token::Bang
4762 | Token::Equal
4763 | Token::Vbar
4764 | Token::LtLt
4765 | Token::GtGt
4766 | Token::Pipe
4767 | Token::Dot
4768 | Token::RArrow
4769 | Token::LArrow
4770 | Token::DotDot
4771 | Token::At
4772 | Token::EndOfFile
4773 | Token::CommentNormal
4774 | Token::CommentModule
4775 | Token::NewLine
4776 | Token::As
4777 | Token::Assert
4778 | Token::Auto
4779 | Token::Case
4780 | Token::Const
4781 | Token::Delegate
4782 | Token::Derive
4783 | Token::Echo
4784 | Token::Else
4785 | Token::Fn
4786 | Token::If
4787 | Token::Implement
4788 | Token::Import
4789 | Token::Let
4790 | Token::Macro
4791 | Token::Opaque
4792 | Token::Panic
4793 | Token::Pub
4794 | Token::Test
4795 | Token::Todo
4796 | Token::Type
4797 | Token::Use => None,
4798 }
4799}
4800
4801fn token_to_bit_array_size_operator(t: &Token) -> Option<IntOperator> {
4802 match t {
4803 Token::Plus => Some(IntOperator::Add),
4804 Token::Minus => Some(IntOperator::Subtract),
4805 Token::Star => Some(IntOperator::Multiply),
4806 Token::Slash => Some(IntOperator::Divide),
4807 Token::Percent => Some(IntOperator::Remainder),
4808 Token::Name { .. }
4809 | Token::UpName { .. }
4810 | Token::DiscardName { .. }
4811 | Token::Int { .. }
4812 | Token::Float { .. }
4813 | Token::String { .. }
4814 | Token::CommentDoc { .. }
4815 | Token::LeftParen
4816 | Token::RightParen
4817 | Token::LeftSquare
4818 | Token::RightSquare
4819 | Token::LeftBrace
4820 | Token::RightBrace
4821 | Token::Less
4822 | Token::Greater
4823 | Token::LessEqual
4824 | Token::GreaterEqual
4825 | Token::PlusDot
4826 | Token::MinusDot
4827 | Token::StarDot
4828 | Token::SlashDot
4829 | Token::LessDot
4830 | Token::GreaterDot
4831 | Token::LessEqualDot
4832 | Token::GreaterEqualDot
4833 | Token::Concatenate
4834 | Token::Colon
4835 | Token::Comma
4836 | Token::Hash
4837 | Token::Bang
4838 | Token::Equal
4839 | Token::EqualEqual
4840 | Token::NotEqual
4841 | Token::Vbar
4842 | Token::VbarVbar
4843 | Token::AmperAmper
4844 | Token::LtLt
4845 | Token::GtGt
4846 | Token::Pipe
4847 | Token::Dot
4848 | Token::RArrow
4849 | Token::LArrow
4850 | Token::DotDot
4851 | Token::At
4852 | Token::EndOfFile
4853 | Token::CommentNormal
4854 | Token::CommentModule
4855 | Token::NewLine
4856 | Token::As
4857 | Token::Assert
4858 | Token::Auto
4859 | Token::Case
4860 | Token::Const
4861 | Token::Delegate
4862 | Token::Derive
4863 | Token::Echo
4864 | Token::Else
4865 | Token::Fn
4866 | Token::If
4867 | Token::Implement
4868 | Token::Import
4869 | Token::Let
4870 | Token::Macro
4871 | Token::Opaque
4872 | Token::Panic
4873 | Token::Pub
4874 | Token::Test
4875 | Token::Todo
4876 | Token::Type
4877 | Token::Use => None,
4878 }
4879}
4880
4881/// Simple-Precedence-Parser, perform reduction for expression
4882fn do_reduce_expression(op: Spanned, estack: &mut Vec<UntypedExpr>) {
4883 match (estack.pop(), estack.pop()) {
4884 (Some(er), Some(el)) => {
4885 let new_e = expr_op_reduction(op, el, er);
4886 estack.push(new_e);
4887 }
4888 _ => panic!("Tried to reduce without 2 expressions"),
4889 }
4890}
4891
4892/// Simple-Precedence-Parser, perform reduction for clause guard
4893fn do_reduce_clause_guard(op: Spanned, estack: &mut Vec<UntypedClauseGuard>) {
4894 match (estack.pop(), estack.pop()) {
4895 (Some(er), Some(el)) => {
4896 let new_e = clause_guard_reduction(op, el, er);
4897 estack.push(new_e);
4898 }
4899 _ => panic!("Tried to reduce without 2 guards"),
4900 }
4901}
4902
4903/// Simple-Precedence-Parser, perform reduction for bit array size expressions
4904fn reduce_bit_array_size((_, token, _): Spanned, estack: &mut Vec<BitArraySize<()>>) {
4905 let operator = token_to_bit_array_size_operator(&token)
4906 .expect("only operator tokens are pushed onto the bit array size opstack");
4907 match (estack.pop(), estack.pop()) {
4908 (Some(right), Some(left)) => {
4909 let location = SrcSpan {
4910 start: left.location().start,
4911 end: right.location().end,
4912 };
4913 estack.push(BitArraySize::BinaryOperator {
4914 left: Box::new(left),
4915 right: Box::new(right),
4916 operator,
4917 location,
4918 });
4919 }
4920 _ => panic!("Tried to reduce bit array size without 2 operands"),
4921 }
4922}
4923
4924fn expr_op_reduction(
4925 (token_start, token, _token_end): Spanned,
4926 left: UntypedExpr,
4927 right: UntypedExpr,
4928) -> UntypedExpr {
4929 if token == Token::Pipe {
4930 let expressions = if let UntypedExpr::PipeLine { mut expressions } = left {
4931 expressions.push(right);
4932 expressions
4933 } else {
4934 vec1![left, right]
4935 };
4936 UntypedExpr::PipeLine { expressions }
4937 } else {
4938 match tok_to_binop(&token) {
4939 Some(operator) => UntypedExpr::BinOp {
4940 location: SrcSpan {
4941 start: left.location().start,
4942 end: right.location().end,
4943 },
4944 operator,
4945 operator_start: token_start,
4946 left: Box::new(left),
4947 right: Box::new(right),
4948 },
4949 _ => {
4950 panic!("Token could not be converted to binop.")
4951 }
4952 }
4953 }
4954}
4955
4956fn clause_guard_reduction(
4957 (start, token, _end): Spanned,
4958 left: UntypedClauseGuard,
4959 right: UntypedClauseGuard,
4960) -> UntypedClauseGuard {
4961 let location = SrcSpan {
4962 start: left.location().start,
4963 end: right.location().end,
4964 };
4965 let left = Box::new(left);
4966 let right = Box::new(right);
4967 let operator = tok_to_binop(&token).expect("Token could not be converted to binop.");
4968 UntypedClauseGuard::BinaryOperator {
4969 location,
4970 operator,
4971 operator_start: start,
4972 left,
4973 right,
4974 }
4975}
4976
4977// BitArray Parse Helpers
4978//
4979// BitArrays in patterns, guards, and expressions have a very similar structure
4980// but need specific types. These are helpers for that. There is probably a
4981// rustier way to do this :)
4982fn bit_array_size_int(value: EcoString, int_value: BigInt, start: u32, end: u32) -> UntypedPattern {
4983 Pattern::BitArraySize(BitArraySize::Int {
4984 location: SrcSpan { start, end },
4985 value,
4986 int_value,
4987 })
4988}
4989
4990fn bit_array_expr_int(value: EcoString, int_value: BigInt, start: u32, end: u32) -> UntypedExpr {
4991 UntypedExpr::Int {
4992 location: SrcSpan { start, end },
4993 value,
4994 int_value,
4995 }
4996}
4997
4998fn bit_array_const_int(
4999 value: EcoString,
5000 int_value: BigInt,
5001 start: u32,
5002 end: u32,
5003) -> UntypedConstant {
5004 Constant::Int {
5005 location: SrcSpan { start, end },
5006 value,
5007 int_value,
5008 }
5009}
5010
5011fn str_to_bit_array_option<A>(lit: &str, location: SrcSpan) -> Option<BitArrayOption<A>> {
5012 match lit {
5013 "bytes" => Some(BitArrayOption::Bytes { location }),
5014 "int" => Some(BitArrayOption::Int { location }),
5015 "float" => Some(BitArrayOption::Float { location }),
5016 "bits" => Some(BitArrayOption::Bits { location }),
5017 "utf8" => Some(BitArrayOption::Utf8 { location }),
5018 "utf16" => Some(BitArrayOption::Utf16 { location }),
5019 "utf32" => Some(BitArrayOption::Utf32 { location }),
5020 "utf8_codepoint" => Some(BitArrayOption::Utf8Codepoint { location }),
5021 "utf16_codepoint" => Some(BitArrayOption::Utf16Codepoint { location }),
5022 "utf32_codepoint" => Some(BitArrayOption::Utf32Codepoint { location }),
5023 "signed" => Some(BitArrayOption::Signed { location }),
5024 "unsigned" => Some(BitArrayOption::Unsigned { location }),
5025 "big" => Some(BitArrayOption::Big { location }),
5026 "little" => Some(BitArrayOption::Little { location }),
5027 "native" => Some(BitArrayOption::Native { location }),
5028 _ => None,
5029 }
5030}
5031
5032//
5033// Error Helpers
5034//
5035fn parse_error<T>(error: ParseErrorType, location: SrcSpan) -> Result<T, ParseError> {
5036 Err(ParseError { error, location })
5037}
5038
5039//
5040// Misc Helpers
5041//
5042
5043// Parsing a function call into the appropriate structure
5044#[derive(Debug)]
5045pub enum ParserArg {
5046 Arg(Box<CallArg<UntypedExpr>>),
5047 Hole {
5048 name: EcoString,
5049 /// The whole span of the argument.
5050 arg_location: SrcSpan,
5051 /// Just the span of the ignore name.
5052 discard_location: SrcSpan,
5053 label: Option<EcoString>,
5054 },
5055}
5056
5057pub fn make_call(
5058 fun: UntypedExpr,
5059 arguments: Vec<ParserArg>,
5060 start: u32,
5061 end: u32,
5062 open_parenthesis: u32,
5063) -> Result<UntypedExpr, ParseError> {
5064 let mut hole_location = None;
5065
5066 let arguments = arguments
5067 .into_iter()
5068 .map(|argument| match argument {
5069 ParserArg::Arg(arg) => Ok(*arg),
5070 ParserArg::Hole {
5071 arg_location,
5072 discard_location,
5073 name,
5074 label,
5075 } => {
5076 if hole_location.is_some() {
5077 return parse_error(ParseErrorType::TooManyArgHoles, SrcSpan { start, end });
5078 }
5079
5080 hole_location = Some(discard_location);
5081 if name != "_" {
5082 return parse_error(
5083 ParseErrorType::UnexpectedToken {
5084 token: Token::Name { name },
5085 expected: vec!["An expression".into(), "An underscore".into()],
5086 hint: None,
5087 },
5088 arg_location,
5089 );
5090 }
5091
5092 Ok(CallArg {
5093 implicit: None,
5094 label,
5095 location: arg_location,
5096 value: UntypedExpr::Var {
5097 location: discard_location,
5098 name: CAPTURE_VARIABLE.into(),
5099 },
5100 })
5101 }
5102 })
5103 .collect::<Result<_, _>>()?;
5104
5105 let call = UntypedExpr::Call {
5106 location: SrcSpan { start, end },
5107 fun: Box::new(fun),
5108 arguments,
5109 open_parenthesis,
5110 };
5111
5112 match hole_location {
5113 // A normal call
5114 None => Ok(call),
5115
5116 // An anon function using the capture syntax run(_, 1, 2)
5117 Some(hole_location) => Ok(UntypedExpr::Fn {
5118 location: call.location(),
5119 end_of_head_byte_index: call.location().end,
5120 kind: FunctionLiteralKind::Capture {
5121 hole: hole_location,
5122 },
5123 arguments: vec![Arg {
5124 location: hole_location,
5125 annotation: None,
5126 names: ArgNames::Named {
5127 name: CAPTURE_VARIABLE.into(),
5128 location: hole_location,
5129 },
5130 type_: (),
5131 }],
5132 body: vec1![Statement::Expression(call)],
5133 return_annotation: None,
5134 }),
5135 }
5136}
5137
5138#[derive(Debug, Default)]
5139struct ParsedUnqualifiedImports {
5140 types: Vec<UnqualifiedImport>,
5141 values: Vec<UnqualifiedImport>,
5142}
5143
5144/// Parses an Int value to a bigint.
5145///
5146pub fn parse_int_value(value: &str) -> Option<BigInt> {
5147 let (radix, value) = if let Some(value) = value.strip_prefix("0x") {
5148 (16, value)
5149 } else if let Some(value) = value.strip_prefix("0o") {
5150 (8, value)
5151 } else if let Some(value) = value.strip_prefix("0b") {
5152 (2, value)
5153 } else {
5154 (10, value)
5155 };
5156
5157 let value = value.trim_start_matches('_');
5158
5159 BigInt::parse_bytes(value.as_bytes(), radix)
5160}
5161
5162#[derive(Debug, PartialEq, Clone, Copy)]
5163enum ExpressionUnitContext {
5164 FollowingPipe,
5165 Other,
5166}
5167
5168#[derive(Debug, Clone, Copy)]
5169pub enum PatternPosition {
5170 LetAssignment,
5171 CaseClause,
5172 UsePattern,
5173}
5174
5175impl PatternPosition {
5176 pub fn to_declaration(&self) -> VariableDeclaration {
5177 match self {
5178 PatternPosition::LetAssignment => VariableDeclaration::LetPattern,
5179 PatternPosition::CaseClause => VariableDeclaration::ClausePattern,
5180 PatternPosition::UsePattern => VariableDeclaration::UsePattern,
5181 }
5182 }
5183}
5184
5185/// A thin f64 wrapper that does not permit NaN.
5186/// This allows us to implement `Eq`, which require reflexivity.
5187///
5188/// Used for gleam float literals, which cannot be NaN.
5189///
5190/// While there is no syntax for "infinity", float literals might be too big and
5191/// overflow into infinity. This is still allowed so we can parse big literal
5192/// numbers and the error will be raised during the analysis phase.
5193#[derive(Clone, Copy, Debug, PartialEq)]
5194pub struct LiteralFloatValue(f64);
5195
5196impl LiteralFloatValue {
5197 pub const ONE: Self = LiteralFloatValue(1.0);
5198 pub const ZERO: Self = LiteralFloatValue(0.0);
5199
5200 /// Parse from a string, returning `None` if the string
5201 /// is not a valid f64 or the float is `NaN``
5202 pub fn parse(value: &str) -> Option<Self> {
5203 value
5204 .replace("_", "")
5205 .parse::<f64>()
5206 .ok()
5207 .filter(|float| !float.is_nan())
5208 .map(LiteralFloatValue)
5209 }
5210
5211 pub fn value(&self) -> f64 {
5212 self.0
5213 }
5214}
5215
5216impl Eq for LiteralFloatValue {}
5217
5218impl Ord for LiteralFloatValue {
5219 fn cmp(&self, other: &Self) -> Ordering {
5220 self.0
5221 .partial_cmp(&other.0)
5222 .expect("Only NaN comparisons should fail")
5223 }
5224}
5225
5226impl PartialOrd for LiteralFloatValue {
5227 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
5228 Some(self.cmp(other))
5229 }
5230}
5231
5232impl Hash for LiteralFloatValue {
5233 fn hash<H: Hasher>(&self, state: &mut H) {
5234 self.0.to_bits().hash(state)
5235 }
5236}
5237
5238impl Serialize for LiteralFloatValue {
5239 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
5240 where
5241 S: serde::Serializer,
5242 {
5243 serializer.serialize_f64(self.0)
5244 }
5245}
5246
5247impl<'de> Deserialize<'de> for LiteralFloatValue {
5248 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
5249 where
5250 D: serde::Deserializer<'de>,
5251 {
5252 let value = f64::deserialize(deserializer)?;
5253 if value.is_nan() {
5254 Err(serde::de::Error::custom("NaN is not allowed"))
5255 } else {
5256 Ok(LiteralFloatValue(value))
5257 }
5258 }
5259}