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