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