17ac06127Sopenharmony_ciuse crate::fallback::{ 27ac06127Sopenharmony_ci self, is_ident_continue, is_ident_start, Group, LexError, Literal, Span, TokenStream, 37ac06127Sopenharmony_ci TokenStreamBuilder, 47ac06127Sopenharmony_ci}; 57ac06127Sopenharmony_ciuse crate::{Delimiter, Punct, Spacing, TokenTree}; 67ac06127Sopenharmony_ciuse core::char; 77ac06127Sopenharmony_ciuse core::str::{Bytes, CharIndices, Chars}; 87ac06127Sopenharmony_ci 97ac06127Sopenharmony_ci#[derive(Copy, Clone, Eq, PartialEq)] 107ac06127Sopenharmony_cipub(crate) struct Cursor<'a> { 117ac06127Sopenharmony_ci pub rest: &'a str, 127ac06127Sopenharmony_ci #[cfg(span_locations)] 137ac06127Sopenharmony_ci pub off: u32, 147ac06127Sopenharmony_ci} 157ac06127Sopenharmony_ci 167ac06127Sopenharmony_ciimpl<'a> Cursor<'a> { 177ac06127Sopenharmony_ci pub fn advance(&self, bytes: usize) -> Cursor<'a> { 187ac06127Sopenharmony_ci let (_front, rest) = self.rest.split_at(bytes); 197ac06127Sopenharmony_ci Cursor { 207ac06127Sopenharmony_ci rest, 217ac06127Sopenharmony_ci #[cfg(span_locations)] 227ac06127Sopenharmony_ci off: self.off + _front.chars().count() as u32, 237ac06127Sopenharmony_ci } 247ac06127Sopenharmony_ci } 257ac06127Sopenharmony_ci 267ac06127Sopenharmony_ci pub fn starts_with(&self, s: &str) -> bool { 277ac06127Sopenharmony_ci self.rest.starts_with(s) 287ac06127Sopenharmony_ci } 297ac06127Sopenharmony_ci 307ac06127Sopenharmony_ci pub fn starts_with_char(&self, ch: char) -> bool { 317ac06127Sopenharmony_ci self.rest.starts_with(ch) 327ac06127Sopenharmony_ci } 337ac06127Sopenharmony_ci 347ac06127Sopenharmony_ci pub fn starts_with_fn<Pattern>(&self, f: Pattern) -> bool 357ac06127Sopenharmony_ci where 367ac06127Sopenharmony_ci Pattern: FnMut(char) -> bool, 377ac06127Sopenharmony_ci { 387ac06127Sopenharmony_ci self.rest.starts_with(f) 397ac06127Sopenharmony_ci } 407ac06127Sopenharmony_ci 417ac06127Sopenharmony_ci pub fn is_empty(&self) -> bool { 427ac06127Sopenharmony_ci self.rest.is_empty() 437ac06127Sopenharmony_ci } 447ac06127Sopenharmony_ci 457ac06127Sopenharmony_ci fn len(&self) -> usize { 467ac06127Sopenharmony_ci self.rest.len() 477ac06127Sopenharmony_ci } 487ac06127Sopenharmony_ci 497ac06127Sopenharmony_ci fn as_bytes(&self) -> &'a [u8] { 507ac06127Sopenharmony_ci self.rest.as_bytes() 517ac06127Sopenharmony_ci } 527ac06127Sopenharmony_ci 537ac06127Sopenharmony_ci fn bytes(&self) -> Bytes<'a> { 547ac06127Sopenharmony_ci self.rest.bytes() 557ac06127Sopenharmony_ci } 567ac06127Sopenharmony_ci 577ac06127Sopenharmony_ci fn chars(&self) -> Chars<'a> { 587ac06127Sopenharmony_ci self.rest.chars() 597ac06127Sopenharmony_ci } 607ac06127Sopenharmony_ci 617ac06127Sopenharmony_ci fn char_indices(&self) -> CharIndices<'a> { 627ac06127Sopenharmony_ci self.rest.char_indices() 637ac06127Sopenharmony_ci } 647ac06127Sopenharmony_ci 657ac06127Sopenharmony_ci fn parse(&self, tag: &str) -> Result<Cursor<'a>, Reject> { 667ac06127Sopenharmony_ci if self.starts_with(tag) { 677ac06127Sopenharmony_ci Ok(self.advance(tag.len())) 687ac06127Sopenharmony_ci } else { 697ac06127Sopenharmony_ci Err(Reject) 707ac06127Sopenharmony_ci } 717ac06127Sopenharmony_ci } 727ac06127Sopenharmony_ci} 737ac06127Sopenharmony_ci 747ac06127Sopenharmony_cipub(crate) struct Reject; 757ac06127Sopenharmony_citype PResult<'a, O> = Result<(Cursor<'a>, O), Reject>; 767ac06127Sopenharmony_ci 777ac06127Sopenharmony_cifn skip_whitespace(input: Cursor) -> Cursor { 787ac06127Sopenharmony_ci let mut s = input; 797ac06127Sopenharmony_ci 807ac06127Sopenharmony_ci while !s.is_empty() { 817ac06127Sopenharmony_ci let byte = s.as_bytes()[0]; 827ac06127Sopenharmony_ci if byte == b'/' { 837ac06127Sopenharmony_ci if s.starts_with("//") 847ac06127Sopenharmony_ci && (!s.starts_with("///") || s.starts_with("////")) 857ac06127Sopenharmony_ci && !s.starts_with("//!") 867ac06127Sopenharmony_ci { 877ac06127Sopenharmony_ci let (cursor, _) = take_until_newline_or_eof(s); 887ac06127Sopenharmony_ci s = cursor; 897ac06127Sopenharmony_ci continue; 907ac06127Sopenharmony_ci } else if s.starts_with("/**/") { 917ac06127Sopenharmony_ci s = s.advance(4); 927ac06127Sopenharmony_ci continue; 937ac06127Sopenharmony_ci } else if s.starts_with("/*") 947ac06127Sopenharmony_ci && (!s.starts_with("/**") || s.starts_with("/***")) 957ac06127Sopenharmony_ci && !s.starts_with("/*!") 967ac06127Sopenharmony_ci { 977ac06127Sopenharmony_ci match block_comment(s) { 987ac06127Sopenharmony_ci Ok((rest, _)) => { 997ac06127Sopenharmony_ci s = rest; 1007ac06127Sopenharmony_ci continue; 1017ac06127Sopenharmony_ci } 1027ac06127Sopenharmony_ci Err(Reject) => return s, 1037ac06127Sopenharmony_ci } 1047ac06127Sopenharmony_ci } 1057ac06127Sopenharmony_ci } 1067ac06127Sopenharmony_ci match byte { 1077ac06127Sopenharmony_ci b' ' | 0x09..=0x0d => { 1087ac06127Sopenharmony_ci s = s.advance(1); 1097ac06127Sopenharmony_ci continue; 1107ac06127Sopenharmony_ci } 1117ac06127Sopenharmony_ci b if b.is_ascii() => {} 1127ac06127Sopenharmony_ci _ => { 1137ac06127Sopenharmony_ci let ch = s.chars().next().unwrap(); 1147ac06127Sopenharmony_ci if is_whitespace(ch) { 1157ac06127Sopenharmony_ci s = s.advance(ch.len_utf8()); 1167ac06127Sopenharmony_ci continue; 1177ac06127Sopenharmony_ci } 1187ac06127Sopenharmony_ci } 1197ac06127Sopenharmony_ci } 1207ac06127Sopenharmony_ci return s; 1217ac06127Sopenharmony_ci } 1227ac06127Sopenharmony_ci s 1237ac06127Sopenharmony_ci} 1247ac06127Sopenharmony_ci 1257ac06127Sopenharmony_cifn block_comment(input: Cursor) -> PResult<&str> { 1267ac06127Sopenharmony_ci if !input.starts_with("/*") { 1277ac06127Sopenharmony_ci return Err(Reject); 1287ac06127Sopenharmony_ci } 1297ac06127Sopenharmony_ci 1307ac06127Sopenharmony_ci let mut depth = 0usize; 1317ac06127Sopenharmony_ci let bytes = input.as_bytes(); 1327ac06127Sopenharmony_ci let mut i = 0usize; 1337ac06127Sopenharmony_ci let upper = bytes.len() - 1; 1347ac06127Sopenharmony_ci 1357ac06127Sopenharmony_ci while i < upper { 1367ac06127Sopenharmony_ci if bytes[i] == b'/' && bytes[i + 1] == b'*' { 1377ac06127Sopenharmony_ci depth += 1; 1387ac06127Sopenharmony_ci i += 1; // eat '*' 1397ac06127Sopenharmony_ci } else if bytes[i] == b'*' && bytes[i + 1] == b'/' { 1407ac06127Sopenharmony_ci depth -= 1; 1417ac06127Sopenharmony_ci if depth == 0 { 1427ac06127Sopenharmony_ci return Ok((input.advance(i + 2), &input.rest[..i + 2])); 1437ac06127Sopenharmony_ci } 1447ac06127Sopenharmony_ci i += 1; // eat '/' 1457ac06127Sopenharmony_ci } 1467ac06127Sopenharmony_ci i += 1; 1477ac06127Sopenharmony_ci } 1487ac06127Sopenharmony_ci 1497ac06127Sopenharmony_ci Err(Reject) 1507ac06127Sopenharmony_ci} 1517ac06127Sopenharmony_ci 1527ac06127Sopenharmony_cifn is_whitespace(ch: char) -> bool { 1537ac06127Sopenharmony_ci // Rust treats left-to-right mark and right-to-left mark as whitespace 1547ac06127Sopenharmony_ci ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}' 1557ac06127Sopenharmony_ci} 1567ac06127Sopenharmony_ci 1577ac06127Sopenharmony_cifn word_break(input: Cursor) -> Result<Cursor, Reject> { 1587ac06127Sopenharmony_ci match input.chars().next() { 1597ac06127Sopenharmony_ci Some(ch) if is_ident_continue(ch) => Err(Reject), 1607ac06127Sopenharmony_ci Some(_) | None => Ok(input), 1617ac06127Sopenharmony_ci } 1627ac06127Sopenharmony_ci} 1637ac06127Sopenharmony_ci 1647ac06127Sopenharmony_ci// Rustc's representation of a macro expansion error in expression position or 1657ac06127Sopenharmony_ci// type position. 1667ac06127Sopenharmony_ciconst ERROR: &str = "(/*ERROR*/)"; 1677ac06127Sopenharmony_ci 1687ac06127Sopenharmony_cipub(crate) fn token_stream(mut input: Cursor) -> Result<TokenStream, LexError> { 1697ac06127Sopenharmony_ci let mut trees = TokenStreamBuilder::new(); 1707ac06127Sopenharmony_ci let mut stack = Vec::new(); 1717ac06127Sopenharmony_ci 1727ac06127Sopenharmony_ci loop { 1737ac06127Sopenharmony_ci input = skip_whitespace(input); 1747ac06127Sopenharmony_ci 1757ac06127Sopenharmony_ci if let Ok((rest, ())) = doc_comment(input, &mut trees) { 1767ac06127Sopenharmony_ci input = rest; 1777ac06127Sopenharmony_ci continue; 1787ac06127Sopenharmony_ci } 1797ac06127Sopenharmony_ci 1807ac06127Sopenharmony_ci #[cfg(span_locations)] 1817ac06127Sopenharmony_ci let lo = input.off; 1827ac06127Sopenharmony_ci 1837ac06127Sopenharmony_ci let first = match input.bytes().next() { 1847ac06127Sopenharmony_ci Some(first) => first, 1857ac06127Sopenharmony_ci None => match stack.last() { 1867ac06127Sopenharmony_ci None => return Ok(trees.build()), 1877ac06127Sopenharmony_ci #[cfg(span_locations)] 1887ac06127Sopenharmony_ci Some((lo, _frame)) => { 1897ac06127Sopenharmony_ci return Err(LexError { 1907ac06127Sopenharmony_ci span: Span { lo: *lo, hi: *lo }, 1917ac06127Sopenharmony_ci }) 1927ac06127Sopenharmony_ci } 1937ac06127Sopenharmony_ci #[cfg(not(span_locations))] 1947ac06127Sopenharmony_ci Some(_frame) => return Err(LexError { span: Span {} }), 1957ac06127Sopenharmony_ci }, 1967ac06127Sopenharmony_ci }; 1977ac06127Sopenharmony_ci 1987ac06127Sopenharmony_ci if let Some(open_delimiter) = match first { 1997ac06127Sopenharmony_ci b'(' if !input.starts_with(ERROR) => Some(Delimiter::Parenthesis), 2007ac06127Sopenharmony_ci b'[' => Some(Delimiter::Bracket), 2017ac06127Sopenharmony_ci b'{' => Some(Delimiter::Brace), 2027ac06127Sopenharmony_ci _ => None, 2037ac06127Sopenharmony_ci } { 2047ac06127Sopenharmony_ci input = input.advance(1); 2057ac06127Sopenharmony_ci let frame = (open_delimiter, trees); 2067ac06127Sopenharmony_ci #[cfg(span_locations)] 2077ac06127Sopenharmony_ci let frame = (lo, frame); 2087ac06127Sopenharmony_ci stack.push(frame); 2097ac06127Sopenharmony_ci trees = TokenStreamBuilder::new(); 2107ac06127Sopenharmony_ci } else if let Some(close_delimiter) = match first { 2117ac06127Sopenharmony_ci b')' => Some(Delimiter::Parenthesis), 2127ac06127Sopenharmony_ci b']' => Some(Delimiter::Bracket), 2137ac06127Sopenharmony_ci b'}' => Some(Delimiter::Brace), 2147ac06127Sopenharmony_ci _ => None, 2157ac06127Sopenharmony_ci } { 2167ac06127Sopenharmony_ci let frame = match stack.pop() { 2177ac06127Sopenharmony_ci Some(frame) => frame, 2187ac06127Sopenharmony_ci None => return Err(lex_error(input)), 2197ac06127Sopenharmony_ci }; 2207ac06127Sopenharmony_ci #[cfg(span_locations)] 2217ac06127Sopenharmony_ci let (lo, frame) = frame; 2227ac06127Sopenharmony_ci let (open_delimiter, outer) = frame; 2237ac06127Sopenharmony_ci if open_delimiter != close_delimiter { 2247ac06127Sopenharmony_ci return Err(lex_error(input)); 2257ac06127Sopenharmony_ci } 2267ac06127Sopenharmony_ci input = input.advance(1); 2277ac06127Sopenharmony_ci let mut g = Group::new(open_delimiter, trees.build()); 2287ac06127Sopenharmony_ci g.set_span(Span { 2297ac06127Sopenharmony_ci #[cfg(span_locations)] 2307ac06127Sopenharmony_ci lo, 2317ac06127Sopenharmony_ci #[cfg(span_locations)] 2327ac06127Sopenharmony_ci hi: input.off, 2337ac06127Sopenharmony_ci }); 2347ac06127Sopenharmony_ci trees = outer; 2357ac06127Sopenharmony_ci trees.push_token_from_parser(TokenTree::Group(crate::Group::_new_fallback(g))); 2367ac06127Sopenharmony_ci } else { 2377ac06127Sopenharmony_ci let (rest, mut tt) = match leaf_token(input) { 2387ac06127Sopenharmony_ci Ok((rest, tt)) => (rest, tt), 2397ac06127Sopenharmony_ci Err(Reject) => return Err(lex_error(input)), 2407ac06127Sopenharmony_ci }; 2417ac06127Sopenharmony_ci tt.set_span(crate::Span::_new_fallback(Span { 2427ac06127Sopenharmony_ci #[cfg(span_locations)] 2437ac06127Sopenharmony_ci lo, 2447ac06127Sopenharmony_ci #[cfg(span_locations)] 2457ac06127Sopenharmony_ci hi: rest.off, 2467ac06127Sopenharmony_ci })); 2477ac06127Sopenharmony_ci trees.push_token_from_parser(tt); 2487ac06127Sopenharmony_ci input = rest; 2497ac06127Sopenharmony_ci } 2507ac06127Sopenharmony_ci } 2517ac06127Sopenharmony_ci} 2527ac06127Sopenharmony_ci 2537ac06127Sopenharmony_cifn lex_error(cursor: Cursor) -> LexError { 2547ac06127Sopenharmony_ci #[cfg(not(span_locations))] 2557ac06127Sopenharmony_ci let _ = cursor; 2567ac06127Sopenharmony_ci LexError { 2577ac06127Sopenharmony_ci span: Span { 2587ac06127Sopenharmony_ci #[cfg(span_locations)] 2597ac06127Sopenharmony_ci lo: cursor.off, 2607ac06127Sopenharmony_ci #[cfg(span_locations)] 2617ac06127Sopenharmony_ci hi: cursor.off, 2627ac06127Sopenharmony_ci }, 2637ac06127Sopenharmony_ci } 2647ac06127Sopenharmony_ci} 2657ac06127Sopenharmony_ci 2667ac06127Sopenharmony_cifn leaf_token(input: Cursor) -> PResult<TokenTree> { 2677ac06127Sopenharmony_ci if let Ok((input, l)) = literal(input) { 2687ac06127Sopenharmony_ci // must be parsed before ident 2697ac06127Sopenharmony_ci Ok((input, TokenTree::Literal(crate::Literal::_new_fallback(l)))) 2707ac06127Sopenharmony_ci } else if let Ok((input, p)) = punct(input) { 2717ac06127Sopenharmony_ci Ok((input, TokenTree::Punct(p))) 2727ac06127Sopenharmony_ci } else if let Ok((input, i)) = ident(input) { 2737ac06127Sopenharmony_ci Ok((input, TokenTree::Ident(i))) 2747ac06127Sopenharmony_ci } else if input.starts_with(ERROR) { 2757ac06127Sopenharmony_ci let rest = input.advance(ERROR.len()); 2767ac06127Sopenharmony_ci let repr = crate::Literal::_new_fallback(Literal::_new(ERROR.to_owned())); 2777ac06127Sopenharmony_ci Ok((rest, TokenTree::Literal(repr))) 2787ac06127Sopenharmony_ci } else { 2797ac06127Sopenharmony_ci Err(Reject) 2807ac06127Sopenharmony_ci } 2817ac06127Sopenharmony_ci} 2827ac06127Sopenharmony_ci 2837ac06127Sopenharmony_cifn ident(input: Cursor) -> PResult<crate::Ident> { 2847ac06127Sopenharmony_ci if [ 2857ac06127Sopenharmony_ci "r\"", "r#\"", "r##", "b\"", "b\'", "br\"", "br#", "c\"", "cr\"", "cr#", 2867ac06127Sopenharmony_ci ] 2877ac06127Sopenharmony_ci .iter() 2887ac06127Sopenharmony_ci .any(|prefix| input.starts_with(prefix)) 2897ac06127Sopenharmony_ci { 2907ac06127Sopenharmony_ci Err(Reject) 2917ac06127Sopenharmony_ci } else { 2927ac06127Sopenharmony_ci ident_any(input) 2937ac06127Sopenharmony_ci } 2947ac06127Sopenharmony_ci} 2957ac06127Sopenharmony_ci 2967ac06127Sopenharmony_cifn ident_any(input: Cursor) -> PResult<crate::Ident> { 2977ac06127Sopenharmony_ci let raw = input.starts_with("r#"); 2987ac06127Sopenharmony_ci let rest = input.advance((raw as usize) << 1); 2997ac06127Sopenharmony_ci 3007ac06127Sopenharmony_ci let (rest, sym) = ident_not_raw(rest)?; 3017ac06127Sopenharmony_ci 3027ac06127Sopenharmony_ci if !raw { 3037ac06127Sopenharmony_ci let ident = crate::Ident::_new(crate::imp::Ident::new_unchecked( 3047ac06127Sopenharmony_ci sym, 3057ac06127Sopenharmony_ci fallback::Span::call_site(), 3067ac06127Sopenharmony_ci )); 3077ac06127Sopenharmony_ci return Ok((rest, ident)); 3087ac06127Sopenharmony_ci } 3097ac06127Sopenharmony_ci 3107ac06127Sopenharmony_ci match sym { 3117ac06127Sopenharmony_ci "_" | "super" | "self" | "Self" | "crate" => return Err(Reject), 3127ac06127Sopenharmony_ci _ => {} 3137ac06127Sopenharmony_ci } 3147ac06127Sopenharmony_ci 3157ac06127Sopenharmony_ci let ident = crate::Ident::_new(crate::imp::Ident::new_raw_unchecked( 3167ac06127Sopenharmony_ci sym, 3177ac06127Sopenharmony_ci fallback::Span::call_site(), 3187ac06127Sopenharmony_ci )); 3197ac06127Sopenharmony_ci Ok((rest, ident)) 3207ac06127Sopenharmony_ci} 3217ac06127Sopenharmony_ci 3227ac06127Sopenharmony_cifn ident_not_raw(input: Cursor) -> PResult<&str> { 3237ac06127Sopenharmony_ci let mut chars = input.char_indices(); 3247ac06127Sopenharmony_ci 3257ac06127Sopenharmony_ci match chars.next() { 3267ac06127Sopenharmony_ci Some((_, ch)) if is_ident_start(ch) => {} 3277ac06127Sopenharmony_ci _ => return Err(Reject), 3287ac06127Sopenharmony_ci } 3297ac06127Sopenharmony_ci 3307ac06127Sopenharmony_ci let mut end = input.len(); 3317ac06127Sopenharmony_ci for (i, ch) in chars { 3327ac06127Sopenharmony_ci if !is_ident_continue(ch) { 3337ac06127Sopenharmony_ci end = i; 3347ac06127Sopenharmony_ci break; 3357ac06127Sopenharmony_ci } 3367ac06127Sopenharmony_ci } 3377ac06127Sopenharmony_ci 3387ac06127Sopenharmony_ci Ok((input.advance(end), &input.rest[..end])) 3397ac06127Sopenharmony_ci} 3407ac06127Sopenharmony_ci 3417ac06127Sopenharmony_cipub(crate) fn literal(input: Cursor) -> PResult<Literal> { 3427ac06127Sopenharmony_ci let rest = literal_nocapture(input)?; 3437ac06127Sopenharmony_ci let end = input.len() - rest.len(); 3447ac06127Sopenharmony_ci Ok((rest, Literal::_new(input.rest[..end].to_string()))) 3457ac06127Sopenharmony_ci} 3467ac06127Sopenharmony_ci 3477ac06127Sopenharmony_cifn literal_nocapture(input: Cursor) -> Result<Cursor, Reject> { 3487ac06127Sopenharmony_ci if let Ok(ok) = string(input) { 3497ac06127Sopenharmony_ci Ok(ok) 3507ac06127Sopenharmony_ci } else if let Ok(ok) = byte_string(input) { 3517ac06127Sopenharmony_ci Ok(ok) 3527ac06127Sopenharmony_ci } else if let Ok(ok) = c_string(input) { 3537ac06127Sopenharmony_ci Ok(ok) 3547ac06127Sopenharmony_ci } else if let Ok(ok) = byte(input) { 3557ac06127Sopenharmony_ci Ok(ok) 3567ac06127Sopenharmony_ci } else if let Ok(ok) = character(input) { 3577ac06127Sopenharmony_ci Ok(ok) 3587ac06127Sopenharmony_ci } else if let Ok(ok) = float(input) { 3597ac06127Sopenharmony_ci Ok(ok) 3607ac06127Sopenharmony_ci } else if let Ok(ok) = int(input) { 3617ac06127Sopenharmony_ci Ok(ok) 3627ac06127Sopenharmony_ci } else { 3637ac06127Sopenharmony_ci Err(Reject) 3647ac06127Sopenharmony_ci } 3657ac06127Sopenharmony_ci} 3667ac06127Sopenharmony_ci 3677ac06127Sopenharmony_cifn literal_suffix(input: Cursor) -> Cursor { 3687ac06127Sopenharmony_ci match ident_not_raw(input) { 3697ac06127Sopenharmony_ci Ok((input, _)) => input, 3707ac06127Sopenharmony_ci Err(Reject) => input, 3717ac06127Sopenharmony_ci } 3727ac06127Sopenharmony_ci} 3737ac06127Sopenharmony_ci 3747ac06127Sopenharmony_cifn string(input: Cursor) -> Result<Cursor, Reject> { 3757ac06127Sopenharmony_ci if let Ok(input) = input.parse("\"") { 3767ac06127Sopenharmony_ci cooked_string(input) 3777ac06127Sopenharmony_ci } else if let Ok(input) = input.parse("r") { 3787ac06127Sopenharmony_ci raw_string(input) 3797ac06127Sopenharmony_ci } else { 3807ac06127Sopenharmony_ci Err(Reject) 3817ac06127Sopenharmony_ci } 3827ac06127Sopenharmony_ci} 3837ac06127Sopenharmony_ci 3847ac06127Sopenharmony_cifn cooked_string(mut input: Cursor) -> Result<Cursor, Reject> { 3857ac06127Sopenharmony_ci let mut chars = input.char_indices(); 3867ac06127Sopenharmony_ci 3877ac06127Sopenharmony_ci while let Some((i, ch)) = chars.next() { 3887ac06127Sopenharmony_ci match ch { 3897ac06127Sopenharmony_ci '"' => { 3907ac06127Sopenharmony_ci let input = input.advance(i + 1); 3917ac06127Sopenharmony_ci return Ok(literal_suffix(input)); 3927ac06127Sopenharmony_ci } 3937ac06127Sopenharmony_ci '\r' => match chars.next() { 3947ac06127Sopenharmony_ci Some((_, '\n')) => {} 3957ac06127Sopenharmony_ci _ => break, 3967ac06127Sopenharmony_ci }, 3977ac06127Sopenharmony_ci '\\' => match chars.next() { 3987ac06127Sopenharmony_ci Some((_, 'x')) => { 3997ac06127Sopenharmony_ci backslash_x_char(&mut chars)?; 4007ac06127Sopenharmony_ci } 4017ac06127Sopenharmony_ci Some((_, 'n' | 'r' | 't' | '\\' | '\'' | '"' | '0')) => {} 4027ac06127Sopenharmony_ci Some((_, 'u')) => { 4037ac06127Sopenharmony_ci backslash_u(&mut chars)?; 4047ac06127Sopenharmony_ci } 4057ac06127Sopenharmony_ci Some((newline, ch @ ('\n' | '\r'))) => { 4067ac06127Sopenharmony_ci input = input.advance(newline + 1); 4077ac06127Sopenharmony_ci trailing_backslash(&mut input, ch as u8)?; 4087ac06127Sopenharmony_ci chars = input.char_indices(); 4097ac06127Sopenharmony_ci } 4107ac06127Sopenharmony_ci _ => break, 4117ac06127Sopenharmony_ci }, 4127ac06127Sopenharmony_ci _ch => {} 4137ac06127Sopenharmony_ci } 4147ac06127Sopenharmony_ci } 4157ac06127Sopenharmony_ci Err(Reject) 4167ac06127Sopenharmony_ci} 4177ac06127Sopenharmony_ci 4187ac06127Sopenharmony_cifn raw_string(input: Cursor) -> Result<Cursor, Reject> { 4197ac06127Sopenharmony_ci let (input, delimiter) = delimiter_of_raw_string(input)?; 4207ac06127Sopenharmony_ci let mut bytes = input.bytes().enumerate(); 4217ac06127Sopenharmony_ci while let Some((i, byte)) = bytes.next() { 4227ac06127Sopenharmony_ci match byte { 4237ac06127Sopenharmony_ci b'"' if input.rest[i + 1..].starts_with(delimiter) => { 4247ac06127Sopenharmony_ci let rest = input.advance(i + 1 + delimiter.len()); 4257ac06127Sopenharmony_ci return Ok(literal_suffix(rest)); 4267ac06127Sopenharmony_ci } 4277ac06127Sopenharmony_ci b'\r' => match bytes.next() { 4287ac06127Sopenharmony_ci Some((_, b'\n')) => {} 4297ac06127Sopenharmony_ci _ => break, 4307ac06127Sopenharmony_ci }, 4317ac06127Sopenharmony_ci _ => {} 4327ac06127Sopenharmony_ci } 4337ac06127Sopenharmony_ci } 4347ac06127Sopenharmony_ci Err(Reject) 4357ac06127Sopenharmony_ci} 4367ac06127Sopenharmony_ci 4377ac06127Sopenharmony_cifn byte_string(input: Cursor) -> Result<Cursor, Reject> { 4387ac06127Sopenharmony_ci if let Ok(input) = input.parse("b\"") { 4397ac06127Sopenharmony_ci cooked_byte_string(input) 4407ac06127Sopenharmony_ci } else if let Ok(input) = input.parse("br") { 4417ac06127Sopenharmony_ci raw_byte_string(input) 4427ac06127Sopenharmony_ci } else { 4437ac06127Sopenharmony_ci Err(Reject) 4447ac06127Sopenharmony_ci } 4457ac06127Sopenharmony_ci} 4467ac06127Sopenharmony_ci 4477ac06127Sopenharmony_cifn cooked_byte_string(mut input: Cursor) -> Result<Cursor, Reject> { 4487ac06127Sopenharmony_ci let mut bytes = input.bytes().enumerate(); 4497ac06127Sopenharmony_ci while let Some((offset, b)) = bytes.next() { 4507ac06127Sopenharmony_ci match b { 4517ac06127Sopenharmony_ci b'"' => { 4527ac06127Sopenharmony_ci let input = input.advance(offset + 1); 4537ac06127Sopenharmony_ci return Ok(literal_suffix(input)); 4547ac06127Sopenharmony_ci } 4557ac06127Sopenharmony_ci b'\r' => match bytes.next() { 4567ac06127Sopenharmony_ci Some((_, b'\n')) => {} 4577ac06127Sopenharmony_ci _ => break, 4587ac06127Sopenharmony_ci }, 4597ac06127Sopenharmony_ci b'\\' => match bytes.next() { 4607ac06127Sopenharmony_ci Some((_, b'x')) => { 4617ac06127Sopenharmony_ci backslash_x_byte(&mut bytes)?; 4627ac06127Sopenharmony_ci } 4637ac06127Sopenharmony_ci Some((_, b'n' | b'r' | b't' | b'\\' | b'0' | b'\'' | b'"')) => {} 4647ac06127Sopenharmony_ci Some((newline, b @ (b'\n' | b'\r'))) => { 4657ac06127Sopenharmony_ci input = input.advance(newline + 1); 4667ac06127Sopenharmony_ci trailing_backslash(&mut input, b)?; 4677ac06127Sopenharmony_ci bytes = input.bytes().enumerate(); 4687ac06127Sopenharmony_ci } 4697ac06127Sopenharmony_ci _ => break, 4707ac06127Sopenharmony_ci }, 4717ac06127Sopenharmony_ci b if b.is_ascii() => {} 4727ac06127Sopenharmony_ci _ => break, 4737ac06127Sopenharmony_ci } 4747ac06127Sopenharmony_ci } 4757ac06127Sopenharmony_ci Err(Reject) 4767ac06127Sopenharmony_ci} 4777ac06127Sopenharmony_ci 4787ac06127Sopenharmony_cifn delimiter_of_raw_string(input: Cursor) -> PResult<&str> { 4797ac06127Sopenharmony_ci for (i, byte) in input.bytes().enumerate() { 4807ac06127Sopenharmony_ci match byte { 4817ac06127Sopenharmony_ci b'"' => { 4827ac06127Sopenharmony_ci if i > 255 { 4837ac06127Sopenharmony_ci // https://github.com/rust-lang/rust/pull/95251 4847ac06127Sopenharmony_ci return Err(Reject); 4857ac06127Sopenharmony_ci } 4867ac06127Sopenharmony_ci return Ok((input.advance(i + 1), &input.rest[..i])); 4877ac06127Sopenharmony_ci } 4887ac06127Sopenharmony_ci b'#' => {} 4897ac06127Sopenharmony_ci _ => break, 4907ac06127Sopenharmony_ci } 4917ac06127Sopenharmony_ci } 4927ac06127Sopenharmony_ci Err(Reject) 4937ac06127Sopenharmony_ci} 4947ac06127Sopenharmony_ci 4957ac06127Sopenharmony_cifn raw_byte_string(input: Cursor) -> Result<Cursor, Reject> { 4967ac06127Sopenharmony_ci let (input, delimiter) = delimiter_of_raw_string(input)?; 4977ac06127Sopenharmony_ci let mut bytes = input.bytes().enumerate(); 4987ac06127Sopenharmony_ci while let Some((i, byte)) = bytes.next() { 4997ac06127Sopenharmony_ci match byte { 5007ac06127Sopenharmony_ci b'"' if input.rest[i + 1..].starts_with(delimiter) => { 5017ac06127Sopenharmony_ci let rest = input.advance(i + 1 + delimiter.len()); 5027ac06127Sopenharmony_ci return Ok(literal_suffix(rest)); 5037ac06127Sopenharmony_ci } 5047ac06127Sopenharmony_ci b'\r' => match bytes.next() { 5057ac06127Sopenharmony_ci Some((_, b'\n')) => {} 5067ac06127Sopenharmony_ci _ => break, 5077ac06127Sopenharmony_ci }, 5087ac06127Sopenharmony_ci other => { 5097ac06127Sopenharmony_ci if !other.is_ascii() { 5107ac06127Sopenharmony_ci break; 5117ac06127Sopenharmony_ci } 5127ac06127Sopenharmony_ci } 5137ac06127Sopenharmony_ci } 5147ac06127Sopenharmony_ci } 5157ac06127Sopenharmony_ci Err(Reject) 5167ac06127Sopenharmony_ci} 5177ac06127Sopenharmony_ci 5187ac06127Sopenharmony_cifn c_string(input: Cursor) -> Result<Cursor, Reject> { 5197ac06127Sopenharmony_ci if let Ok(input) = input.parse("c\"") { 5207ac06127Sopenharmony_ci cooked_c_string(input) 5217ac06127Sopenharmony_ci } else if let Ok(input) = input.parse("cr") { 5227ac06127Sopenharmony_ci raw_c_string(input) 5237ac06127Sopenharmony_ci } else { 5247ac06127Sopenharmony_ci Err(Reject) 5257ac06127Sopenharmony_ci } 5267ac06127Sopenharmony_ci} 5277ac06127Sopenharmony_ci 5287ac06127Sopenharmony_cifn raw_c_string(input: Cursor) -> Result<Cursor, Reject> { 5297ac06127Sopenharmony_ci let (input, delimiter) = delimiter_of_raw_string(input)?; 5307ac06127Sopenharmony_ci let mut bytes = input.bytes().enumerate(); 5317ac06127Sopenharmony_ci while let Some((i, byte)) = bytes.next() { 5327ac06127Sopenharmony_ci match byte { 5337ac06127Sopenharmony_ci b'"' if input.rest[i + 1..].starts_with(delimiter) => { 5347ac06127Sopenharmony_ci let rest = input.advance(i + 1 + delimiter.len()); 5357ac06127Sopenharmony_ci return Ok(literal_suffix(rest)); 5367ac06127Sopenharmony_ci } 5377ac06127Sopenharmony_ci b'\r' => match bytes.next() { 5387ac06127Sopenharmony_ci Some((_, b'\n')) => {} 5397ac06127Sopenharmony_ci _ => break, 5407ac06127Sopenharmony_ci }, 5417ac06127Sopenharmony_ci b'\0' => break, 5427ac06127Sopenharmony_ci _ => {} 5437ac06127Sopenharmony_ci } 5447ac06127Sopenharmony_ci } 5457ac06127Sopenharmony_ci Err(Reject) 5467ac06127Sopenharmony_ci} 5477ac06127Sopenharmony_ci 5487ac06127Sopenharmony_cifn cooked_c_string(mut input: Cursor) -> Result<Cursor, Reject> { 5497ac06127Sopenharmony_ci let mut chars = input.char_indices(); 5507ac06127Sopenharmony_ci 5517ac06127Sopenharmony_ci while let Some((i, ch)) = chars.next() { 5527ac06127Sopenharmony_ci match ch { 5537ac06127Sopenharmony_ci '"' => { 5547ac06127Sopenharmony_ci let input = input.advance(i + 1); 5557ac06127Sopenharmony_ci return Ok(literal_suffix(input)); 5567ac06127Sopenharmony_ci } 5577ac06127Sopenharmony_ci '\r' => match chars.next() { 5587ac06127Sopenharmony_ci Some((_, '\n')) => {} 5597ac06127Sopenharmony_ci _ => break, 5607ac06127Sopenharmony_ci }, 5617ac06127Sopenharmony_ci '\\' => match chars.next() { 5627ac06127Sopenharmony_ci Some((_, 'x')) => { 5637ac06127Sopenharmony_ci backslash_x_nonzero(&mut chars)?; 5647ac06127Sopenharmony_ci } 5657ac06127Sopenharmony_ci Some((_, 'n' | 'r' | 't' | '\\' | '\'' | '"')) => {} 5667ac06127Sopenharmony_ci Some((_, 'u')) => { 5677ac06127Sopenharmony_ci if backslash_u(&mut chars)? == '\0' { 5687ac06127Sopenharmony_ci break; 5697ac06127Sopenharmony_ci } 5707ac06127Sopenharmony_ci } 5717ac06127Sopenharmony_ci Some((newline, ch @ ('\n' | '\r'))) => { 5727ac06127Sopenharmony_ci input = input.advance(newline + 1); 5737ac06127Sopenharmony_ci trailing_backslash(&mut input, ch as u8)?; 5747ac06127Sopenharmony_ci chars = input.char_indices(); 5757ac06127Sopenharmony_ci } 5767ac06127Sopenharmony_ci _ => break, 5777ac06127Sopenharmony_ci }, 5787ac06127Sopenharmony_ci '\0' => break, 5797ac06127Sopenharmony_ci _ch => {} 5807ac06127Sopenharmony_ci } 5817ac06127Sopenharmony_ci } 5827ac06127Sopenharmony_ci Err(Reject) 5837ac06127Sopenharmony_ci} 5847ac06127Sopenharmony_ci 5857ac06127Sopenharmony_cifn byte(input: Cursor) -> Result<Cursor, Reject> { 5867ac06127Sopenharmony_ci let input = input.parse("b'")?; 5877ac06127Sopenharmony_ci let mut bytes = input.bytes().enumerate(); 5887ac06127Sopenharmony_ci let ok = match bytes.next().map(|(_, b)| b) { 5897ac06127Sopenharmony_ci Some(b'\\') => match bytes.next().map(|(_, b)| b) { 5907ac06127Sopenharmony_ci Some(b'x') => backslash_x_byte(&mut bytes).is_ok(), 5917ac06127Sopenharmony_ci Some(b'n' | b'r' | b't' | b'\\' | b'0' | b'\'' | b'"') => true, 5927ac06127Sopenharmony_ci _ => false, 5937ac06127Sopenharmony_ci }, 5947ac06127Sopenharmony_ci b => b.is_some(), 5957ac06127Sopenharmony_ci }; 5967ac06127Sopenharmony_ci if !ok { 5977ac06127Sopenharmony_ci return Err(Reject); 5987ac06127Sopenharmony_ci } 5997ac06127Sopenharmony_ci let (offset, _) = bytes.next().ok_or(Reject)?; 6007ac06127Sopenharmony_ci if !input.chars().as_str().is_char_boundary(offset) { 6017ac06127Sopenharmony_ci return Err(Reject); 6027ac06127Sopenharmony_ci } 6037ac06127Sopenharmony_ci let input = input.advance(offset).parse("'")?; 6047ac06127Sopenharmony_ci Ok(literal_suffix(input)) 6057ac06127Sopenharmony_ci} 6067ac06127Sopenharmony_ci 6077ac06127Sopenharmony_cifn character(input: Cursor) -> Result<Cursor, Reject> { 6087ac06127Sopenharmony_ci let input = input.parse("'")?; 6097ac06127Sopenharmony_ci let mut chars = input.char_indices(); 6107ac06127Sopenharmony_ci let ok = match chars.next().map(|(_, ch)| ch) { 6117ac06127Sopenharmony_ci Some('\\') => match chars.next().map(|(_, ch)| ch) { 6127ac06127Sopenharmony_ci Some('x') => backslash_x_char(&mut chars).is_ok(), 6137ac06127Sopenharmony_ci Some('u') => backslash_u(&mut chars).is_ok(), 6147ac06127Sopenharmony_ci Some('n' | 'r' | 't' | '\\' | '0' | '\'' | '"') => true, 6157ac06127Sopenharmony_ci _ => false, 6167ac06127Sopenharmony_ci }, 6177ac06127Sopenharmony_ci ch => ch.is_some(), 6187ac06127Sopenharmony_ci }; 6197ac06127Sopenharmony_ci if !ok { 6207ac06127Sopenharmony_ci return Err(Reject); 6217ac06127Sopenharmony_ci } 6227ac06127Sopenharmony_ci let (idx, _) = chars.next().ok_or(Reject)?; 6237ac06127Sopenharmony_ci let input = input.advance(idx).parse("'")?; 6247ac06127Sopenharmony_ci Ok(literal_suffix(input)) 6257ac06127Sopenharmony_ci} 6267ac06127Sopenharmony_ci 6277ac06127Sopenharmony_cimacro_rules! next_ch { 6287ac06127Sopenharmony_ci ($chars:ident @ $pat:pat) => { 6297ac06127Sopenharmony_ci match $chars.next() { 6307ac06127Sopenharmony_ci Some((_, ch)) => match ch { 6317ac06127Sopenharmony_ci $pat => ch, 6327ac06127Sopenharmony_ci _ => return Err(Reject), 6337ac06127Sopenharmony_ci }, 6347ac06127Sopenharmony_ci None => return Err(Reject), 6357ac06127Sopenharmony_ci } 6367ac06127Sopenharmony_ci }; 6377ac06127Sopenharmony_ci} 6387ac06127Sopenharmony_ci 6397ac06127Sopenharmony_cifn backslash_x_char<I>(chars: &mut I) -> Result<(), Reject> 6407ac06127Sopenharmony_ciwhere 6417ac06127Sopenharmony_ci I: Iterator<Item = (usize, char)>, 6427ac06127Sopenharmony_ci{ 6437ac06127Sopenharmony_ci next_ch!(chars @ '0'..='7'); 6447ac06127Sopenharmony_ci next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); 6457ac06127Sopenharmony_ci Ok(()) 6467ac06127Sopenharmony_ci} 6477ac06127Sopenharmony_ci 6487ac06127Sopenharmony_cifn backslash_x_byte<I>(chars: &mut I) -> Result<(), Reject> 6497ac06127Sopenharmony_ciwhere 6507ac06127Sopenharmony_ci I: Iterator<Item = (usize, u8)>, 6517ac06127Sopenharmony_ci{ 6527ac06127Sopenharmony_ci next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); 6537ac06127Sopenharmony_ci next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); 6547ac06127Sopenharmony_ci Ok(()) 6557ac06127Sopenharmony_ci} 6567ac06127Sopenharmony_ci 6577ac06127Sopenharmony_cifn backslash_x_nonzero<I>(chars: &mut I) -> Result<(), Reject> 6587ac06127Sopenharmony_ciwhere 6597ac06127Sopenharmony_ci I: Iterator<Item = (usize, char)>, 6607ac06127Sopenharmony_ci{ 6617ac06127Sopenharmony_ci let first = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); 6627ac06127Sopenharmony_ci let second = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); 6637ac06127Sopenharmony_ci if first == '0' && second == '0' { 6647ac06127Sopenharmony_ci Err(Reject) 6657ac06127Sopenharmony_ci } else { 6667ac06127Sopenharmony_ci Ok(()) 6677ac06127Sopenharmony_ci } 6687ac06127Sopenharmony_ci} 6697ac06127Sopenharmony_ci 6707ac06127Sopenharmony_cifn backslash_u<I>(chars: &mut I) -> Result<char, Reject> 6717ac06127Sopenharmony_ciwhere 6727ac06127Sopenharmony_ci I: Iterator<Item = (usize, char)>, 6737ac06127Sopenharmony_ci{ 6747ac06127Sopenharmony_ci next_ch!(chars @ '{'); 6757ac06127Sopenharmony_ci let mut value = 0; 6767ac06127Sopenharmony_ci let mut len = 0; 6777ac06127Sopenharmony_ci for (_, ch) in chars { 6787ac06127Sopenharmony_ci let digit = match ch { 6797ac06127Sopenharmony_ci '0'..='9' => ch as u8 - b'0', 6807ac06127Sopenharmony_ci 'a'..='f' => 10 + ch as u8 - b'a', 6817ac06127Sopenharmony_ci 'A'..='F' => 10 + ch as u8 - b'A', 6827ac06127Sopenharmony_ci '_' if len > 0 => continue, 6837ac06127Sopenharmony_ci '}' if len > 0 => return char::from_u32(value).ok_or(Reject), 6847ac06127Sopenharmony_ci _ => break, 6857ac06127Sopenharmony_ci }; 6867ac06127Sopenharmony_ci if len == 6 { 6877ac06127Sopenharmony_ci break; 6887ac06127Sopenharmony_ci } 6897ac06127Sopenharmony_ci value *= 0x10; 6907ac06127Sopenharmony_ci value += u32::from(digit); 6917ac06127Sopenharmony_ci len += 1; 6927ac06127Sopenharmony_ci } 6937ac06127Sopenharmony_ci Err(Reject) 6947ac06127Sopenharmony_ci} 6957ac06127Sopenharmony_ci 6967ac06127Sopenharmony_cifn trailing_backslash(input: &mut Cursor, mut last: u8) -> Result<(), Reject> { 6977ac06127Sopenharmony_ci let mut whitespace = input.bytes().enumerate(); 6987ac06127Sopenharmony_ci loop { 6997ac06127Sopenharmony_ci if last == b'\r' && whitespace.next().map_or(true, |(_, b)| b != b'\n') { 7007ac06127Sopenharmony_ci return Err(Reject); 7017ac06127Sopenharmony_ci } 7027ac06127Sopenharmony_ci match whitespace.next() { 7037ac06127Sopenharmony_ci Some((_, b @ (b' ' | b'\t' | b'\n' | b'\r'))) => { 7047ac06127Sopenharmony_ci last = b; 7057ac06127Sopenharmony_ci } 7067ac06127Sopenharmony_ci Some((offset, _)) => { 7077ac06127Sopenharmony_ci *input = input.advance(offset); 7087ac06127Sopenharmony_ci return Ok(()); 7097ac06127Sopenharmony_ci } 7107ac06127Sopenharmony_ci None => return Err(Reject), 7117ac06127Sopenharmony_ci } 7127ac06127Sopenharmony_ci } 7137ac06127Sopenharmony_ci} 7147ac06127Sopenharmony_ci 7157ac06127Sopenharmony_cifn float(input: Cursor) -> Result<Cursor, Reject> { 7167ac06127Sopenharmony_ci let mut rest = float_digits(input)?; 7177ac06127Sopenharmony_ci if let Some(ch) = rest.chars().next() { 7187ac06127Sopenharmony_ci if is_ident_start(ch) { 7197ac06127Sopenharmony_ci rest = ident_not_raw(rest)?.0; 7207ac06127Sopenharmony_ci } 7217ac06127Sopenharmony_ci } 7227ac06127Sopenharmony_ci word_break(rest) 7237ac06127Sopenharmony_ci} 7247ac06127Sopenharmony_ci 7257ac06127Sopenharmony_cifn float_digits(input: Cursor) -> Result<Cursor, Reject> { 7267ac06127Sopenharmony_ci let mut chars = input.chars().peekable(); 7277ac06127Sopenharmony_ci match chars.next() { 7287ac06127Sopenharmony_ci Some(ch) if '0' <= ch && ch <= '9' => {} 7297ac06127Sopenharmony_ci _ => return Err(Reject), 7307ac06127Sopenharmony_ci } 7317ac06127Sopenharmony_ci 7327ac06127Sopenharmony_ci let mut len = 1; 7337ac06127Sopenharmony_ci let mut has_dot = false; 7347ac06127Sopenharmony_ci let mut has_exp = false; 7357ac06127Sopenharmony_ci while let Some(&ch) = chars.peek() { 7367ac06127Sopenharmony_ci match ch { 7377ac06127Sopenharmony_ci '0'..='9' | '_' => { 7387ac06127Sopenharmony_ci chars.next(); 7397ac06127Sopenharmony_ci len += 1; 7407ac06127Sopenharmony_ci } 7417ac06127Sopenharmony_ci '.' => { 7427ac06127Sopenharmony_ci if has_dot { 7437ac06127Sopenharmony_ci break; 7447ac06127Sopenharmony_ci } 7457ac06127Sopenharmony_ci chars.next(); 7467ac06127Sopenharmony_ci if chars 7477ac06127Sopenharmony_ci .peek() 7487ac06127Sopenharmony_ci .map_or(false, |&ch| ch == '.' || is_ident_start(ch)) 7497ac06127Sopenharmony_ci { 7507ac06127Sopenharmony_ci return Err(Reject); 7517ac06127Sopenharmony_ci } 7527ac06127Sopenharmony_ci len += 1; 7537ac06127Sopenharmony_ci has_dot = true; 7547ac06127Sopenharmony_ci } 7557ac06127Sopenharmony_ci 'e' | 'E' => { 7567ac06127Sopenharmony_ci chars.next(); 7577ac06127Sopenharmony_ci len += 1; 7587ac06127Sopenharmony_ci has_exp = true; 7597ac06127Sopenharmony_ci break; 7607ac06127Sopenharmony_ci } 7617ac06127Sopenharmony_ci _ => break, 7627ac06127Sopenharmony_ci } 7637ac06127Sopenharmony_ci } 7647ac06127Sopenharmony_ci 7657ac06127Sopenharmony_ci if !(has_dot || has_exp) { 7667ac06127Sopenharmony_ci return Err(Reject); 7677ac06127Sopenharmony_ci } 7687ac06127Sopenharmony_ci 7697ac06127Sopenharmony_ci if has_exp { 7707ac06127Sopenharmony_ci let token_before_exp = if has_dot { 7717ac06127Sopenharmony_ci Ok(input.advance(len - 1)) 7727ac06127Sopenharmony_ci } else { 7737ac06127Sopenharmony_ci Err(Reject) 7747ac06127Sopenharmony_ci }; 7757ac06127Sopenharmony_ci let mut has_sign = false; 7767ac06127Sopenharmony_ci let mut has_exp_value = false; 7777ac06127Sopenharmony_ci while let Some(&ch) = chars.peek() { 7787ac06127Sopenharmony_ci match ch { 7797ac06127Sopenharmony_ci '+' | '-' => { 7807ac06127Sopenharmony_ci if has_exp_value { 7817ac06127Sopenharmony_ci break; 7827ac06127Sopenharmony_ci } 7837ac06127Sopenharmony_ci if has_sign { 7847ac06127Sopenharmony_ci return token_before_exp; 7857ac06127Sopenharmony_ci } 7867ac06127Sopenharmony_ci chars.next(); 7877ac06127Sopenharmony_ci len += 1; 7887ac06127Sopenharmony_ci has_sign = true; 7897ac06127Sopenharmony_ci } 7907ac06127Sopenharmony_ci '0'..='9' => { 7917ac06127Sopenharmony_ci chars.next(); 7927ac06127Sopenharmony_ci len += 1; 7937ac06127Sopenharmony_ci has_exp_value = true; 7947ac06127Sopenharmony_ci } 7957ac06127Sopenharmony_ci '_' => { 7967ac06127Sopenharmony_ci chars.next(); 7977ac06127Sopenharmony_ci len += 1; 7987ac06127Sopenharmony_ci } 7997ac06127Sopenharmony_ci _ => break, 8007ac06127Sopenharmony_ci } 8017ac06127Sopenharmony_ci } 8027ac06127Sopenharmony_ci if !has_exp_value { 8037ac06127Sopenharmony_ci return token_before_exp; 8047ac06127Sopenharmony_ci } 8057ac06127Sopenharmony_ci } 8067ac06127Sopenharmony_ci 8077ac06127Sopenharmony_ci Ok(input.advance(len)) 8087ac06127Sopenharmony_ci} 8097ac06127Sopenharmony_ci 8107ac06127Sopenharmony_cifn int(input: Cursor) -> Result<Cursor, Reject> { 8117ac06127Sopenharmony_ci let mut rest = digits(input)?; 8127ac06127Sopenharmony_ci if let Some(ch) = rest.chars().next() { 8137ac06127Sopenharmony_ci if is_ident_start(ch) { 8147ac06127Sopenharmony_ci rest = ident_not_raw(rest)?.0; 8157ac06127Sopenharmony_ci } 8167ac06127Sopenharmony_ci } 8177ac06127Sopenharmony_ci word_break(rest) 8187ac06127Sopenharmony_ci} 8197ac06127Sopenharmony_ci 8207ac06127Sopenharmony_cifn digits(mut input: Cursor) -> Result<Cursor, Reject> { 8217ac06127Sopenharmony_ci let base = if input.starts_with("0x") { 8227ac06127Sopenharmony_ci input = input.advance(2); 8237ac06127Sopenharmony_ci 16 8247ac06127Sopenharmony_ci } else if input.starts_with("0o") { 8257ac06127Sopenharmony_ci input = input.advance(2); 8267ac06127Sopenharmony_ci 8 8277ac06127Sopenharmony_ci } else if input.starts_with("0b") { 8287ac06127Sopenharmony_ci input = input.advance(2); 8297ac06127Sopenharmony_ci 2 8307ac06127Sopenharmony_ci } else { 8317ac06127Sopenharmony_ci 10 8327ac06127Sopenharmony_ci }; 8337ac06127Sopenharmony_ci 8347ac06127Sopenharmony_ci let mut len = 0; 8357ac06127Sopenharmony_ci let mut empty = true; 8367ac06127Sopenharmony_ci for b in input.bytes() { 8377ac06127Sopenharmony_ci match b { 8387ac06127Sopenharmony_ci b'0'..=b'9' => { 8397ac06127Sopenharmony_ci let digit = (b - b'0') as u64; 8407ac06127Sopenharmony_ci if digit >= base { 8417ac06127Sopenharmony_ci return Err(Reject); 8427ac06127Sopenharmony_ci } 8437ac06127Sopenharmony_ci } 8447ac06127Sopenharmony_ci b'a'..=b'f' => { 8457ac06127Sopenharmony_ci let digit = 10 + (b - b'a') as u64; 8467ac06127Sopenharmony_ci if digit >= base { 8477ac06127Sopenharmony_ci break; 8487ac06127Sopenharmony_ci } 8497ac06127Sopenharmony_ci } 8507ac06127Sopenharmony_ci b'A'..=b'F' => { 8517ac06127Sopenharmony_ci let digit = 10 + (b - b'A') as u64; 8527ac06127Sopenharmony_ci if digit >= base { 8537ac06127Sopenharmony_ci break; 8547ac06127Sopenharmony_ci } 8557ac06127Sopenharmony_ci } 8567ac06127Sopenharmony_ci b'_' => { 8577ac06127Sopenharmony_ci if empty && base == 10 { 8587ac06127Sopenharmony_ci return Err(Reject); 8597ac06127Sopenharmony_ci } 8607ac06127Sopenharmony_ci len += 1; 8617ac06127Sopenharmony_ci continue; 8627ac06127Sopenharmony_ci } 8637ac06127Sopenharmony_ci _ => break, 8647ac06127Sopenharmony_ci }; 8657ac06127Sopenharmony_ci len += 1; 8667ac06127Sopenharmony_ci empty = false; 8677ac06127Sopenharmony_ci } 8687ac06127Sopenharmony_ci if empty { 8697ac06127Sopenharmony_ci Err(Reject) 8707ac06127Sopenharmony_ci } else { 8717ac06127Sopenharmony_ci Ok(input.advance(len)) 8727ac06127Sopenharmony_ci } 8737ac06127Sopenharmony_ci} 8747ac06127Sopenharmony_ci 8757ac06127Sopenharmony_cifn punct(input: Cursor) -> PResult<Punct> { 8767ac06127Sopenharmony_ci let (rest, ch) = punct_char(input)?; 8777ac06127Sopenharmony_ci if ch == '\'' { 8787ac06127Sopenharmony_ci if ident_any(rest)?.0.starts_with_char('\'') { 8797ac06127Sopenharmony_ci Err(Reject) 8807ac06127Sopenharmony_ci } else { 8817ac06127Sopenharmony_ci Ok((rest, Punct::new('\'', Spacing::Joint))) 8827ac06127Sopenharmony_ci } 8837ac06127Sopenharmony_ci } else { 8847ac06127Sopenharmony_ci let kind = match punct_char(rest) { 8857ac06127Sopenharmony_ci Ok(_) => Spacing::Joint, 8867ac06127Sopenharmony_ci Err(Reject) => Spacing::Alone, 8877ac06127Sopenharmony_ci }; 8887ac06127Sopenharmony_ci Ok((rest, Punct::new(ch, kind))) 8897ac06127Sopenharmony_ci } 8907ac06127Sopenharmony_ci} 8917ac06127Sopenharmony_ci 8927ac06127Sopenharmony_cifn punct_char(input: Cursor) -> PResult<char> { 8937ac06127Sopenharmony_ci if input.starts_with("//") || input.starts_with("/*") { 8947ac06127Sopenharmony_ci // Do not accept `/` of a comment as a punct. 8957ac06127Sopenharmony_ci return Err(Reject); 8967ac06127Sopenharmony_ci } 8977ac06127Sopenharmony_ci 8987ac06127Sopenharmony_ci let mut chars = input.chars(); 8997ac06127Sopenharmony_ci let first = match chars.next() { 9007ac06127Sopenharmony_ci Some(ch) => ch, 9017ac06127Sopenharmony_ci None => { 9027ac06127Sopenharmony_ci return Err(Reject); 9037ac06127Sopenharmony_ci } 9047ac06127Sopenharmony_ci }; 9057ac06127Sopenharmony_ci let recognized = "~!@#$%^&*-=+|;:,<.>/?'"; 9067ac06127Sopenharmony_ci if recognized.contains(first) { 9077ac06127Sopenharmony_ci Ok((input.advance(first.len_utf8()), first)) 9087ac06127Sopenharmony_ci } else { 9097ac06127Sopenharmony_ci Err(Reject) 9107ac06127Sopenharmony_ci } 9117ac06127Sopenharmony_ci} 9127ac06127Sopenharmony_ci 9137ac06127Sopenharmony_cifn doc_comment<'a>(input: Cursor<'a>, trees: &mut TokenStreamBuilder) -> PResult<'a, ()> { 9147ac06127Sopenharmony_ci #[cfg(span_locations)] 9157ac06127Sopenharmony_ci let lo = input.off; 9167ac06127Sopenharmony_ci let (rest, (comment, inner)) = doc_comment_contents(input)?; 9177ac06127Sopenharmony_ci let fallback_span = Span { 9187ac06127Sopenharmony_ci #[cfg(span_locations)] 9197ac06127Sopenharmony_ci lo, 9207ac06127Sopenharmony_ci #[cfg(span_locations)] 9217ac06127Sopenharmony_ci hi: rest.off, 9227ac06127Sopenharmony_ci }; 9237ac06127Sopenharmony_ci let span = crate::Span::_new_fallback(fallback_span); 9247ac06127Sopenharmony_ci 9257ac06127Sopenharmony_ci let mut scan_for_bare_cr = comment; 9267ac06127Sopenharmony_ci while let Some(cr) = scan_for_bare_cr.find('\r') { 9277ac06127Sopenharmony_ci let rest = &scan_for_bare_cr[cr + 1..]; 9287ac06127Sopenharmony_ci if !rest.starts_with('\n') { 9297ac06127Sopenharmony_ci return Err(Reject); 9307ac06127Sopenharmony_ci } 9317ac06127Sopenharmony_ci scan_for_bare_cr = rest; 9327ac06127Sopenharmony_ci } 9337ac06127Sopenharmony_ci 9347ac06127Sopenharmony_ci let mut pound = Punct::new('#', Spacing::Alone); 9357ac06127Sopenharmony_ci pound.set_span(span); 9367ac06127Sopenharmony_ci trees.push_token_from_parser(TokenTree::Punct(pound)); 9377ac06127Sopenharmony_ci 9387ac06127Sopenharmony_ci if inner { 9397ac06127Sopenharmony_ci let mut bang = Punct::new('!', Spacing::Alone); 9407ac06127Sopenharmony_ci bang.set_span(span); 9417ac06127Sopenharmony_ci trees.push_token_from_parser(TokenTree::Punct(bang)); 9427ac06127Sopenharmony_ci } 9437ac06127Sopenharmony_ci 9447ac06127Sopenharmony_ci let doc_ident = crate::Ident::_new(crate::imp::Ident::new_unchecked("doc", fallback_span)); 9457ac06127Sopenharmony_ci let mut equal = Punct::new('=', Spacing::Alone); 9467ac06127Sopenharmony_ci equal.set_span(span); 9477ac06127Sopenharmony_ci let mut literal = crate::Literal::string(comment); 9487ac06127Sopenharmony_ci literal.set_span(span); 9497ac06127Sopenharmony_ci let mut bracketed = TokenStreamBuilder::with_capacity(3); 9507ac06127Sopenharmony_ci bracketed.push_token_from_parser(TokenTree::Ident(doc_ident)); 9517ac06127Sopenharmony_ci bracketed.push_token_from_parser(TokenTree::Punct(equal)); 9527ac06127Sopenharmony_ci bracketed.push_token_from_parser(TokenTree::Literal(literal)); 9537ac06127Sopenharmony_ci let group = Group::new(Delimiter::Bracket, bracketed.build()); 9547ac06127Sopenharmony_ci let mut group = crate::Group::_new_fallback(group); 9557ac06127Sopenharmony_ci group.set_span(span); 9567ac06127Sopenharmony_ci trees.push_token_from_parser(TokenTree::Group(group)); 9577ac06127Sopenharmony_ci 9587ac06127Sopenharmony_ci Ok((rest, ())) 9597ac06127Sopenharmony_ci} 9607ac06127Sopenharmony_ci 9617ac06127Sopenharmony_cifn doc_comment_contents(input: Cursor) -> PResult<(&str, bool)> { 9627ac06127Sopenharmony_ci if input.starts_with("//!") { 9637ac06127Sopenharmony_ci let input = input.advance(3); 9647ac06127Sopenharmony_ci let (input, s) = take_until_newline_or_eof(input); 9657ac06127Sopenharmony_ci Ok((input, (s, true))) 9667ac06127Sopenharmony_ci } else if input.starts_with("/*!") { 9677ac06127Sopenharmony_ci let (input, s) = block_comment(input)?; 9687ac06127Sopenharmony_ci Ok((input, (&s[3..s.len() - 2], true))) 9697ac06127Sopenharmony_ci } else if input.starts_with("///") { 9707ac06127Sopenharmony_ci let input = input.advance(3); 9717ac06127Sopenharmony_ci if input.starts_with_char('/') { 9727ac06127Sopenharmony_ci return Err(Reject); 9737ac06127Sopenharmony_ci } 9747ac06127Sopenharmony_ci let (input, s) = take_until_newline_or_eof(input); 9757ac06127Sopenharmony_ci Ok((input, (s, false))) 9767ac06127Sopenharmony_ci } else if input.starts_with("/**") && !input.rest[3..].starts_with('*') { 9777ac06127Sopenharmony_ci let (input, s) = block_comment(input)?; 9787ac06127Sopenharmony_ci Ok((input, (&s[3..s.len() - 2], false))) 9797ac06127Sopenharmony_ci } else { 9807ac06127Sopenharmony_ci Err(Reject) 9817ac06127Sopenharmony_ci } 9827ac06127Sopenharmony_ci} 9837ac06127Sopenharmony_ci 9847ac06127Sopenharmony_cifn take_until_newline_or_eof(input: Cursor) -> (Cursor, &str) { 9857ac06127Sopenharmony_ci let chars = input.char_indices(); 9867ac06127Sopenharmony_ci 9877ac06127Sopenharmony_ci for (i, ch) in chars { 9887ac06127Sopenharmony_ci if ch == '\n' { 9897ac06127Sopenharmony_ci return (input.advance(i), &input.rest[..i]); 9907ac06127Sopenharmony_ci } else if ch == '\r' && input.rest[i + 1..].starts_with('\n') { 9917ac06127Sopenharmony_ci return (input.advance(i + 1), &input.rest[..i]); 9927ac06127Sopenharmony_ci } 9937ac06127Sopenharmony_ci } 9947ac06127Sopenharmony_ci 9957ac06127Sopenharmony_ci (input.advance(input.len()), input.rest) 9967ac06127Sopenharmony_ci} 997