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 5252 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 Ok(Some(Constant::Record { 3579 location: SrcSpan { start, end: par_e }, 3580 module, 3581 name, 3582 arguments: Some(arguments), 3583 type_: (), 3584 field_map: Inferred::Unknown, 3585 record_constructor: None, 3586 })) 3587 } 3588 } 3589 _ => Ok(Some(Constant::Record { 3590 location: SrcSpan { start, end }, 3591 module, 3592 name, 3593 arguments: None, 3594 type_: (), 3595 field_map: Inferred::Unknown, 3596 record_constructor: None, 3597 })), 3598 } 3599 } 3600 3601 // examples: 3602 // name: const 3603 // const 3604 // name: 3605 fn parse_const_record_arg(&mut self) -> Result<Option<CallArg<UntypedConstant>>, ParseError> { 3606 let label = match (self.tok0.take(), self.tok1.take()) { 3607 // Named arg 3608 (Some((start, Token::Name { name }, _)), Some((_, Token::Colon, end))) => { 3609 self.advance(); 3610 self.advance(); 3611 Some((start, name, end)) 3612 } 3613 3614 // Unnamed arg 3615 (t0, t1) => { 3616 self.tok0 = t0; 3617 self.tok1 = t1; 3618 None 3619 } 3620 }; 3621 3622 match self.parse_const_value()? { 3623 Some(value) => match label { 3624 Some((start, label, _)) => Ok(Some(CallArg { 3625 implicit: None, 3626 location: SrcSpan { 3627 start, 3628 end: value.location().end, 3629 }, 3630 value, 3631 label: Some(label), 3632 })), 3633 _ => Ok(Some(CallArg { 3634 implicit: None, 3635 location: value.location(), 3636 value, 3637 label: None, 3638 })), 3639 }, 3640 _ => { 3641 match label { 3642 Some((start, label, end)) => { 3643 // Argument supplied with a label shorthand. 3644 Ok(Some(CallArg { 3645 implicit: None, 3646 location: SrcSpan { start, end }, 3647 label: Some(label.clone()), 3648 value: UntypedConstant::Var { 3649 location: SrcSpan { start, end }, 3650 constructor: None, 3651 module: None, 3652 name: label, 3653 type_: (), 3654 }, 3655 })) 3656 } 3657 _ => Ok(None), 3658 } 3659 } 3660 } 3661 } 3662 3663 fn parse_const_record_update_arg( 3664 &mut self, 3665 ) -> Result<Option<RecordUpdateArg<UntypedConstant>>, ParseError> { 3666 let (start, label, label_end) = match (self.tok0.take(), self.tok1.take()) { 3667 // Named arg - required for record updates 3668 (Some((start, Token::Name { name }, _)), Some((_, Token::Colon, end))) => { 3669 self.advance(); 3670 self.advance(); 3671 (start, name, end) 3672 } 3673 3674 // Unnamed arg or other - return error since record updates require labels 3675 (Some((start, Token::Name { name }, end)), t1) => { 3676 self.tok0 = Some((start, Token::Name { name: name.clone() }, end)); 3677 self.tok1 = t1; 3678 3679 // Check if this is label shorthand (name without colon) 3680 // In this case, use the name as both label and value 3681 match self.parse_const_value()? { 3682 Some(value) if value.location() == SrcSpan { start, end } => { 3683 return Ok(Some(RecordUpdateArg { 3684 label: name.clone(), 3685 location: SrcSpan { start, end }, 3686 value, 3687 })); 3688 } 3689 _ => { 3690 self.tok0 = Some((start, Token::Name { name }, end)); 3691 return parse_error(ParseErrorType::ExpectedName, SrcSpan { start, end }); 3692 } 3693 } 3694 } 3695 3696 (t0, t1) => { 3697 self.tok0 = t0; 3698 self.tok1 = t1; 3699 return Ok(None); 3700 } 3701 }; 3702 3703 match self.parse_const_value()? { 3704 Some(value) => Ok(Some(RecordUpdateArg { 3705 label, 3706 location: SrcSpan { 3707 start, 3708 end: value.location().end, 3709 }, 3710 value, 3711 })), 3712 _ => { 3713 // Label shorthand: field without value means field: field 3714 Ok(Some(RecordUpdateArg { 3715 label: label.clone(), 3716 location: SrcSpan { 3717 start, 3718 end: label_end, 3719 }, 3720 value: UntypedConstant::Var { 3721 location: SrcSpan { 3722 start, 3723 end: label_end, 3724 }, 3725 constructor: None, 3726 module: None, 3727 name: label, 3728 type_: (), 3729 }, 3730 })) 3731 } 3732 } 3733 } 3734 3735 // 3736 // Bit String parsing 3737 // 3738 3739 // The structure is roughly the same for pattern, const, and expr 3740 // that's why these functions take functions 3741 // 3742 // pattern (: option)? 3743 fn parse_bit_array_segment<A>( 3744 &mut self, 3745 value_parser: &impl Fn(&mut Self) -> Result<Option<A>, ParseError>, 3746 arg_parser: &impl Fn(&mut Self) -> Result<A, ParseError>, 3747 to_int_segment: &impl Fn(EcoString, BigInt, u32, u32) -> A, 3748 ) -> Result<Option<BitArraySegment<A, ()>>, ParseError> 3749 where 3750 A: HasLocation + std::fmt::Debug, 3751 { 3752 match value_parser(self)? { 3753 Some(value) => { 3754 let options = if self.maybe_one(&Token::Colon).is_some() { 3755 Parser::series_of( 3756 self, 3757 &|this| this.parse_bit_array_option(&arg_parser, &to_int_segment), 3758 Some(&Token::Minus), 3759 )? 3760 } else { 3761 vec![] 3762 }; 3763 let end = options 3764 .last() 3765 .map(|option| option.location().end) 3766 .unwrap_or_else(|| value.location().end); 3767 Ok(Some(BitArraySegment { 3768 location: SrcSpan { 3769 start: value.location().start, 3770 end, 3771 }, 3772 value: Box::new(value), 3773 type_: (), 3774 options, 3775 })) 3776 } 3777 _ => Ok(None), 3778 } 3779 } 3780 3781 // examples: 3782 // 1 3783 // size(1) 3784 // size(five) 3785 // utf8 3786 fn parse_bit_array_option<A: std::fmt::Debug>( 3787 &mut self, 3788 arg_parser: &impl Fn(&mut Self) -> Result<A, ParseError>, 3789 to_int_segment: &impl Fn(EcoString, BigInt, u32, u32) -> A, 3790 ) -> Result<Option<BitArrayOption<A>>, ParseError> { 3791 match self.tok0.take() { 3792 // named segment 3793 Some((start, Token::Name { name }, end)) => { 3794 self.advance(); 3795 if self.maybe_one(&Token::LeftParen).is_some() { 3796 // named function segment 3797 match name.as_str() { 3798 "unit" => match self.tok0.take() { 3799 Some((int_s, Token::Int { value, .. }, int_e)) => { 3800 self.advance(); 3801 let (_, end) = self.expect_one(&Token::RightParen)?; 3802 let v = value.replace("_", ""); 3803 match u8::from_str(&v) { 3804 Ok(units) if units > 0 => Ok(Some(BitArrayOption::Unit { 3805 location: SrcSpan { start, end }, 3806 value: units, 3807 })), 3808 3809 _ => Err(ParseError { 3810 error: ParseErrorType::InvalidBitArrayUnit, 3811 location: SrcSpan { 3812 start: int_s, 3813 end: int_e, 3814 }, 3815 }), 3816 } 3817 } 3818 tok0 => { 3819 self.tok0 = tok0; 3820 self.next_tok_unexpected(vec!["A positive int".into()]) 3821 } 3822 }, 3823 3824 "size" => { 3825 let value = arg_parser(self)?; 3826 let (_, end) = self.expect_one(&Token::RightParen)?; 3827 Ok(Some(BitArrayOption::Size { 3828 location: SrcSpan { start, end }, 3829 value: Box::new(value), 3830 short_form: false, 3831 })) 3832 } 3833 _ => parse_error( 3834 ParseErrorType::InvalidBitArraySegment, 3835 SrcSpan { start, end }, 3836 ), 3837 } 3838 } else { 3839 str_to_bit_array_option(&name, SrcSpan { start, end }) 3840 .ok_or(ParseError { 3841 error: ParseErrorType::InvalidBitArraySegment, 3842 location: SrcSpan { start, end }, 3843 }) 3844 .map(Some) 3845 } 3846 } 3847 // int segment 3848 Some((start, Token::Int { value, int_value }, end)) => { 3849 self.advance(); 3850 Ok(Some(BitArrayOption::Size { 3851 location: SrcSpan { start, end }, 3852 value: Box::new(to_int_segment(value, int_value, start, end)), 3853 short_form: true, 3854 })) 3855 } 3856 // invalid 3857 tok0 => { 3858 self.tok0 = tok0; 3859 self.next_tok_unexpected(vec![ 3860 "A valid bit array segment type".into(), 3861 "See: https://tour.gleam.run/data-types/bit-arrays/".into(), 3862 ]) 3863 } 3864 } 3865 } 3866 3867 fn expect_bit_array_pattern_segment_arg(&mut self) -> Result<UntypedPattern, ParseError> { 3868 Ok(Pattern::BitArraySize(self.expect_bit_array_size()?)) 3869 } 3870 3871 fn expect_bit_array_size(&mut self) -> Result<BitArraySize<()>, ParseError> { 3872 let mut opstack = vec![]; 3873 let mut estack: Vec<BitArraySize<()>> = vec![]; 3874 3875 estack.push(self.parse_bit_array_size_unit()?); 3876 3877 loop { 3878 let Some((op_s, token, op_e)) = self.tok0.take() else { 3879 break; 3880 }; 3881 let Some(prec) = token_to_bit_array_size_operator(&token).map(|op| op.precedence()) 3882 else { 3883 self.tok0 = Some((op_s, token, op_e)); 3884 break; 3885 }; 3886 3887 self.advance(); 3888 let _ = handle_op( 3889 Some(((op_s, token, op_e), prec)), 3890 &mut opstack, 3891 &mut estack, 3892 &reduce_bit_array_size, 3893 ); 3894 3895 estack.push(self.parse_bit_array_size_unit()?); 3896 } 3897 3898 Ok( 3899 handle_op(None, &mut opstack, &mut estack, &reduce_bit_array_size) 3900 .expect("bit array size expression stack should not be empty"), 3901 ) 3902 } 3903 3904 fn parse_bit_array_size_unit(&mut self) -> Result<BitArraySize<()>, ParseError> { 3905 match self.tok0.take() { 3906 Some((start, Token::Name { name }, end)) => { 3907 self.advance(); 3908 Ok(BitArraySize::Variable { 3909 location: SrcSpan { start, end }, 3910 name, 3911 constructor: None, 3912 type_: (), 3913 }) 3914 } 3915 Some((start, Token::Int { value, int_value }, end)) => { 3916 self.advance(); 3917 Ok(BitArraySize::Int { 3918 location: SrcSpan { start, end }, 3919 value, 3920 int_value, 3921 }) 3922 } 3923 Some((start, Token::LeftBrace, _)) => { 3924 self.advance(); 3925 let inner = self.expect_bit_array_size()?; 3926 let (_, end) = self.expect_one(&Token::RightBrace)?; 3927 3928 Ok(BitArraySize::Block { 3929 location: SrcSpan { start, end }, 3930 inner: Box::new(inner), 3931 }) 3932 } 3933 tok0 => { 3934 self.tok0 = tok0; 3935 self.next_tok_unexpected(vec!["A variable name or an int".into()]) 3936 } 3937 } 3938 } 3939 3940 fn expect_const_int(&mut self) -> Result<UntypedConstant, ParseError> { 3941 match self.tok0.take() { 3942 Some((start, Token::Int { value, int_value }, end)) => { 3943 self.advance(); 3944 Ok(Constant::Int { 3945 location: SrcSpan { start, end }, 3946 value, 3947 int_value, 3948 }) 3949 } 3950 tok0 => { 3951 self.tok0 = tok0; 3952 self.next_tok_unexpected(vec!["An int".into()]) 3953 } 3954 } 3955 } 3956 3957 fn expect_expression(&mut self) -> Result<UntypedExpr, ParseError> { 3958 match self.parse_expression()? { 3959 Some(e) => Ok(e), 3960 _ => self.next_tok_unexpected(vec!["An expression".into()]), 3961 } 3962 } 3963 3964 fn expect_expression_unit( 3965 &mut self, 3966 context: ExpressionUnitContext, 3967 ) -> Result<UntypedExpr, ParseError> { 3968 if let Some(e) = self.parse_expression_unit(context)? { 3969 Ok(e) 3970 } else { 3971 self.next_tok_unexpected(vec!["An expression".into()]) 3972 } 3973 } 3974 3975 // 3976 // Parse Helpers 3977 // 3978 3979 /// Expect a particular token, advances the token stream 3980 fn expect_one(&mut self, wanted: &Token) -> Result<(u32, u32), ParseError> { 3981 match self.maybe_one(wanted) { 3982 Some((start, end)) => Ok((start, end)), 3983 None => self.next_tok_unexpected(vec![wanted.to_string().into()]), 3984 } 3985 } 3986 3987 // Expect a particular token after having parsed a series, advances the token stream 3988 // Used for giving a clearer error message in cases where the series item is what failed to parse 3989 fn expect_one_following_series( 3990 &mut self, 3991 wanted: &Token, 3992 series: &'static str, 3993 ) -> Result<(u32, u32), ParseError> { 3994 match self.maybe_one(wanted) { 3995 Some((start, end)) => Ok((start, end)), 3996 None => self.next_tok_unexpected(vec![wanted.to_string().into(), series.into()]), 3997 } 3998 } 3999 4000 /// Expect the end to a custom type definiton or handle an incorrect 4001 /// record constructor definition. 4002 /// 4003 /// Used for mapping to a more specific error type and message. 4004 fn expect_custom_type_close( 4005 &mut self, 4006 name: &EcoString, 4007 public: bool, 4008 opaque: bool, 4009 ) -> Result<(u32, u32), ParseError> { 4010 match self.maybe_one(&Token::RightBrace) { 4011 Some((start, end)) => Ok((start, end)), 4012 None => match self.next_tok() { 4013 None => parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }), 4014 Some((start, token, end)) => { 4015 // If provided a Name, map to a more detailed error 4016 // message to nudge the user. 4017 // Else, handle as an unexpected token. 4018 let field = if let Token::Name { name } = token { 4019 name 4020 } else { 4021 let hint = match (&token, self.tok0.take()) { 4022 (&Token::Fn, _) | (&Token::Pub, Some((_, Token::Fn, _))) => { 4023 let text = "Gleam is not an object oriented programming language so 4024functions are declared separately from types."; 4025 Some(wrap(text).into()) 4026 } 4027 (_, _) => None, 4028 }; 4029 4030 return parse_error( 4031 ParseErrorType::UnexpectedToken { 4032 token, 4033 expected: vec![ 4034 Token::RightBrace.to_string().into(), 4035 "a record constructor".into(), 4036 ], 4037 hint, 4038 }, 4039 SrcSpan { start, end }, 4040 ); 4041 }; 4042 let field_type = match self.parse_type_annotation(&Token::Colon) { 4043 Ok(Some(annotation)) => Some(Box::new(annotation)), 4044 _ => None, 4045 }; 4046 parse_error( 4047 ParseErrorType::ExpectedRecordConstructor { 4048 name: name.clone(), 4049 public, 4050 opaque, 4051 field, 4052 field_type, 4053 }, 4054 SrcSpan { start, end }, 4055 ) 4056 } 4057 }, 4058 } 4059 } 4060 4061 // Expect a Name else a token dependent helpful error 4062 fn expect_name(&mut self) -> Result<(u32, EcoString, u32), ParseError> { 4063 let (start, token, end) = self.expect_assign_name()?; 4064 match token { 4065 AssignName::Variable(name) => Ok((start, name, end)), 4066 AssignName::Discard(_) => { 4067 parse_error(ParseErrorType::IncorrectName, SrcSpan { start, end }) 4068 } 4069 } 4070 } 4071 4072 fn expect_assign_name(&mut self) -> Result<(u32, AssignName, u32), ParseError> { 4073 let t = self.next_tok(); 4074 match t { 4075 Some((start, tok, end)) => match tok { 4076 Token::Name { name } => Ok((start, AssignName::Variable(name), end)), 4077 Token::DiscardName { name, .. } => Ok((start, AssignName::Discard(name), end)), 4078 Token::UpName { .. } => { 4079 parse_error(ParseErrorType::IncorrectName, SrcSpan { start, end }) 4080 } 4081 _ if tok.is_reserved_word() => parse_error( 4082 ParseErrorType::UnexpectedReservedWord, 4083 SrcSpan { start, end }, 4084 ), 4085 Token::Int { .. } 4086 | Token::Float { .. } 4087 | Token::String { .. } 4088 | Token::CommentDoc { .. } 4089 | Token::LeftParen 4090 | Token::RightParen 4091 | Token::LeftSquare 4092 | Token::RightSquare 4093 | Token::LeftBrace 4094 | Token::RightBrace 4095 | Token::Plus 4096 | Token::Minus 4097 | Token::Star 4098 | Token::Slash 4099 | Token::Less 4100 | Token::Greater 4101 | Token::LessEqual 4102 | Token::GreaterEqual 4103 | Token::Percent 4104 | Token::PlusDot 4105 | Token::MinusDot 4106 | Token::StarDot 4107 | Token::SlashDot 4108 | Token::LessDot 4109 | Token::GreaterDot 4110 | Token::LessEqualDot 4111 | Token::GreaterEqualDot 4112 | Token::Concatenate 4113 | Token::Colon 4114 | Token::Comma 4115 | Token::Hash 4116 | Token::Bang 4117 | Token::Equal 4118 | Token::EqualEqual 4119 | Token::NotEqual 4120 | Token::Vbar 4121 | Token::VbarVbar 4122 | Token::AmperAmper 4123 | Token::LtLt 4124 | Token::GtGt 4125 | Token::Pipe 4126 | Token::Dot 4127 | Token::RArrow 4128 | Token::LArrow 4129 | Token::DotDot 4130 | Token::At 4131 | Token::EndOfFile 4132 | Token::CommentNormal 4133 | Token::CommentModule 4134 | Token::NewLine 4135 | Token::As 4136 | Token::Assert 4137 | Token::Auto 4138 | Token::Case 4139 | Token::Const 4140 | Token::Delegate 4141 | Token::Derive 4142 | Token::Echo 4143 | Token::Else 4144 | Token::Fn 4145 | Token::If 4146 | Token::Implement 4147 | Token::Import 4148 | Token::Let 4149 | Token::Macro 4150 | Token::Opaque 4151 | Token::Panic 4152 | Token::Pub 4153 | Token::Test 4154 | Token::Todo 4155 | Token::Type 4156 | Token::Use => parse_error(ParseErrorType::ExpectedName, SrcSpan { start, end }), 4157 }, 4158 None => parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }), 4159 } 4160 } 4161 4162 // Expect an UpName else a token dependent helpful error 4163 fn expect_upname(&mut self) -> Result<(u32, EcoString, u32), ParseError> { 4164 let t = self.next_tok(); 4165 match t { 4166 Some((start, tok, end)) => match tok { 4167 Token::Name { .. } | Token::DiscardName { .. } => { 4168 parse_error(ParseErrorType::IncorrectUpName, SrcSpan { start, end }) 4169 } 4170 Token::UpName { name } => Ok((start, name, end)), 4171 Token::Int { .. } 4172 | Token::Float { .. } 4173 | Token::String { .. } 4174 | Token::CommentDoc { .. } 4175 | Token::LeftParen 4176 | Token::RightParen 4177 | Token::LeftSquare 4178 | Token::RightSquare 4179 | Token::LeftBrace 4180 | Token::RightBrace 4181 | Token::Plus 4182 | Token::Minus 4183 | Token::Star 4184 | Token::Slash 4185 | Token::Less 4186 | Token::Greater 4187 | Token::LessEqual 4188 | Token::GreaterEqual 4189 | Token::Percent 4190 | Token::PlusDot 4191 | Token::MinusDot 4192 | Token::StarDot 4193 | Token::SlashDot 4194 | Token::LessDot 4195 | Token::GreaterDot 4196 | Token::LessEqualDot 4197 | Token::GreaterEqualDot 4198 | Token::Concatenate 4199 | Token::Colon 4200 | Token::Comma 4201 | Token::Hash 4202 | Token::Bang 4203 | Token::Equal 4204 | Token::EqualEqual 4205 | Token::NotEqual 4206 | Token::Vbar 4207 | Token::VbarVbar 4208 | Token::AmperAmper 4209 | Token::LtLt 4210 | Token::GtGt 4211 | Token::Pipe 4212 | Token::Dot 4213 | Token::RArrow 4214 | Token::LArrow 4215 | Token::DotDot 4216 | Token::At 4217 | Token::EndOfFile 4218 | Token::CommentNormal 4219 | Token::CommentModule 4220 | Token::NewLine 4221 | Token::As 4222 | Token::Assert 4223 | Token::Auto 4224 | Token::Case 4225 | Token::Const 4226 | Token::Delegate 4227 | Token::Derive 4228 | Token::Echo 4229 | Token::Else 4230 | Token::Fn 4231 | Token::If 4232 | Token::Implement 4233 | Token::Import 4234 | Token::Let 4235 | Token::Macro 4236 | Token::Opaque 4237 | Token::Panic 4238 | Token::Pub 4239 | Token::Test 4240 | Token::Todo 4241 | Token::Type 4242 | Token::Use => parse_error(ParseErrorType::ExpectedUpName, SrcSpan { start, end }), 4243 }, 4244 None => parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }), 4245 } 4246 } 4247 4248 // Expect a target name. e.g. `javascript` or `erlang`. 4249 // The location of the preceding left parenthesis is required 4250 // to give the correct error span in case the target name is missing. 4251 fn expect_target(&mut self, paren_location: SrcSpan) -> Result<Target, ParseError> { 4252 let (start, t, end) = match self.next_tok() { 4253 Some(t) => t, 4254 None => { 4255 return parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }); 4256 } 4257 }; 4258 if let Token::Name { name } = t { 4259 match name.as_str() { 4260 "javascript" => Ok(Target::JavaScript), 4261 "erlang" => Ok(Target::Erlang), 4262 "js" => { 4263 self.warnings 4264 .push(DeprecatedSyntaxWarning::DeprecatedTargetShorthand { 4265 location: SrcSpan::new(start, end), 4266 target: Target::JavaScript, 4267 }); 4268 Ok(Target::JavaScript) 4269 } 4270 "erl" => { 4271 self.warnings 4272 .push(DeprecatedSyntaxWarning::DeprecatedTargetShorthand { 4273 location: SrcSpan::new(start, end), 4274 target: Target::Erlang, 4275 }); 4276 Ok(Target::Erlang) 4277 } 4278 _ => parse_error(ParseErrorType::UnknownTarget, SrcSpan::new(start, end)), 4279 } 4280 } else { 4281 parse_error(ParseErrorType::ExpectedTargetName, paren_location) 4282 } 4283 } 4284 4285 // Expect a String else error 4286 fn expect_string(&mut self) -> Result<(u32, EcoString, u32), ParseError> { 4287 match self.tok0.take() { 4288 Some((start, Token::String { value }, end)) => { 4289 self.advance(); 4290 Ok((start, value, end)) 4291 } 4292 tok0 => { 4293 self.tok0 = tok0; 4294 self.next_tok_unexpected(vec!["a string".into()]) 4295 } 4296 } 4297 } 4298 4299 fn peek_tok1(&mut self) -> Option<&Token> { 4300 self.tok1.as_ref().map(|(_, token, _)| token) 4301 } 4302 4303 // If the next token matches the requested, consume it and return (start, end) 4304 fn maybe_one(&mut self, tok: &Token) -> Option<(u32, u32)> { 4305 match self.tok0.take() { 4306 Some((s, t, e)) if t == *tok => { 4307 self.advance(); 4308 Some((s, e)) 4309 } 4310 4311 t0 => { 4312 self.tok0 = t0; 4313 None 4314 } 4315 } 4316 } 4317 4318 // Parse a series by repeating a parser, and possibly a separator 4319 fn series_of<A>( 4320 &mut self, 4321 parser: &impl Fn(&mut Self) -> Result<Option<A>, ParseError>, 4322 sep: Option<&Token>, 4323 ) -> Result<Vec<A>, ParseError> { 4324 let (res, _) = self.series_of_has_trailing_separator(parser, sep)?; 4325 Ok(res) 4326 } 4327 4328 /// Parse a series by repeating a parser, and a separator. Returns true if 4329 /// the series ends with the trailing separator. 4330 fn series_of_has_trailing_separator<A>( 4331 &mut self, 4332 parser: &impl Fn(&mut Self) -> Result<Option<A>, ParseError>, 4333 sep: Option<&Token>, 4334 ) -> Result<(Vec<A>, bool), ParseError> { 4335 let mut results = vec![]; 4336 let mut final_separator = None; 4337 while let Some(result) = parser(self)? { 4338 results.push(result); 4339 if let Some(sep) = sep { 4340 if let Some(separator) = self.maybe_one(sep) { 4341 final_separator = Some(separator); 4342 } else { 4343 final_separator = None; 4344 break; 4345 } 4346 4347 // Helpful error if extra separator 4348 if let Some((start, end)) = self.maybe_one(sep) { 4349 return parse_error(ParseErrorType::ExtraSeparator, SrcSpan { start, end }); 4350 } 4351 } 4352 } 4353 4354 // If the sequence ends with a trailing comma we want to keep track of 4355 // its position. 4356 if let (Some(Token::Comma), Some((_, end))) = (sep, final_separator) { 4357 self.extra.trailing_commas.push(end) 4358 }; 4359 4360 Ok((results, final_separator.is_some())) 4361 } 4362 4363 // If next token is a Name, consume it and return relevant info, otherwise, return none 4364 fn maybe_name(&mut self) -> Option<(u32, EcoString, u32)> { 4365 match self.tok0.take() { 4366 Some((s, Token::Name { name }, e)) => { 4367 self.advance(); 4368 Some((s, name, e)) 4369 } 4370 t0 => { 4371 self.tok0 = t0; 4372 None 4373 } 4374 } 4375 } 4376 4377 // if next token is an UpName, consume it and return relevant info, otherwise, return none 4378 fn maybe_upname(&mut self) -> Option<(u32, EcoString, u32)> { 4379 match self.tok0.take() { 4380 Some((s, Token::UpName { name }, e)) => { 4381 self.advance(); 4382 Some((s, name, e)) 4383 } 4384 t0 => { 4385 self.tok0 = t0; 4386 None 4387 } 4388 } 4389 } 4390 4391 // if next token is a DiscardName, consume it and return relevant info, otherwise, return none 4392 fn maybe_discard_name(&mut self) -> Option<(u32, EcoString, u32)> { 4393 match self.tok0.take() { 4394 Some((s, Token::DiscardName { name }, e)) => { 4395 self.advance(); 4396 Some((s, name, e)) 4397 } 4398 t0 => { 4399 self.tok0 = t0; 4400 None 4401 } 4402 } 4403 } 4404 4405 // Unexpected token error on the next token or EOF 4406 fn next_tok_unexpected<A>(&mut self, expected: Vec<EcoString>) -> Result<A, ParseError> { 4407 match self.next_tok() { 4408 None => parse_error(ParseErrorType::UnexpectedEof, SrcSpan { start: 0, end: 0 }), 4409 Some((start, token, end)) => parse_error( 4410 ParseErrorType::UnexpectedToken { 4411 token, 4412 expected, 4413 hint: None, 4414 }, 4415 SrcSpan { start, end }, 4416 ), 4417 } 4418 } 4419 4420 // Moves the token stream forward 4421 fn advance(&mut self) { 4422 let _ = self.next_tok(); 4423 } 4424 4425 // Moving the token stream forward 4426 // returns old tok0 4427 fn next_tok(&mut self) -> Option<Spanned> { 4428 let t = self.tok0.take(); 4429 let mut previous_newline = None; 4430 let mut nxt; 4431 loop { 4432 match self.tokens.next() { 4433 // gather and skip extra 4434 Some(Ok((start, Token::CommentNormal, end))) => { 4435 self.extra.comments.push(SrcSpan { start, end }); 4436 previous_newline = None; 4437 } 4438 Some(Ok((start, Token::CommentDoc { content }, end))) => { 4439 self.extra.doc_comments.push(SrcSpan::new(start, end)); 4440 self.doc_comments.push_back((start, content)); 4441 previous_newline = None; 4442 } 4443 Some(Ok((start, Token::CommentModule, end))) => { 4444 self.extra.module_comments.push(SrcSpan { start, end }); 4445 previous_newline = None; 4446 } 4447 Some(Ok((start, Token::NewLine, _))) => { 4448 self.extra.new_lines.push(start); 4449 // If the previous token is a newline as well that means we 4450 // have run into an empty line. 4451 if let Some(start) = previous_newline { 4452 // We increase the byte position so that newline's start 4453 // doesn't overlap with the previous token's end. 4454 self.extra.empty_lines.push(start + 1); 4455 } 4456 previous_newline = Some(start); 4457 } 4458 4459 // die on lex error 4460 Some(Err(err)) => { 4461 nxt = None; 4462 self.lex_errors.push(err); 4463 break; 4464 } 4465 4466 Some(Ok(tok)) => { 4467 nxt = Some(tok); 4468 break; 4469 } 4470 None => { 4471 nxt = None; 4472 break; 4473 } 4474 } 4475 } 4476 self.tok0 = self.tok1.take(); 4477 self.tok1 = nxt.take(); 4478 t 4479 } 4480 4481 fn take_documentation(&mut self, until: u32) -> Option<(u32, EcoString)> { 4482 let mut content = String::new(); 4483 let mut doc_start = u32::MAX; 4484 while let Some((start, line)) = self.doc_comments.front() { 4485 if *start < doc_start { 4486 doc_start = *start; 4487 } 4488 if *start >= until { 4489 break; 4490 } 4491 4492 if self.extra.has_comment_between(*start, until) { 4493 // We ignore doc comments that come before a regular comment. 4494 let location = SrcSpan::new(*start, start + line.len() as u32); 4495 _ = self.doc_comments.pop_front(); 4496 self.detached_doc_comments.push(location); 4497 continue; 4498 } 4499 4500 content.push_str(line); 4501 content.push('\n'); 4502 _ = self.doc_comments.pop_front(); 4503 } 4504 if content.is_empty() { 4505 None 4506 } else { 4507 Some((doc_start, content.into())) 4508 } 4509 } 4510 4511 fn parse_attributes( 4512 &mut self, 4513 attributes: &mut Attributes, 4514 ) -> Result<Option<SrcSpan>, ParseError> { 4515 let mut attributes_span = None; 4516 4517 while let Some((start, end)) = self.maybe_one(&Token::At) { 4518 if attributes_span.is_none() { 4519 attributes_span = Some(SrcSpan { start, end }); 4520 } 4521 4522 let end = self.parse_attribute(start, attributes)?; 4523 attributes_span = attributes_span.map(|span| SrcSpan { 4524 start: span.start, 4525 end, 4526 }); 4527 } 4528 4529 Ok(attributes_span) 4530 } 4531 4532 fn parse_attribute( 4533 &mut self, 4534 start: u32, 4535 attributes: &mut Attributes, 4536 ) -> Result<u32, ParseError> { 4537 // Parse the name of the attribute. 4538 4539 let (_, name, end) = self.expect_name()?; 4540 4541 let end = match name.as_str() { 4542 "external" => { 4543 let _ = self.expect_one(&Token::LeftParen)?; 4544 self.parse_external_attribute(start, end, attributes) 4545 } 4546 "target" => self.parse_target_attribute(start, end, attributes), 4547 "deprecated" => self.parse_deprecated_attribute(start, end, attributes), 4548 "internal" => self.parse_internal_attribute(start, end, attributes), 4549 _ => parse_error(ParseErrorType::UnknownAttribute, SrcSpan { start, end }), 4550 }?; 4551 4552 Ok(end) 4553 } 4554 4555 fn parse_target_attribute( 4556 &mut self, 4557 start: u32, 4558 end: u32, 4559 attributes: &mut Attributes, 4560 ) -> Result<u32, ParseError> { 4561 let (paren_start, paren_end) = self.expect_one(&Token::LeftParen)?; 4562 let target = self.expect_target(SrcSpan::new(paren_start, paren_end))?; 4563 if attributes.target.is_some() { 4564 return parse_error(ParseErrorType::DuplicateAttribute, SrcSpan { start, end }); 4565 } 4566 let (_, end) = self.expect_one(&Token::RightParen)?; 4567 if attributes.target.is_some() { 4568 return parse_error(ParseErrorType::DuplicateAttribute, SrcSpan { start, end }); 4569 } 4570 attributes.target = Some(target); 4571 Ok(end) 4572 } 4573 4574 fn parse_external_attribute( 4575 &mut self, 4576 start: u32, 4577 end: u32, 4578 attributes: &mut Attributes, 4579 ) -> Result<u32, ParseError> { 4580 let (_, name, _) = self.expect_name()?; 4581 4582 let target = match name.as_str() { 4583 "erlang" => Target::Erlang, 4584 "javascript" => Target::JavaScript, 4585 _ => return parse_error(ParseErrorType::UnknownTarget, SrcSpan::new(start, end)), 4586 }; 4587 4588 let _ = self.expect_one(&Token::Comma)?; 4589 let (_, module, _) = self.expect_string()?; 4590 let _ = self.expect_one(&Token::Comma)?; 4591 let (_, function, _) = self.expect_string()?; 4592 let _ = self.maybe_one(&Token::Comma); 4593 let (_, end) = self.expect_one(&Token::RightParen)?; 4594 4595 if attributes.has_external_for(target) { 4596 return parse_error(ParseErrorType::DuplicateAttribute, SrcSpan { start, end }); 4597 } 4598 4599 attributes.set_external_for(target, Some((module, function, SrcSpan { start, end }))); 4600 Ok(end) 4601 } 4602 4603 fn parse_deprecated_attribute( 4604 &mut self, 4605 start: u32, 4606 end: u32, 4607 attributes: &mut Attributes, 4608 ) -> Result<u32, ParseError> { 4609 let _ = self.expect_one(&Token::LeftParen).map_err(|_| ParseError { 4610 error: ParseErrorType::ExpectedDeprecationMessage, 4611 location: SrcSpan { start, end }, 4612 })?; 4613 if attributes.deprecated.is_deprecated() { 4614 return parse_error(ParseErrorType::DuplicateAttribute, SrcSpan::new(start, end)); 4615 } 4616 let (_, message, _) = self.expect_string().map_err(|_| ParseError { 4617 error: ParseErrorType::ExpectedDeprecationMessage, 4618 location: SrcSpan { start, end }, 4619 })?; 4620 let (_, end) = self.expect_one(&Token::RightParen)?; 4621 attributes.deprecated = Deprecation::Deprecated { message }; 4622 Ok(end) 4623 } 4624 4625 fn parse_internal_attribute( 4626 &mut self, 4627 start: u32, 4628 end: u32, 4629 attributes: &mut Attributes, 4630 ) -> Result<u32, ParseError> { 4631 match attributes.internal { 4632 // If `internal` is present that means that we have already run into 4633 // another `@internal` annotation, so it results in a `DuplicateAttribute` 4634 // error. 4635 InternalAttribute::Present(_) => { 4636 parse_error(ParseErrorType::DuplicateAttribute, SrcSpan::new(start, end)) 4637 } 4638 InternalAttribute::Missing => { 4639 attributes.internal = InternalAttribute::Present(SrcSpan::new(start, end)); 4640 Ok(end) 4641 } 4642 } 4643 } 4644} 4645 4646fn concat_pattern_variable_left_hand_side_error<T>(start: u32, end: u32) -> Result<T, ParseError> { 4647 Err(ParseError { 4648 error: ParseErrorType::ConcatPatternVariableLeftHandSide, 4649 location: SrcSpan::new(start, end), 4650 }) 4651} 4652 4653// Operator Precedence Parsing 4654// 4655// Higher number means higher precedence. 4656// All operators are left associative. 4657 4658/// Simple-Precedence-Parser, handle seeing an operator or end 4659fn handle_op<A>( 4660 next_op: Option<(Spanned, u8)>, 4661 opstack: &mut Vec<(Spanned, u8)>, 4662 estack: &mut Vec<A>, 4663 do_reduce: &impl Fn(Spanned, &mut Vec<A>), 4664) -> Option<A> { 4665 let mut next_op = next_op; 4666 loop { 4667 match (opstack.pop(), next_op.take()) { 4668 (None, None) => match estack.pop() { 4669 Some(fin) => { 4670 if estack.is_empty() { 4671 return Some(fin); 4672 } else { 4673 panic!("Expression not fully reduced.") 4674 } 4675 } 4676 _ => { 4677 return None; 4678 } 4679 }, 4680 4681 (None, Some(op)) => { 4682 opstack.push(op); 4683 break; 4684 } 4685 4686 (Some((op, _)), None) => do_reduce(op, estack), 4687 4688 (Some((opl, pl)), Some((opr, pr))) => { 4689 match pl.cmp(&pr) { 4690 // all ops are left associative 4691 Ordering::Greater | Ordering::Equal => { 4692 do_reduce(opl, estack); 4693 next_op = Some((opr, pr)); 4694 } 4695 Ordering::Less => { 4696 opstack.push((opl, pl)); 4697 opstack.push((opr, pr)); 4698 break; 4699 } 4700 } 4701 } 4702 } 4703 } 4704 None 4705} 4706 4707fn precedence(t: &Token) -> Option<u8> { 4708 if t == &Token::Pipe { 4709 return Some(6); 4710 }; 4711 tok_to_binop(t).map(|op| op.precedence()) 4712} 4713 4714fn tok_to_binop(t: &Token) -> Option<BinOp> { 4715 match t { 4716 Token::VbarVbar => Some(BinOp::Or), 4717 Token::AmperAmper => Some(BinOp::And), 4718 Token::EqualEqual => Some(BinOp::Eq), 4719 Token::NotEqual => Some(BinOp::NotEq), 4720 Token::Less => Some(BinOp::LtInt), 4721 Token::LessEqual => Some(BinOp::LtEqInt), 4722 Token::Greater => Some(BinOp::GtInt), 4723 Token::GreaterEqual => Some(BinOp::GtEqInt), 4724 Token::LessDot => Some(BinOp::LtFloat), 4725 Token::LessEqualDot => Some(BinOp::LtEqFloat), 4726 Token::GreaterDot => Some(BinOp::GtFloat), 4727 Token::GreaterEqualDot => Some(BinOp::GtEqFloat), 4728 Token::Plus => Some(BinOp::AddInt), 4729 Token::Minus => Some(BinOp::SubInt), 4730 Token::PlusDot => Some(BinOp::AddFloat), 4731 Token::MinusDot => Some(BinOp::SubFloat), 4732 Token::Percent => Some(BinOp::RemainderInt), 4733 Token::Star => Some(BinOp::MultInt), 4734 Token::StarDot => Some(BinOp::MultFloat), 4735 Token::Slash => Some(BinOp::DivInt), 4736 Token::SlashDot => Some(BinOp::DivFloat), 4737 Token::Concatenate => Some(BinOp::Concatenate), 4738 Token::Name { .. } 4739 | Token::UpName { .. } 4740 | Token::DiscardName { .. } 4741 | Token::Int { .. } 4742 | Token::Float { .. } 4743 | Token::String { .. } 4744 | Token::CommentDoc { .. } 4745 | Token::LeftParen 4746 | Token::RightParen 4747 | Token::LeftSquare 4748 | Token::RightSquare 4749 | Token::LeftBrace 4750 | Token::RightBrace 4751 | Token::Colon 4752 | Token::Comma 4753 | Token::Hash 4754 | Token::Bang 4755 | Token::Equal 4756 | Token::Vbar 4757 | Token::LtLt 4758 | Token::GtGt 4759 | Token::Pipe 4760 | Token::Dot 4761 | Token::RArrow 4762 | Token::LArrow 4763 | Token::DotDot 4764 | Token::At 4765 | Token::EndOfFile 4766 | Token::CommentNormal 4767 | Token::CommentModule 4768 | Token::NewLine 4769 | Token::As 4770 | Token::Assert 4771 | Token::Auto 4772 | Token::Case 4773 | Token::Const 4774 | Token::Delegate 4775 | Token::Derive 4776 | Token::Echo 4777 | Token::Else 4778 | Token::Fn 4779 | Token::If 4780 | Token::Implement 4781 | Token::Import 4782 | Token::Let 4783 | Token::Macro 4784 | Token::Opaque 4785 | Token::Panic 4786 | Token::Pub 4787 | Token::Test 4788 | Token::Todo 4789 | Token::Type 4790 | Token::Use => None, 4791 } 4792} 4793 4794fn token_to_bit_array_size_operator(t: &Token) -> Option<IntOperator> { 4795 match t { 4796 Token::Plus => Some(IntOperator::Add), 4797 Token::Minus => Some(IntOperator::Subtract), 4798 Token::Star => Some(IntOperator::Multiply), 4799 Token::Slash => Some(IntOperator::Divide), 4800 Token::Percent => Some(IntOperator::Remainder), 4801 Token::Name { .. } 4802 | Token::UpName { .. } 4803 | Token::DiscardName { .. } 4804 | Token::Int { .. } 4805 | Token::Float { .. } 4806 | Token::String { .. } 4807 | Token::CommentDoc { .. } 4808 | Token::LeftParen 4809 | Token::RightParen 4810 | Token::LeftSquare 4811 | Token::RightSquare 4812 | Token::LeftBrace 4813 | Token::RightBrace 4814 | Token::Less 4815 | Token::Greater 4816 | Token::LessEqual 4817 | Token::GreaterEqual 4818 | Token::PlusDot 4819 | Token::MinusDot 4820 | Token::StarDot 4821 | Token::SlashDot 4822 | Token::LessDot 4823 | Token::GreaterDot 4824 | Token::LessEqualDot 4825 | Token::GreaterEqualDot 4826 | Token::Concatenate 4827 | Token::Colon 4828 | Token::Comma 4829 | Token::Hash 4830 | Token::Bang 4831 | Token::Equal 4832 | Token::EqualEqual 4833 | Token::NotEqual 4834 | Token::Vbar 4835 | Token::VbarVbar 4836 | Token::AmperAmper 4837 | Token::LtLt 4838 | Token::GtGt 4839 | Token::Pipe 4840 | Token::Dot 4841 | Token::RArrow 4842 | Token::LArrow 4843 | Token::DotDot 4844 | Token::At 4845 | Token::EndOfFile 4846 | Token::CommentNormal 4847 | Token::CommentModule 4848 | Token::NewLine 4849 | Token::As 4850 | Token::Assert 4851 | Token::Auto 4852 | Token::Case 4853 | Token::Const 4854 | Token::Delegate 4855 | Token::Derive 4856 | Token::Echo 4857 | Token::Else 4858 | Token::Fn 4859 | Token::If 4860 | Token::Implement 4861 | Token::Import 4862 | Token::Let 4863 | Token::Macro 4864 | Token::Opaque 4865 | Token::Panic 4866 | Token::Pub 4867 | Token::Test 4868 | Token::Todo 4869 | Token::Type 4870 | Token::Use => None, 4871 } 4872} 4873 4874/// Simple-Precedence-Parser, perform reduction for expression 4875fn do_reduce_expression(op: Spanned, estack: &mut Vec<UntypedExpr>) { 4876 match (estack.pop(), estack.pop()) { 4877 (Some(er), Some(el)) => { 4878 let new_e = expr_op_reduction(op, el, er); 4879 estack.push(new_e); 4880 } 4881 _ => panic!("Tried to reduce without 2 expressions"), 4882 } 4883} 4884 4885/// Simple-Precedence-Parser, perform reduction for clause guard 4886fn do_reduce_clause_guard(op: Spanned, estack: &mut Vec<UntypedClauseGuard>) { 4887 match (estack.pop(), estack.pop()) { 4888 (Some(er), Some(el)) => { 4889 let new_e = clause_guard_reduction(op, el, er); 4890 estack.push(new_e); 4891 } 4892 _ => panic!("Tried to reduce without 2 guards"), 4893 } 4894} 4895 4896/// Simple-Precedence-Parser, perform reduction for bit array size expressions 4897fn reduce_bit_array_size((_, token, _): Spanned, estack: &mut Vec<BitArraySize<()>>) { 4898 let operator = token_to_bit_array_size_operator(&token) 4899 .expect("only operator tokens are pushed onto the bit array size opstack"); 4900 match (estack.pop(), estack.pop()) { 4901 (Some(right), Some(left)) => { 4902 let location = SrcSpan { 4903 start: left.location().start, 4904 end: right.location().end, 4905 }; 4906 estack.push(BitArraySize::BinaryOperator { 4907 left: Box::new(left), 4908 right: Box::new(right), 4909 operator, 4910 location, 4911 }); 4912 } 4913 _ => panic!("Tried to reduce bit array size without 2 operands"), 4914 } 4915} 4916 4917fn expr_op_reduction( 4918 (token_start, token, _token_end): Spanned, 4919 left: UntypedExpr, 4920 right: UntypedExpr, 4921) -> UntypedExpr { 4922 if token == Token::Pipe { 4923 let expressions = if let UntypedExpr::PipeLine { mut expressions } = left { 4924 expressions.push(right); 4925 expressions 4926 } else { 4927 vec1![left, right] 4928 }; 4929 UntypedExpr::PipeLine { expressions } 4930 } else { 4931 match tok_to_binop(&token) { 4932 Some(operator) => UntypedExpr::BinOp { 4933 location: SrcSpan { 4934 start: left.location().start, 4935 end: right.location().end, 4936 }, 4937 operator, 4938 operator_start: token_start, 4939 left: Box::new(left), 4940 right: Box::new(right), 4941 }, 4942 _ => { 4943 panic!("Token could not be converted to binop.") 4944 } 4945 } 4946 } 4947} 4948 4949fn clause_guard_reduction( 4950 (start, token, _end): Spanned, 4951 left: UntypedClauseGuard, 4952 right: UntypedClauseGuard, 4953) -> UntypedClauseGuard { 4954 let location = SrcSpan { 4955 start: left.location().start, 4956 end: right.location().end, 4957 }; 4958 let left = Box::new(left); 4959 let right = Box::new(right); 4960 let operator = tok_to_binop(&token).expect("Token could not be converted to binop."); 4961 UntypedClauseGuard::BinaryOperator { 4962 location, 4963 operator, 4964 operator_start: start, 4965 left, 4966 right, 4967 } 4968} 4969 4970// BitArray Parse Helpers 4971// 4972// BitArrays in patterns, guards, and expressions have a very similar structure 4973// but need specific types. These are helpers for that. There is probably a 4974// rustier way to do this :) 4975fn bit_array_size_int(value: EcoString, int_value: BigInt, start: u32, end: u32) -> UntypedPattern { 4976 Pattern::BitArraySize(BitArraySize::Int { 4977 location: SrcSpan { start, end }, 4978 value, 4979 int_value, 4980 }) 4981} 4982 4983fn bit_array_expr_int(value: EcoString, int_value: BigInt, start: u32, end: u32) -> UntypedExpr { 4984 UntypedExpr::Int { 4985 location: SrcSpan { start, end }, 4986 value, 4987 int_value, 4988 } 4989} 4990 4991fn bit_array_const_int( 4992 value: EcoString, 4993 int_value: BigInt, 4994 start: u32, 4995 end: u32, 4996) -> UntypedConstant { 4997 Constant::Int { 4998 location: SrcSpan { start, end }, 4999 value, 5000 int_value, 5001 } 5002} 5003 5004fn str_to_bit_array_option<A>(lit: &str, location: SrcSpan) -> Option<BitArrayOption<A>> { 5005 match lit { 5006 "bytes" => Some(BitArrayOption::Bytes { location }), 5007 "int" => Some(BitArrayOption::Int { location }), 5008 "float" => Some(BitArrayOption::Float { location }), 5009 "bits" => Some(BitArrayOption::Bits { location }), 5010 "utf8" => Some(BitArrayOption::Utf8 { location }), 5011 "utf16" => Some(BitArrayOption::Utf16 { location }), 5012 "utf32" => Some(BitArrayOption::Utf32 { location }), 5013 "utf8_codepoint" => Some(BitArrayOption::Utf8Codepoint { location }), 5014 "utf16_codepoint" => Some(BitArrayOption::Utf16Codepoint { location }), 5015 "utf32_codepoint" => Some(BitArrayOption::Utf32Codepoint { location }), 5016 "signed" => Some(BitArrayOption::Signed { location }), 5017 "unsigned" => Some(BitArrayOption::Unsigned { location }), 5018 "big" => Some(BitArrayOption::Big { location }), 5019 "little" => Some(BitArrayOption::Little { location }), 5020 "native" => Some(BitArrayOption::Native { location }), 5021 _ => None, 5022 } 5023} 5024 5025// 5026// Error Helpers 5027// 5028fn parse_error<T>(error: ParseErrorType, location: SrcSpan) -> Result<T, ParseError> { 5029 Err(ParseError { error, location }) 5030} 5031 5032// 5033// Misc Helpers 5034// 5035 5036// Parsing a function call into the appropriate structure 5037#[derive(Debug)] 5038pub enum ParserArg { 5039 Arg(Box<CallArg<UntypedExpr>>), 5040 Hole { 5041 name: EcoString, 5042 /// The whole span of the argument. 5043 arg_location: SrcSpan, 5044 /// Just the span of the ignore name. 5045 discard_location: SrcSpan, 5046 label: Option<EcoString>, 5047 }, 5048} 5049 5050pub fn make_call( 5051 fun: UntypedExpr, 5052 arguments: Vec<ParserArg>, 5053 start: u32, 5054 end: u32, 5055 open_parenthesis: u32, 5056) -> Result<UntypedExpr, ParseError> { 5057 let mut hole_location = None; 5058 5059 let arguments = arguments 5060 .into_iter() 5061 .map(|argument| match argument { 5062 ParserArg::Arg(arg) => Ok(*arg), 5063 ParserArg::Hole { 5064 arg_location, 5065 discard_location, 5066 name, 5067 label, 5068 } => { 5069 if hole_location.is_some() { 5070 return parse_error(ParseErrorType::TooManyArgHoles, SrcSpan { start, end }); 5071 } 5072 5073 hole_location = Some(discard_location); 5074 if name != "_" { 5075 return parse_error( 5076 ParseErrorType::UnexpectedToken { 5077 token: Token::Name { name }, 5078 expected: vec!["An expression".into(), "An underscore".into()], 5079 hint: None, 5080 }, 5081 arg_location, 5082 ); 5083 } 5084 5085 Ok(CallArg { 5086 implicit: None, 5087 label, 5088 location: arg_location, 5089 value: UntypedExpr::Var { 5090 location: discard_location, 5091 name: CAPTURE_VARIABLE.into(), 5092 }, 5093 }) 5094 } 5095 }) 5096 .collect::<Result<_, _>>()?; 5097 5098 let call = UntypedExpr::Call { 5099 location: SrcSpan { start, end }, 5100 fun: Box::new(fun), 5101 arguments, 5102 open_parenthesis, 5103 }; 5104 5105 match hole_location { 5106 // A normal call 5107 None => Ok(call), 5108 5109 // An anon function using the capture syntax run(_, 1, 2) 5110 Some(hole_location) => Ok(UntypedExpr::Fn { 5111 location: call.location(), 5112 end_of_head_byte_index: call.location().end, 5113 kind: FunctionLiteralKind::Capture { 5114 hole: hole_location, 5115 }, 5116 arguments: vec![Arg { 5117 location: hole_location, 5118 annotation: None, 5119 names: ArgNames::Named { 5120 name: CAPTURE_VARIABLE.into(), 5121 location: hole_location, 5122 }, 5123 type_: (), 5124 }], 5125 body: vec1![Statement::Expression(call)], 5126 return_annotation: None, 5127 }), 5128 } 5129} 5130 5131#[derive(Debug, Default)] 5132struct ParsedUnqualifiedImports { 5133 types: Vec<UnqualifiedImport>, 5134 values: Vec<UnqualifiedImport>, 5135} 5136 5137/// Parses an Int value to a bigint. 5138/// 5139pub fn parse_int_value(value: &str) -> Option<BigInt> { 5140 let (radix, value) = if let Some(value) = value.strip_prefix("0x") { 5141 (16, value) 5142 } else if let Some(value) = value.strip_prefix("0o") { 5143 (8, value) 5144 } else if let Some(value) = value.strip_prefix("0b") { 5145 (2, value) 5146 } else { 5147 (10, value) 5148 }; 5149 5150 let value = value.trim_start_matches('_'); 5151 5152 BigInt::parse_bytes(value.as_bytes(), radix) 5153} 5154 5155#[derive(Debug, PartialEq, Clone, Copy)] 5156enum ExpressionUnitContext { 5157 FollowingPipe, 5158 Other, 5159} 5160 5161#[derive(Debug, Clone, Copy)] 5162pub enum PatternPosition { 5163 LetAssignment, 5164 CaseClause, 5165 UsePattern, 5166} 5167 5168impl PatternPosition { 5169 pub fn to_declaration(&self) -> VariableDeclaration { 5170 match self { 5171 PatternPosition::LetAssignment => VariableDeclaration::LetPattern, 5172 PatternPosition::CaseClause => VariableDeclaration::ClausePattern, 5173 PatternPosition::UsePattern => VariableDeclaration::UsePattern, 5174 } 5175 } 5176} 5177 5178/// A thin f64 wrapper that does not permit NaN. 5179/// This allows us to implement `Eq`, which require reflexivity. 5180/// 5181/// Used for gleam float literals, which cannot be NaN. 5182/// 5183/// While there is no syntax for "infinity", float literals might be too big and 5184/// overflow into infinity. This is still allowed so we can parse big literal 5185/// numbers and the error will be raised during the analysis phase. 5186#[derive(Clone, Copy, Debug, PartialEq)] 5187pub struct LiteralFloatValue(f64); 5188 5189impl LiteralFloatValue { 5190 pub const ONE: Self = LiteralFloatValue(1.0); 5191 pub const ZERO: Self = LiteralFloatValue(0.0); 5192 5193 /// Parse from a string, returning `None` if the string 5194 /// is not a valid f64 or the float is `NaN`` 5195 pub fn parse(value: &str) -> Option<Self> { 5196 value 5197 .replace("_", "") 5198 .parse::<f64>() 5199 .ok() 5200 .filter(|float| !float.is_nan()) 5201 .map(LiteralFloatValue) 5202 } 5203 5204 pub fn value(&self) -> f64 { 5205 self.0 5206 } 5207} 5208 5209impl Eq for LiteralFloatValue {} 5210 5211impl Ord for LiteralFloatValue { 5212 fn cmp(&self, other: &Self) -> Ordering { 5213 self.0 5214 .partial_cmp(&other.0) 5215 .expect("Only NaN comparisons should fail") 5216 } 5217} 5218 5219impl PartialOrd for LiteralFloatValue { 5220 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { 5221 Some(self.cmp(other)) 5222 } 5223} 5224 5225impl Hash for LiteralFloatValue { 5226 fn hash<H: Hasher>(&self, state: &mut H) { 5227 self.0.to_bits().hash(state) 5228 } 5229} 5230 5231impl Serialize for LiteralFloatValue { 5232 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 5233 where 5234 S: serde::Serializer, 5235 { 5236 serializer.serialize_f64(self.0) 5237 } 5238} 5239 5240impl<'de> Deserialize<'de> for LiteralFloatValue { 5241 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 5242 where 5243 D: serde::Deserializer<'de>, 5244 { 5245 let value = f64::deserialize(deserializer)?; 5246 if value.is_nan() { 5247 Err(serde::de::Error::custom("NaN is not allowed")) 5248 } else { 5249 Ok(LiteralFloatValue(value)) 5250 } 5251 } 5252}