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