// SPDX-License-Identifier: Apache-2.0 OR MIT
use crate::fallback::{
self, is_ident_continue, is_ident_start, Group, Ident, LexError, Literal, Span, TokenStream,
TokenStreamBuilder,
};
use crate::{Delimiter, Punct, Spacing, TokenTree};
use core::char;
use core::str::{Bytes, CharIndices, Chars};
#[derive(Copy, Clone, Eq, PartialEq)]
pub(crate) struct Cursor<'a> {
pub(crate) rest: &'a str,
#[cfg(span_locations)]
pub(crate) off: u32,
}
impl<'a> Cursor<'a> {
pub(crate) fn advance(&self, bytes: usize) -> Cursor<'a> {
let (_front, rest) = self.rest.split_at(bytes);
Cursor {
rest,
#[cfg(span_locations)]
off: self.off + _front.chars().count() as u32,
}
}
pub(crate) fn starts_with(&self, s: &str) -> bool {
self.rest.starts_with(s)
}
pub(crate) fn starts_with_char(&self, ch: char) -> bool {
self.rest.starts_with(ch)
}
pub(crate) fn starts_with_fn<Pattern>(&self, f: Pattern) -> bool
where
Pattern: FnMut(char) -> bool,
{
self.rest.starts_with(f)
}
pub(crate) fn is_empty(&self) -> bool {
self.rest.is_empty()
}
fn len(&self) -> usize {
self.rest.len()
}
fn as_bytes(&self) -> &'a [u8] {
self.rest.as_bytes()
}
fn bytes(&self) -> Bytes<'a> {
self.rest.bytes()
}
fn chars(&self) -> Chars<'a> {
self.rest.chars()
}
fn char_indices(&self) -> CharIndices<'a> {
self.rest.char_indices()
}
fn parse(&self, tag: &str) -> Result<Cursor<'a>, Reject> {
if self.starts_with(tag) {
Ok(self.advance(tag.len()))
} else {
Err(Reject)
}
}
}
pub(crate) struct Reject;
type PResult<'a, O> = Result<(Cursor<'a>, O), Reject>;
fn skip_whitespace(input: Cursor) -> Cursor {
let mut s = input;
while !s.is_empty() {
let byte = s.as_bytes()[0];
if byte == b'/' {
if s.starts_with("//")
&& (!s.starts_with("///") || s.starts_with("////"))
&& !s.starts_with("//!")
{
let (cursor, _) = take_until_newline_or_eof(s);
s = cursor;
continue;
} else if s.starts_with("/**/") {
s = s.advance(4);
continue;
} else if s.starts_with("/*")
&& (!s.starts_with("/**") || s.starts_with("/***"))
&& !s.starts_with("/*!")
{
match block_comment(s) {
Ok((rest, _)) => {
s = rest;
continue;
}
Err(Reject) => return