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