Struct erg_parser::lex::Lexer
source · pub struct Lexer { /* private fields */ }
Expand description
Lexes a source code and iterates tokens.
This can be used as an iterator or to generate a TokenStream
.
NOTE: Lexer
checks if indent/dedent is used in the correct format,
but cannot check if indent/dedent is used in the grammatically correct position; Parser
does that.
Implementations§
source§impl Lexer
impl Lexer
sourcepub fn from_str(src: String) -> Self
pub fn from_str(src: String) -> Self
Examples found in repository?
lex.rs (line 51)
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
fn exec(&mut self) -> Result<i32, Self::Errs> {
let lexer = Lexer::from_str(self.input().read());
let ts = lexer
.lex()
.map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))?;
println!("{ts}");
Ok(0)
}
fn eval(&mut self, src: String) -> Result<String, LexerRunnerErrors> {
let lexer = Lexer::from_str(src);
if cfg!(feature = "debug") {
let ts = lexer
.lex()
.map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))?;
println!("{ts}");
Ok(ts.to_string())
} else {
Ok(lexer
.lex()
.map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))?
.to_string())
}
}
sourcepub fn lex(self) -> Result<TokenStream, LexErrors>
pub fn lex(self) -> Result<TokenStream, LexErrors>
Examples found in repository?
lex.rs (line 53)
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
fn exec(&mut self) -> Result<i32, Self::Errs> {
let lexer = Lexer::from_str(self.input().read());
let ts = lexer
.lex()
.map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))?;
println!("{ts}");
Ok(0)
}
fn eval(&mut self, src: String) -> Result<String, LexerRunnerErrors> {
let lexer = Lexer::from_str(src);
if cfg!(feature = "debug") {
let ts = lexer
.lex()
.map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))?;
println!("{ts}");
Ok(ts.to_string())
} else {
Ok(lexer
.lex()
.map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))?
.to_string())
}
}
More examples
sourcepub fn is_bidi(c: char) -> bool
pub fn is_bidi(c: char) -> bool
Detect c
is a bidirectional overriding character.
CVE-2021-42574: homoglyph atack countermeasures.
Examples found in repository?
lex.rs (line 297)
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
fn lex_comment(&mut self) -> LexResult<()> {
// debug_power_assert!(self.consume(), ==, Some('#'));
let mut s = "".to_string();
while self.peek_cur_ch().map(|cur| cur != '\n').unwrap_or(false) {
if Self::is_bidi(self.peek_cur_ch().unwrap()) {
let comment = self.emit_token(Illegal, &s);
return Err(LexError::syntax_error(
0,
comment.loc(),
switch_lang!(
"japanese" => "不正なユニコード文字(双方向オーバーライド)がコメント中に使用されています",
"simplified_chinese" => "注释中使用了非法的unicode字符(双向覆盖)",
"traditional_chinese" => "註釋中使用了非法的unicode字符(雙向覆蓋)",
"english" => "invalid unicode character (bi-directional override) in comments",
),
None,
));
}
s.push(self.consume().unwrap());
}
Ok(())
}
fn lex_multi_line_comment(&mut self) -> LexResult<()> {
let mut s = "".to_string();
let mut nest_level = 0;
loop {
match self.peek_cur_ch() {
Some(c) => {
if let Some(next_c) = self.peek_next_ch() {
match (c, next_c) {
('#', '[') => nest_level += 1,
(']', '#') => {
nest_level -= 1;
if nest_level == 0 {
return Ok(());
}
}
_ => {}
}
if c == '\n' {
self.lineno_token_starts += 1;
self.col_token_starts = 0;
}
s.push(self.consume().unwrap());
}
if Self::is_bidi(self.peek_cur_ch().unwrap()) {
let comment = self.emit_token(Illegal, &s);
return Err(LexError::syntax_error(
0,
comment.loc(),
switch_lang!(
"japanese" => "不正なユニコード文字(双方向オーバーライド)がコメント中に使用されています",
"simplified_chinese" => "注释中使用了非法的unicode字符(双向覆盖)",
"traditional_chinese" => "註釋中使用了非法的unicode字符(雙向覆蓋)",
"english" => "invalid unicode character (bi-directional override) in comments",
),
None,
));
}
}
None => {
let comment = self.emit_token(Illegal, &s);
return Err(LexError::syntax_error(
0,
comment.loc(),
switch_lang!(
"japanese" => "複数行コメントが]#で閉じられていません",
"simplified_chinese" => "未用]#号结束的多处评论",
"traditional_chinese" => "多條評論未用]#關閉",
"english" => "Multi-comment is not closed with ]#",
),
None,
));
}
}
}
}
fn lex_space_indent_dedent(&mut self) -> Option<LexResult<Token>> {
let is_line_break_after =
self.cursor > 0 && !self.indent_stack.is_empty() && self.peek_prev_ch() == Some('\n');
let is_space = self.peek_cur_ch() == Some(' ');
let is_linebreak = self.peek_cur_ch() == Some('\n');
let is_empty = is_space || is_linebreak;
let is_toplevel = is_line_break_after && !is_empty;
if is_toplevel {
let dedent = self.emit_token(Dedent, "");
self.indent_stack.pop();
self.col_token_starts = 0;
return Some(Ok(dedent));
} else if is_linebreak {
self.consume();
let token = self.emit_token(Newline, "\n");
self.lineno_token_starts += 1;
self.col_token_starts = 0;
return Some(Ok(token));
}
let mut spaces = "".to_string();
while let Some(' ') = self.peek_cur_ch() {
spaces.push(self.consume().unwrap());
}
// indent in the first line: error
if !spaces.is_empty() && self.prev_token.is(BOF) {
let space = self.emit_token(Illegal, &spaces);
Some(Err(LexError::syntax_error(
0,
space.loc(),
switch_lang!(
"japanese" => "インデントが不正です",
"simplified_chinese" => "无效缩进",
"traditional_chinese" => "無效縮進",
"english" => "invalid indent",
),
None,
)))
} else if self.prev_token.is(Newline) || self.prev_token.is(Dedent) {
self.lex_indent_dedent(spaces)
} else {
self.col_token_starts += spaces.len();
None
}
}
/// The semantic correctness of the use of indent/dedent will be analyzed with `Parser`
fn lex_indent_dedent(&mut self, spaces: String) -> Option<LexResult<Token>> {
// same as the CPython's limit
if spaces.len() > 100 {
let token = self.emit_token(Indent, &spaces);
return Some(Err(LexError::syntax_error(
0,
token.loc(),
switch_lang!(
"japanese" => "インデントが深すぎます",
"simplified_chinese" => "缩进太深",
"traditional_chinese" => "縮進太深",
"english" => "indentation is too deep",
),
Some(
switch_lang!(
"japanese" => "コードが複雑すぎます。処理を分割してください",
"simplified_chinese" => "代码过于复杂,请拆分过程",
"traditional_chinese" => "代碼過於復雜,請拆分過程",
"english" => "The code is too complicated. Please split the process",
)
.into(),
),
)));
}
// ignore indents if the current line is a comment
if let Some('#') = self.peek_cur_ch() {
if let Some('[') = self.peek_next_ch() {
if let Err(e) = self.lex_multi_line_comment() {
return Some(Err(e));
}
}
if let Err(e) = self.lex_comment() {
return Some(Err(e));
}
}
let mut is_valid_dedent = false;
let calc_indent_and_validate = |sum: usize, x: &usize| {
if sum + *x == spaces.len() {
is_valid_dedent = true;
}
sum + *x
};
let sum_indent = self.indent_stack.iter().fold(0, calc_indent_and_validate);
match sum_indent.cmp(&spaces.len()) {
Ordering::Less => {
let indent_len = spaces.len() - sum_indent;
self.col_token_starts += sum_indent;
let indent = self.emit_token(Indent, &" ".repeat(indent_len));
self.indent_stack.push(indent_len);
Some(Ok(indent))
}
Ordering::Greater => {
self.cursor -= spaces.len();
self.indent_stack.pop();
if is_valid_dedent {
let dedent = self.emit_token(Dedent, "");
Some(Ok(dedent))
} else {
let invalid_dedent = self.emit_token(Dedent, "");
let hint = if self.peek_cur_ch() == Some('\n') {
Some("unnecessary spaces after linebreak".into())
} else { None };
Some(Err(LexError::syntax_error(
0,
invalid_dedent.loc(),
switch_lang!(
"japanese" => "インデントが不正です",
"simplified_chinese" => "无效缩进",
"traditional_chinese" => "無效縮進",
"english" => "invalid indent",
),
hint,
)))
}
}
Ordering::Equal /* if indent_sum == space.len() */ => {
self.col_token_starts += spaces.len();
None
}
}
}
fn lex_exponent(&mut self, mantissa: String) -> LexResult<Token> {
let mut num = mantissa;
debug_power_assert!(self.peek_cur_ch(), ==, Some('e'));
num.push(self.consume().unwrap()); // e
if self.peek_cur_ch().is_some() {
num.push(self.consume().unwrap()); // + | -
while let Some(cur) = self.peek_cur_ch() {
if cur.is_ascii_digit() || cur == '_' {
num.push(self.consume().unwrap());
} else {
break;
}
}
Ok(self.emit_token(RatioLit, &num))
} else {
let token = self.emit_token(RatioLit, &num);
Err(LexError::syntax_error(
0,
token.loc(),
switch_lang!(
"japanese" => format!("`{}`は無効な十進数リテラルです", &token.content),
"simplified_chinese" => format!("`{}`是无效的十进制字面量", &token.content),
"traditional_chinese" => format!("`{}`是無效的十進位字面量", &token.content),
"english" => format!("`{}` is invalid decimal literal", &token.content),
),
None,
))
}
}
/// `_` will be removed at compiletime
fn lex_num(&mut self, first_ch: char) -> LexResult<Token> {
let mut num = first_ch.to_string();
while let Some(ch) = self.peek_cur_ch() {
match ch {
// `.` may be a dot operator, don't consume
'.' => {
return self.lex_num_dot(num);
}
n if n.is_ascii_digit() || n == '_' => {
num.push(self.consume().unwrap());
}
c if Self::is_valid_continue_symbol_ch(c) => {
// exponent (e.g. 10e+3)
if c == 'e'
&& (self.peek_next_ch() == Some('+') || self.peek_next_ch() == Some('-'))
{
return self.lex_exponent(num);
} else {
// IntLit * Symbol(e.g. 3x + 1)
let token = self.emit_token(Illegal, &(num + &c.to_string()));
return Err(LexError::feature_error(
line!() as usize,
token.loc(),
"*-less multiply",
));
}
}
_ => {
break;
}
}
}
let kind = if num.starts_with('-') && !Self::is_zero(&num) {
IntLit
} else {
NatLit
};
Ok(self.emit_token(kind, &num))
}
/// number '.' ~~
/// Possibility: RatioLit or Int/NatLit call
fn lex_num_dot(&mut self, mut num: String) -> LexResult<Token> {
match self.peek_next_ch() {
// RatioLit
Some(n) if n.is_ascii_digit() => {
num.push(self.consume().unwrap());
self.lex_ratio(num)
}
// method call of IntLit
// or range operator (e.g. 1..)
Some(c) if Self::is_valid_continue_symbol_ch(c) || c == '.' => {
let kind = if num.starts_with('-') && !Self::is_zero(&num) {
IntLit
} else {
NatLit
};
Ok(self.emit_token(kind, &num))
}
Some('_') => {
self.consume();
let token = self.emit_token(Illegal, &(num + "_"));
Err(LexError::simple_syntax_error(0, token.loc()))
}
// RatioLit without zero (e.g. 3.)
_ => {
num.push(self.consume().unwrap());
self.lex_ratio(num)
}
}
}
/// int_part_and_point must be like `12.`
fn lex_ratio(&mut self, intpart_and_point: String) -> LexResult<Token> {
let mut num = intpart_and_point;
while let Some(cur) = self.peek_cur_ch() {
if cur.is_ascii_digit() || cur == '_' {
num.push(self.consume().unwrap());
} else if cur == 'e' {
return self.lex_exponent(num);
} else {
break;
}
}
Ok(self.emit_token(RatioLit, &num))
}
fn lex_symbol(&mut self, first_ch: char) -> LexResult<Token> {
let mut cont = first_ch.to_string();
while let Some(c) = self.peek_cur_ch() {
if Self::is_valid_continue_symbol_ch(c) {
cont.push(self.consume().unwrap());
} else {
break;
}
}
if let Some('!') = self.peek_cur_ch() {
cont.push(self.consume().unwrap());
}
if cont.is_empty() {
let token = self.emit_token(Illegal, &self.peek_cur_ch().unwrap().to_string());
return Err(LexError::compiler_bug(
0,
token.loc(),
fn_name_full!(),
line!(),
));
}
// dot: scalar product, cross: vector product
// An alphabetical operator can also declare as a function, so checking is necessary
// e.g. and(true, true, true) = true
let kind = match &cont[..] {
"and" => AndOp,
"or" => OrOp,
"in" => InOp,
"notin" => NotInOp,
"is" => IsOp,
"isnot" => IsNotOp,
"dot" => DotOp,
"cross" => CrossOp,
"ref" => RefOp,
"ref!" => RefMutOp,
// これらはリテラルというより定数だが便宜的にリテラルということにしておく
"True" | "False" => BoolLit,
"None" => NoneLit,
"NotImplemented" => NoImplLit,
"Ellipsis" => EllipsisLit,
"Inf" => InfLit,
"_" => UBar,
_ => Symbol,
};
Ok(self.emit_token(kind, &cont))
}
fn str_line_break_error(token: Token, line: usize) -> LexError {
LexError::syntax_error(
line,
token.loc(),
switch_lang!(
"japanese" => "文字列内で改行をすることはできません",
"simplified_chinese" => "在一个字符串中不允许有换行符",
"traditional_chinese" => "在一個字符串中不允許有換行符",
"english" => "Line breaks are not allowed within a string",
),
Some(
switch_lang!(
"japanese" => "\"\"内で改行を使いたい場合は'\\n'を利用してください",
"simplified_chinese" => "如果你想在\"\"中使用换行符,请使用'\\n'",
"traditional_chinese" => "如果你想在\"\"中使用換行符,請使用'\\n'",
"english" => "If you want to use line breaks within \"\", use '\\n'",
)
.into(),
),
)
}
fn invalid_escape_error(ch: char, token: Token) -> LexError {
LexError::syntax_error(
0,
token.loc(),
switch_lang!(
"japanese" => format!("不正なエスケープシーケンスです: \\{}", ch),
"simplified_chinese" => format!("不合法的转义序列: \\{}", ch),
"traditional_chinese" => format!("不合法的轉義序列: \\{}", ch),
"english" => format!("illegal escape sequence: \\{}", ch),
),
None,
)
}
fn unclosed_string_error(token: Token, by: &str, line: usize) -> LexError {
let by = if by.is_empty() {
"".to_string()
} else {
switch_lang!(
"japanese" => format!("{by}によって"),
"simplified_chinese" => format!("{by}关"),
"traditional_chinese" => format!("{by}关"),
"english" => format!("by {by}"),
)
};
LexError::syntax_error(
line,
token.loc(),
switch_lang!(
"japanese" => format!("文字列が{by}閉じられていません"),
"simplified_chinese" => format!("字符串没有被{by}闭"),
"traditional_chinese" => format!("字符串没有被{by}闭"),
"english" => format!("the string is not closed {by}"),
),
None,
)
}
fn unclosed_interpol_error(token: Token) -> LexError {
LexError::syntax_error(
0,
token.loc(),
switch_lang!(
"japanese" => "文字列内の補間が閉じられていません",
"simplified_chinese" => "字符串内的插值没有被闭",
"traditional_chinese" => "字符串內的插值沒有被閉",
"english" => "the interpolation in the string is not closed",
),
None,
)
}
fn invalid_unicode_character(&mut self, s: &str) -> LexError {
let token = self.emit_token(Illegal, s);
LexError::syntax_error(
0,
token.loc(),
switch_lang!(
"japanese" => "不正なユニコード文字(双方向オーバーライド)が文字列中に使用されています",
"simplified_chinese" => "注释中使用了非法的unicode字符(双向覆盖)",
"traditional_chinese" => "註釋中使用了非法的unicode字符(雙向覆蓋)",
"english" => "invalid unicode character (bi-directional override) in string literal",
),
None,
)
}
fn lex_single_str(&mut self) -> LexResult<Token> {
let mut s = "\"".to_string();
while let Some(c) = self.peek_cur_ch() {
match c {
'\n' => match self.interpol_stack.last().unwrap() {
Interpolation::SingleLine if self.interpol_stack.len() == 1 => {
let token = self.emit_token(Illegal, &s);
return Err(Self::str_line_break_error(token, line!() as usize));
}
_ => {
let token = self.emit_token(Illegal, &s);
return Err(Self::unclosed_interpol_error(token));
}
},
'"' => {
s.push(self.consume().unwrap());
let token = self.emit_token(StrLit, &s);
return Ok(token);
}
_ => {
let c = self.consume().unwrap();
if c == '\\' {
let next_c = self.consume().unwrap();
match next_c {
'{' => {
s.push_str("\\{");
self.interpol_stack.push(Interpolation::SingleLine);
let token = self.emit_token(StrInterpLeft, &s);
return Ok(token);
}
'0' => s.push('\0'),
'r' => s.push('\r'),
'n' => s.push('\n'),
'\'' => s.push('\''),
'"' => s.push('"'),
't' => s.push_str(" "), // tab is invalid, so changed into 4 whitespace
'\\' => s.push('\\'),
_ => {
let token = self.emit_token(Illegal, &format!("\\{next_c}"));
return Err(Self::invalid_escape_error(next_c, token));
}
}
} else {
s.push(c);
if Self::is_bidi(c) {
return Err(self.invalid_unicode_character(&s));
}
}
}
}
}
let token = self.emit_token(Illegal, &s);
Err(Self::unclosed_string_error(token, "\"", line!() as usize))
}
const QUOTES: &str = "\"\"\"";
fn lex_multi_line_str(&mut self) -> LexResult<Token> {
let mut s = Self::QUOTES.to_string();
while let Some(c) = self.peek_cur_ch() {
if c == '"' {
let c = self.consume().unwrap();
let next_c = self.peek_cur_ch();
let aft_next_c = self.peek_next_ch();
if next_c.is_none() {
let token = self.emit_token(Illegal, &s);
return Err(Self::unclosed_string_error(
token,
Self::QUOTES,
line!() as usize,
));
}
if aft_next_c.is_none() {
s.push(self.consume().unwrap());
let token = self.emit_token(Illegal, &s);
return Err(Self::unclosed_string_error(
token,
Self::QUOTES,
line!() as usize,
));
}
if next_c.unwrap() == '"' && aft_next_c.unwrap() == '"' {
self.consume().unwrap();
self.consume().unwrap();
s.push_str(Self::QUOTES);
let token = self.emit_token(StrLit, &s);
return Ok(token);
}
// else unclosed_string_error
s.push(c);
} else {
let c = self.consume().unwrap();
match c {
'\\' => {
let next_c = self.consume().unwrap();
match next_c {
'{' => {
s.push_str("\\{");
self.interpol_stack.push(Interpolation::MultiLine);
let token = self.emit_token(StrInterpLeft, &s);
return Ok(token);
}
'0' => s.push('\0'),
'r' => s.push('\r'),
'\'' => s.push('\''),
'\"' => s.push('\"'),
't' => s.push_str(" "), // tab is invalid, so changed into 4 whitespace
'\\' => s.push('\\'),
'n' => s.push('\n'),
'\n' => {
self.lineno_token_starts += 1;
self.col_token_starts = 0;
continue;
}
_ => {
let token = self.emit_token(Illegal, &format!("\\{next_c}"));
return Err(Self::invalid_escape_error(next_c, token));
}
}
}
'\n' => {
self.lineno_token_starts += 1;
self.col_token_starts = 0;
s.push('\n');
}
_ => {
s.push(c);
if Self::is_bidi(c) {
return Err(self.invalid_unicode_character(&s));
}
}
}
}
}
let token = self.emit_token(Illegal, &s);
if self.interpol_stack.len() == 1 {
Err(Self::unclosed_string_error(
token,
Self::QUOTES,
line!() as usize,
))
} else {
Err(Self::unclosed_interpol_error(token))
}
}
/// e.g. `}aaa"`, `}aaa{`
fn lex_interpolation_mid(&mut self) -> LexResult<Token> {
let mut s = "}".to_string();
while let Some(c) = self.peek_cur_ch() {
match c {
'\n' => match self.interpol_stack.last().unwrap() {
Interpolation::MultiLine => {
self.lineno_token_starts += 1;
self.col_token_starts = 0;
self.consume().unwrap();
s.push('\n');
}
Interpolation::SingleLine => {
if self.peek_next_ch().is_some() {
let token = self.emit_token(Illegal, &s);
return Err(Self::str_line_break_error(token, line!() as usize));
} else {
let token = self.emit_token(Illegal, &s);
return Err(Self::unclosed_string_error(token, "", line!() as usize));
}
}
Interpolation::Not => {
let token = self.emit_token(Illegal, &s);
return Err(Self::unclosed_interpol_error(token));
}
},
'"' => {
s.push(self.consume().unwrap());
match self.interpol_stack.last().unwrap() {
Interpolation::MultiLine => {
let next_c = self.peek_cur_ch();
let aft_next_c = self.peek_next_ch();
if next_c.is_none() {
self.interpol_stack.pop();
let token = self.emit_token(Illegal, &s);
return Err(Self::unclosed_string_error(
token,
Self::QUOTES,
line!() as usize,
));
}
if aft_next_c.is_none() {
self.interpol_stack.pop();
s.push(self.consume().unwrap());
let token = self.emit_token(Illegal, &s);
return Err(Self::unclosed_string_error(
token,
Self::QUOTES,
line!() as usize,
));
}
if next_c.unwrap() == '"' && aft_next_c.unwrap() == '"' {
self.interpol_stack.pop();
self.consume().unwrap();
self.consume().unwrap();
s.push_str(Self::QUOTES);
let token = self.emit_token(StrInterpRight, &s);
return Ok(token);
}
// else unclosed_string_error
}
Interpolation::SingleLine => {
self.interpol_stack.pop();
let token = self.emit_token(StrInterpRight, &s);
return Ok(token);
}
Interpolation::Not => {}
}
}
_ => {
let c = self.consume().unwrap();
if c == '\\' {
let next_c = self.consume().unwrap();
match next_c {
'{' => {
s.push_str("\\{");
let token = self.emit_token(StrInterpMid, &s);
return Ok(token);
}
'0' => s.push('\0'),
'r' => s.push('\r'),
'n' => s.push('\n'),
'\'' => s.push('\''),
'"' => s.push('"'),
't' => s.push_str(" "), // tab is invalid, so changed into 4 whitespace
'\\' => s.push('\\'),
_ => {
let token = self.emit_token(Illegal, &format!("\\{next_c}"));
return Err(Self::invalid_escape_error(next_c, token));
}
}
} else {
s.push(c);
if Self::is_bidi(c) {
return Err(self.invalid_unicode_character(&s));
}
}
}
}
}
let token = self.emit_token(Illegal, &s);
Err(Self::unclosed_string_error(token, "", line!() as usize))
}
fn lex_raw_ident(&mut self) -> LexResult<Token> {
let mut s = "\'".to_string();
while let Some(c) = self.peek_cur_ch() {
match c {
'\n' => {
let token = self.emit_token(Illegal, &s);
return Err(LexError::simple_syntax_error(line!() as usize, token.loc()));
}
'\'' => {
s.push(self.consume().unwrap());
if self.peek_cur_ch() == Some('!') {
s.push(self.consume().unwrap());
}
let token = self.emit_token(Symbol, &s);
return Ok(token);
}
_ => {
let c = self.consume().unwrap();
s.push(c);
if Self::is_bidi(c) {
return Err(self.invalid_unicode_character(&s));
}
}
}
}
let token = self.emit_token(Illegal, &s);
Err(LexError::syntax_error(
0,
token.loc(),
switch_lang!(
"japanese" => "raw識別子が'によって閉じられていません",
"simplified_chinese" => "raw标识符没有被'关闭",
"traditional_chinese" => "raw標誌符沒有被'關閉",
"english" => "raw identifier is not closed by '",
),
None,
))
}
Trait Implementations§
source§impl Iterator for Lexer
impl Iterator for Lexer
source§fn next(&mut self) -> Option<Self::Item>
fn next(&mut self) -> Option<Self::Item>
Advances the iterator and returns the next value. Read more
source§fn next_chunk<const N: usize>(
&mut self
) -> Result<[Self::Item; N], IntoIter<Self::Item, N>>where
Self: Sized,
fn next_chunk<const N: usize>(
&mut self
) -> Result<[Self::Item; N], IntoIter<Self::Item, N>>where
Self: Sized,
🔬This is a nightly-only experimental API. (
iter_next_chunk
)Advances the iterator and returns an array containing the next
N
values. Read more1.0.0 · source§fn size_hint(&self) -> (usize, Option<usize>)
fn size_hint(&self) -> (usize, Option<usize>)
Returns the bounds on the remaining length of the iterator. Read more
1.0.0 · source§fn count(self) -> usizewhere
Self: Sized,
fn count(self) -> usizewhere
Self: Sized,
Consumes the iterator, counting the number of iterations and returning it. Read more
1.0.0 · source§fn last(self) -> Option<Self::Item>where
Self: Sized,
fn last(self) -> Option<Self::Item>where
Self: Sized,
Consumes the iterator, returning the last element. Read more
source§fn advance_by(&mut self, n: usize) -> Result<(), usize>
fn advance_by(&mut self, n: usize) -> Result<(), usize>
🔬This is a nightly-only experimental API. (
iter_advance_by
)Advances the iterator by
n
elements. Read more1.0.0 · source§fn nth(&mut self, n: usize) -> Option<Self::Item>
fn nth(&mut self, n: usize) -> Option<Self::Item>
Returns the
n
th element of the iterator. Read more1.28.0 · source§fn step_by(self, step: usize) -> StepBy<Self>where
Self: Sized,
fn step_by(self, step: usize) -> StepBy<Self>where
Self: Sized,
Creates an iterator starting at the same point, but stepping by
the given amount at each iteration. Read more
1.0.0 · source§fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter>where
Self: Sized,
U: IntoIterator<Item = Self::Item>,
fn chain<U>(self, other: U) -> Chain<Self, <U as IntoIterator>::IntoIter>where
Self: Sized,
U: IntoIterator<Item = Self::Item>,
Takes two iterators and creates a new iterator over both in sequence. Read more
1.0.0 · source§fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter>where
Self: Sized,
U: IntoIterator,
fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter>where
Self: Sized,
U: IntoIterator,
‘Zips up’ two iterators into a single iterator of pairs. Read more
source§fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>where
Self: Sized,
G: FnMut() -> Self::Item,
fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>where
Self: Sized,
G: FnMut() -> Self::Item,
🔬This is a nightly-only experimental API. (
iter_intersperse
)Creates a new iterator which places an item generated by
separator
between adjacent items of the original iterator. Read more1.0.0 · source§fn map<B, F>(self, f: F) -> Map<Self, F>where
Self: Sized,
F: FnMut(Self::Item) -> B,
fn map<B, F>(self, f: F) -> Map<Self, F>where
Self: Sized,
F: FnMut(Self::Item) -> B,
Takes a closure and creates an iterator which calls that closure on each
element. Read more
1.21.0 · source§fn for_each<F>(self, f: F)where
Self: Sized,
F: FnMut(Self::Item),
fn for_each<F>(self, f: F)where
Self: Sized,
F: FnMut(Self::Item),
Calls a closure on each element of an iterator. Read more
1.0.0 · source§fn filter<P>(self, predicate: P) -> Filter<Self, P>where
Self: Sized,
P: FnMut(&Self::Item) -> bool,
fn filter<P>(self, predicate: P) -> Filter<Self, P>where
Self: Sized,
P: FnMut(&Self::Item) -> bool,
Creates an iterator which uses a closure to determine if an element
should be yielded. Read more
1.0.0 · source§fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>where
Self: Sized,
F: FnMut(Self::Item) -> Option<B>,
fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>where
Self: Sized,
F: FnMut(Self::Item) -> Option<B>,
Creates an iterator that both filters and maps. Read more
1.0.0 · source§fn enumerate(self) -> Enumerate<Self>where
Self: Sized,
fn enumerate(self) -> Enumerate<Self>where
Self: Sized,
Creates an iterator which gives the current iteration count as well as
the next value. Read more
1.0.0 · source§fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>where
Self: Sized,
P: FnMut(&Self::Item) -> bool,
fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>where
Self: Sized,
P: FnMut(&Self::Item) -> bool,
1.0.0 · source§fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>where
Self: Sized,
P: FnMut(&Self::Item) -> bool,
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>where
Self: Sized,
P: FnMut(&Self::Item) -> bool,
Creates an iterator that yields elements based on a predicate. Read more
1.57.0 · source§fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>where
Self: Sized,
P: FnMut(Self::Item) -> Option<B>,
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>where
Self: Sized,
P: FnMut(Self::Item) -> Option<B>,
Creates an iterator that both yields elements based on a predicate and maps. Read more
1.0.0 · source§fn skip(self, n: usize) -> Skip<Self>where
Self: Sized,
fn skip(self, n: usize) -> Skip<Self>where
Self: Sized,
Creates an iterator that skips the first
n
elements. Read more1.0.0 · source§fn take(self, n: usize) -> Take<Self>where
Self: Sized,
fn take(self, n: usize) -> Take<Self>where
Self: Sized,
Creates an iterator that yields the first
n
elements, or fewer
if the underlying iterator ends sooner. Read more1.0.0 · source§fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>where
Self: Sized,
F: FnMut(&mut St, Self::Item) -> Option<B>,
fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>where
Self: Sized,
F: FnMut(&mut St, Self::Item) -> Option<B>,
1.0.0 · source§fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>where
Self: Sized,
U: IntoIterator,
F: FnMut(Self::Item) -> U,
fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>where
Self: Sized,
U: IntoIterator,
F: FnMut(Self::Item) -> U,
Creates an iterator that works like map, but flattens nested structure. Read more
1.0.0 · source§fn inspect<F>(self, f: F) -> Inspect<Self, F>where
Self: Sized,
F: FnMut(&Self::Item),
fn inspect<F>(self, f: F) -> Inspect<Self, F>where
Self: Sized,
F: FnMut(&Self::Item),
Does something with each element of an iterator, passing the value on. Read more
1.0.0 · source§fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
Borrows an iterator, rather than consuming it. Read more
1.0.0 · source§fn collect<B>(self) -> Bwhere
B: FromIterator<Self::Item>,
Self: Sized,
fn collect<B>(self) -> Bwhere
B: FromIterator<Self::Item>,
Self: Sized,
Transforms an iterator into a collection. Read more
source§fn collect_into<E>(self, collection: &mut E) -> &mut Ewhere
E: Extend<Self::Item>,
Self: Sized,
fn collect_into<E>(self, collection: &mut E) -> &mut Ewhere
E: Extend<Self::Item>,
Self: Sized,
🔬This is a nightly-only experimental API. (
iter_collect_into
)Collects all the items from an iterator into a collection. Read more
1.0.0 · source§fn partition<B, F>(self, f: F) -> (B, B)where
Self: Sized,
B: Default + Extend<Self::Item>,
F: FnMut(&Self::Item) -> bool,
fn partition<B, F>(self, f: F) -> (B, B)where
Self: Sized,
B: Default + Extend<Self::Item>,
F: FnMut(&Self::Item) -> bool,
Consumes an iterator, creating two collections from it. Read more
source§fn is_partitioned<P>(self, predicate: P) -> boolwhere
Self: Sized,
P: FnMut(Self::Item) -> bool,
fn is_partitioned<P>(self, predicate: P) -> boolwhere
Self: Sized,
P: FnMut(Self::Item) -> bool,
🔬This is a nightly-only experimental API. (
iter_is_partitioned
)Checks if the elements of this iterator are partitioned according to the given predicate,
such that all those that return
true
precede all those that return false
. Read more1.27.0 · source§fn try_fold<B, F, R>(&mut self, init: B, f: F) -> Rwhere
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> Rwhere
Self: Sized,
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
An iterator method that applies a function as long as it returns
successfully, producing a single, final value. Read more
1.27.0 · source§fn try_for_each<F, R>(&mut self, f: F) -> Rwhere
Self: Sized,
F: FnMut(Self::Item) -> R,
R: Try<Output = ()>,
fn try_for_each<F, R>(&mut self, f: F) -> Rwhere
Self: Sized,
F: FnMut(Self::Item) -> R,
R: Try<Output = ()>,
An iterator method that applies a fallible function to each item in the
iterator, stopping at the first error and returning that error. Read more
1.0.0 · source§fn fold<B, F>(self, init: B, f: F) -> Bwhere
Self: Sized,
F: FnMut(B, Self::Item) -> B,
fn fold<B, F>(self, init: B, f: F) -> Bwhere
Self: Sized,
F: FnMut(B, Self::Item) -> B,
Folds every element into an accumulator by applying an operation,
returning the final result. Read more
1.51.0 · source§fn reduce<F>(self, f: F) -> Option<Self::Item>where
Self: Sized,
F: FnMut(Self::Item, Self::Item) -> Self::Item,
fn reduce<F>(self, f: F) -> Option<Self::Item>where
Self: Sized,
F: FnMut(Self::Item, Self::Item) -> Self::Item,
Reduces the elements to a single one, by repeatedly applying a reducing
operation. Read more
source§fn try_reduce<F, R>(
&mut self,
f: F
) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryTypewhere
Self: Sized,
F: FnMut(Self::Item, Self::Item) -> R,
R: Try<Output = Self::Item>,
<R as Try>::Residual: Residual<Option<Self::Item>>,
fn try_reduce<F, R>(
&mut self,
f: F
) -> <<R as Try>::Residual as Residual<Option<<R as Try>::Output>>>::TryTypewhere
Self: Sized,
F: FnMut(Self::Item, Self::Item) -> R,
R: Try<Output = Self::Item>,
<R as Try>::Residual: Residual<Option<Self::Item>>,
🔬This is a nightly-only experimental API. (
iterator_try_reduce
)Reduces the elements to a single one by repeatedly applying a reducing operation. If the
closure returns a failure, the failure is propagated back to the caller immediately. Read more
1.0.0 · source§fn all<F>(&mut self, f: F) -> boolwhere
Self: Sized,
F: FnMut(Self::Item) -> bool,
fn all<F>(&mut self, f: F) -> boolwhere
Self: Sized,
F: FnMut(Self::Item) -> bool,
Tests if every element of the iterator matches a predicate. Read more
1.0.0 · source§fn any<F>(&mut self, f: F) -> boolwhere
Self: Sized,
F: FnMut(Self::Item) -> bool,
fn any<F>(&mut self, f: F) -> boolwhere
Self: Sized,
F: FnMut(Self::Item) -> bool,
Tests if any element of the iterator matches a predicate. Read more
1.0.0 · source§fn find<P>(&mut self, predicate: P) -> Option<Self::Item>where
Self: Sized,
P: FnMut(&Self::Item) -> bool,
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>where
Self: Sized,
P: FnMut(&Self::Item) -> bool,
Searches for an element of an iterator that satisfies a predicate. Read more
1.30.0 · source§fn find_map<B, F>(&mut self, f: F) -> Option<B>where
Self: Sized,
F: FnMut(Self::Item) -> Option<B>,
fn find_map<B, F>(&mut self, f: F) -> Option<B>where
Self: Sized,
F: FnMut(Self::Item) -> Option<B>,
Applies function to the elements of iterator and returns
the first non-none result. Read more
source§fn try_find<F, R>(
&mut self,
f: F
) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryTypewhere
Self: Sized,
F: FnMut(&Self::Item) -> R,
R: Try<Output = bool>,
<R as Try>::Residual: Residual<Option<Self::Item>>,
fn try_find<F, R>(
&mut self,
f: F
) -> <<R as Try>::Residual as Residual<Option<Self::Item>>>::TryTypewhere
Self: Sized,
F: FnMut(&Self::Item) -> R,
R: Try<Output = bool>,
<R as Try>::Residual: Residual<Option<Self::Item>>,
🔬This is a nightly-only experimental API. (
try_find
)Applies function to the elements of iterator and returns
the first true result or the first error. Read more
1.0.0 · source§fn position<P>(&mut self, predicate: P) -> Option<usize>where
Self: Sized,
P: FnMut(Self::Item) -> bool,
fn position<P>(&mut self, predicate: P) -> Option<usize>where
Self: Sized,
P: FnMut(Self::Item) -> bool,
Searches for an element in an iterator, returning its index. Read more
1.6.0 · source§fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>where
B: Ord,
Self: Sized,
F: FnMut(&Self::Item) -> B,
fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>where
B: Ord,
Self: Sized,
F: FnMut(&Self::Item) -> B,
Returns the element that gives the maximum value from the
specified function. Read more
1.15.0 · source§fn max_by<F>(self, compare: F) -> Option<Self::Item>where
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
fn max_by<F>(self, compare: F) -> Option<Self::Item>where
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
Returns the element that gives the maximum value with respect to the
specified comparison function. Read more
1.6.0 · source§fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>where
B: Ord,
Self: Sized,
F: FnMut(&Self::Item) -> B,
fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>where
B: Ord,
Self: Sized,
F: FnMut(&Self::Item) -> B,
Returns the element that gives the minimum value from the
specified function. Read more
1.15.0 · source§fn min_by<F>(self, compare: F) -> Option<Self::Item>where
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
fn min_by<F>(self, compare: F) -> Option<Self::Item>where
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
Returns the element that gives the minimum value with respect to the
specified comparison function. Read more
1.0.0 · source§fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)where
FromA: Default + Extend<A>,
FromB: Default + Extend<B>,
Self: Sized + Iterator<Item = (A, B)>,
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)where
FromA: Default + Extend<A>,
FromB: Default + Extend<B>,
Self: Sized + Iterator<Item = (A, B)>,
Converts an iterator of pairs into a pair of containers. Read more
1.36.0 · source§fn copied<'a, T>(self) -> Copied<Self>where
T: 'a + Copy,
Self: Sized + Iterator<Item = &'a T>,
fn copied<'a, T>(self) -> Copied<Self>where
T: 'a + Copy,
Self: Sized + Iterator<Item = &'a T>,
Creates an iterator which copies all of its elements. Read more
1.0.0 · source§fn cloned<'a, T>(self) -> Cloned<Self>where
T: 'a + Clone,
Self: Sized + Iterator<Item = &'a T>,
fn cloned<'a, T>(self) -> Cloned<Self>where
T: 'a + Clone,
Self: Sized + Iterator<Item = &'a T>,
source§fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>where
Self: Sized,
fn array_chunks<const N: usize>(self) -> ArrayChunks<Self, N>where
Self: Sized,
🔬This is a nightly-only experimental API. (
iter_array_chunks
)Returns an iterator over
N
elements of the iterator at a time. Read more1.11.0 · source§fn sum<S>(self) -> Swhere
Self: Sized,
S: Sum<Self::Item>,
fn sum<S>(self) -> Swhere
Self: Sized,
S: Sum<Self::Item>,
Sums the elements of an iterator. Read more
1.11.0 · source§fn product<P>(self) -> Pwhere
Self: Sized,
P: Product<Self::Item>,
fn product<P>(self) -> Pwhere
Self: Sized,
P: Product<Self::Item>,
Iterates over the entire iterator, multiplying all the elements Read more
source§fn cmp_by<I, F>(self, other: I, cmp: F) -> Orderingwhere
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Ordering,
fn cmp_by<I, F>(self, other: I, cmp: F) -> Orderingwhere
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Ordering,
🔬This is a nightly-only experimental API. (
iter_order_by
)Lexicographically compares the elements of this
Iterator
with those
of another with respect to the specified comparison function. Read more1.5.0 · source§fn partial_cmp<I>(self, other: I) -> Option<Ordering>where
I: IntoIterator,
Self::Item: PartialOrd<<I as IntoIterator>::Item>,
Self: Sized,
fn partial_cmp<I>(self, other: I) -> Option<Ordering>where
I: IntoIterator,
Self::Item: PartialOrd<<I as IntoIterator>::Item>,
Self: Sized,
source§fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>,
fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>,
🔬This is a nightly-only experimental API. (
iter_order_by
)Lexicographically compares the elements of this
Iterator
with those
of another with respect to the specified comparison function. Read more1.5.0 · source§fn eq<I>(self, other: I) -> boolwhere
I: IntoIterator,
Self::Item: PartialEq<<I as IntoIterator>::Item>,
Self: Sized,
fn eq<I>(self, other: I) -> boolwhere
I: IntoIterator,
Self::Item: PartialEq<<I as IntoIterator>::Item>,
Self: Sized,
source§fn eq_by<I, F>(self, other: I, eq: F) -> boolwhere
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> bool,
fn eq_by<I, F>(self, other: I, eq: F) -> boolwhere
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, <I as IntoIterator>::Item) -> bool,
🔬This is a nightly-only experimental API. (
iter_order_by
)1.5.0 · source§fn ne<I>(self, other: I) -> boolwhere
I: IntoIterator,
Self::Item: PartialEq<<I as IntoIterator>::Item>,
Self: Sized,
fn ne<I>(self, other: I) -> boolwhere
I: IntoIterator,
Self::Item: PartialEq<<I as IntoIterator>::Item>,
Self: Sized,
1.5.0 · source§fn lt<I>(self, other: I) -> boolwhere
I: IntoIterator,
Self::Item: PartialOrd<<I as IntoIterator>::Item>,
Self: Sized,
fn lt<I>(self, other: I) -> boolwhere
I: IntoIterator,
Self::Item: PartialOrd<<I as IntoIterator>::Item>,
Self: Sized,
Determines if the elements of this
Iterator
are lexicographically
less than those of another. Read more1.5.0 · source§fn le<I>(self, other: I) -> boolwhere
I: IntoIterator,
Self::Item: PartialOrd<<I as IntoIterator>::Item>,
Self: Sized,
fn le<I>(self, other: I) -> boolwhere
I: IntoIterator,
Self::Item: PartialOrd<<I as IntoIterator>::Item>,
Self: Sized,
Determines if the elements of this
Iterator
are lexicographically
less or equal to those of another. Read more1.5.0 · source§fn gt<I>(self, other: I) -> boolwhere
I: IntoIterator,
Self::Item: PartialOrd<<I as IntoIterator>::Item>,
Self: Sized,
fn gt<I>(self, other: I) -> boolwhere
I: IntoIterator,
Self::Item: PartialOrd<<I as IntoIterator>::Item>,
Self: Sized,
Determines if the elements of this
Iterator
are lexicographically
greater than those of another. Read more1.5.0 · source§fn ge<I>(self, other: I) -> boolwhere
I: IntoIterator,
Self::Item: PartialOrd<<I as IntoIterator>::Item>,
Self: Sized,
fn ge<I>(self, other: I) -> boolwhere
I: IntoIterator,
Self::Item: PartialOrd<<I as IntoIterator>::Item>,
Self: Sized,
Determines if the elements of this
Iterator
are lexicographically
greater than or equal to those of another. Read moresource§fn is_sorted_by<F>(self, compare: F) -> boolwhere
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>,
fn is_sorted_by<F>(self, compare: F) -> boolwhere
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>,
🔬This is a nightly-only experimental API. (
is_sorted
)Checks if the elements of this iterator are sorted using the given comparator function. Read more
source§fn is_sorted_by_key<F, K>(self, f: F) -> boolwhere
Self: Sized,
F: FnMut(Self::Item) -> K,
K: PartialOrd<K>,
fn is_sorted_by_key<F, K>(self, f: F) -> boolwhere
Self: Sized,
F: FnMut(Self::Item) -> K,
K: PartialOrd<K>,
🔬This is a nightly-only experimental API. (
is_sorted
)Checks if the elements of this iterator are sorted using the given key extraction
function. Read more