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

Configure Feed

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

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