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