Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

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