use crate::{Base, LiteralKind};
use super::CursorIter;
pub fn rustc_is_id_start(c: char) -> bool {
c == '_' || unicode_xid::UnicodeXID::is_xid_start(c)
}
pub fn rustc_is_id_continue(c: char) -> bool {
unicode_xid::UnicodeXID::is_xid_continue(c)
}
impl<I> CursorIter<I>
where
I: Iterator<Item = char>,
{
pub(super) fn number(&mut self, first_digit: char) -> LiteralKind {
use LiteralKind::*;
let mut base = Base::Decimal;
match first_digit {
'0' => {
match self.peek_nth(0) {
Some(ch) if ch == &'b' => {
self.next();
if !self.eat_decimal_digits() {
return Int {
base: Base::Decimal,
is_empty: true,
};
}
}
Some(ch) if ch == &'o' => {
base = Base::Octal;
self.next();
if !self.eat_decimal_digits() {
return Int {
base,
is_empty: true,
};
}
}
Some(ch) if ch == &'x' => {
base = Base::Hexadecimal;
self.next();
if !self.eat_hexadecimal_digits() {
return Int {
base,
is_empty: true,
};
}
}
Some(ch) if ch.is_ascii_digit() || ch == &'_' => {
self.eat_decimal_digits();
}
Some(ch) if ['.', 'e', 'E'].contains(ch) => {}
_ => {
return Int {
base: Base::Decimal,
is_empty: false,
}
}
}
}
_ => {
self.eat_decimal_digits();
}
};
match self.peek_nth(0).cloned() {
Some(ch) if ['e', 'E'].contains(&ch) => {
self.next();
let empty_exponent = !self.eat_float_exponent();
Double {
base,
empty_exponent,
}
}
_ => Int {
base,
is_empty: false,
},
}
}
fn eat_decimal_digits(&mut self) -> bool {
let mut has_digits = false;
while self
.peeking_next(|ch| match ch {
&'_' => true,
'0'..='9' => {
has_digits = true;
true
}
_ => false,
})
.is_some()
{}
has_digits
}
fn eat_hexadecimal_digits(&mut self) -> bool {
let mut has_digits = false;
while self
.peeking_next(|ch| match ch {
&'_' => true,
'0'..='9' | 'a'..='f' | 'A'..='F' => {
has_digits = true;
true
}
_ => false,
})
.is_some()
{}
has_digits
}
fn eat_float_exponent(&mut self) -> bool {
let _ = self.peeking_next(|ch| ['-', '+'].contains(ch));
self.eat_decimal_digits()
}
}
impl<I> CursorIter<I>
where
I: Iterator<Item = char>,
{
pub(super) fn parse_double_quoted_string(&mut self) -> LiteralKind {
let is_terminated = self.double_quoted_string();
LiteralKind::Str { is_terminated }
}
fn double_quoted_string(&mut self) -> bool {
while let Some(c) = self.next() {
match c {
'"' => {
return true;
}
'\\' if self
.peek_nth(0)
.map(|next_ch| ['\\', '"'].contains(next_ch))
.unwrap_or(false) =>
{
self.next();
}
_ => (),
}
}
false
}
}
impl<I> CursorIter<I>
where
I: Iterator<Item = char>,
{
pub(super) fn parse_single_quote_string(&mut self) -> LiteralKind {
let is_terminated = self.single_quoted_string();
LiteralKind::Str { is_terminated }
}
fn single_quoted_string(&mut self) -> bool {
while let Some(ch) = self.peek_nth(0).cloned() {
match ch {
'\'' => {
self.next();
return true;
}
'\n' if self.peek_nth(1).is_some_and(|next_ch| next_ch != &'\'') => break,
'\\' => {
self.next();
self.next();
}
_ => {
self.next();
}
}
}
false
}
}