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