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