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