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