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