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