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