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