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