1#![deny(unstable_features)]
26#[cfg(test)]
29mod tests;
30
31use std::str::Chars;
32
33use LiteralKind::*;
34use TokenKind::*;
35pub use unicode_ident::UNICODE_VERSION;
36use unicode_properties::UnicodeEmoji;
37
38const _: () = {
40 let properties = unicode_properties::UNICODE_VERSION;
41 let ident = unicode_ident::UNICODE_VERSION;
42
43 if properties.0 != ident.0 as u64
44 || properties.1 != ident.1 as u64
45 || properties.2 != ident.2 as u64
46 {
47 {
::core::panicking::panic_fmt(format_args!("unicode-properties and unicode-ident must use the same Unicode version, `unicode_properties::UNICODE_VERSION` and `unicode_ident::UNICODE_VERSION` are different."));
};panic!(
48 "unicode-properties and unicode-ident must use the same Unicode version, \
49 `unicode_properties::UNICODE_VERSION` and `unicode_ident::UNICODE_VERSION` are \
50 different."
51 );
52 }
53};
54
55#[derive(#[automatically_derived]impl ::core::fmt::Debug for Token {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Token kind len", &self.kind, &&self.len)
}
}Debug)]
59pub struct Token {
60 pub kind: TokenKind,
61 pub len: u32,
62}
63
64impl Token {
65 fn new(kind: TokenKind, len: u32) -> Token {
66 Token { kind, len }
67 }
68}
69
70#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for TokenKind {
}
#[automatically_derived]impl ::core::clone::Clone for TokenKind {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Option<DocStyle>>;
let _: ::core::clone::AssertParamIsClone<Option<DocStyle>>;
let _: ::core::clone::AssertParamIsClone<bool>;
let _: ::core::clone::AssertParamIsClone<LiteralKind>;
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}Clone, #[automatically_derived]impl ::core::marker::Copy for TokenKind { }Copy, #[automatically_derived]impl ::core::fmt::Debug for TokenKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::LineComment { doc_style: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"LineComment doc_style", &__self_0),
Self::BlockComment { doc_style: __self_0, terminated: __self_1 }
=>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"BlockComment doc_style terminated", __self_0, &__self_1),
Self::Whitespace =>
::core::fmt::Formatter::write_str(f, "Whitespace"),
Self::Frontmatter {
has_invalid_preceding_whitespace: __self_0,
invalid_infostring: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Frontmatter has_invalid_preceding_whitespace invalid_infostring",
__self_0, &__self_1),
Self::Ident => ::core::fmt::Formatter::write_str(f, "Ident"),
Self::InvalidIdent =>
::core::fmt::Formatter::write_str(f, "InvalidIdent"),
Self::RawIdent =>
::core::fmt::Formatter::write_str(f, "RawIdent"),
Self::ForcedKeywordIdent =>
::core::fmt::Formatter::write_str(f, "ForcedKeywordIdent"),
Self::UnknownPrefix =>
::core::fmt::Formatter::write_str(f, "UnknownPrefix"),
Self::UnknownPrefixLifetime =>
::core::fmt::Formatter::write_str(f, "UnknownPrefixLifetime"),
Self::RawLifetime =>
::core::fmt::Formatter::write_str(f, "RawLifetime"),
Self::GuardedStrPrefix =>
::core::fmt::Formatter::write_str(f, "GuardedStrPrefix"),
Self::Literal { kind: __self_0, suffix_start: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Literal kind suffix_start", __self_0, &__self_1),
Self::Lifetime { starts_with_number: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"Lifetime starts_with_number", &__self_0),
Self::Semi => ::core::fmt::Formatter::write_str(f, "Semi"),
Self::Comma => ::core::fmt::Formatter::write_str(f, "Comma"),
Self::Dot => ::core::fmt::Formatter::write_str(f, "Dot"),
Self::OpenParen =>
::core::fmt::Formatter::write_str(f, "OpenParen"),
Self::CloseParen =>
::core::fmt::Formatter::write_str(f, "CloseParen"),
Self::OpenBrace =>
::core::fmt::Formatter::write_str(f, "OpenBrace"),
Self::CloseBrace =>
::core::fmt::Formatter::write_str(f, "CloseBrace"),
Self::OpenBracket =>
::core::fmt::Formatter::write_str(f, "OpenBracket"),
Self::CloseBracket =>
::core::fmt::Formatter::write_str(f, "CloseBracket"),
Self::At => ::core::fmt::Formatter::write_str(f, "At"),
Self::Pound => ::core::fmt::Formatter::write_str(f, "Pound"),
Self::Tilde => ::core::fmt::Formatter::write_str(f, "Tilde"),
Self::Question =>
::core::fmt::Formatter::write_str(f, "Question"),
Self::Colon => ::core::fmt::Formatter::write_str(f, "Colon"),
Self::Dollar => ::core::fmt::Formatter::write_str(f, "Dollar"),
Self::Eq => ::core::fmt::Formatter::write_str(f, "Eq"),
Self::Bang => ::core::fmt::Formatter::write_str(f, "Bang"),
Self::Lt => ::core::fmt::Formatter::write_str(f, "Lt"),
Self::Gt => ::core::fmt::Formatter::write_str(f, "Gt"),
Self::Minus => ::core::fmt::Formatter::write_str(f, "Minus"),
Self::And => ::core::fmt::Formatter::write_str(f, "And"),
Self::Or => ::core::fmt::Formatter::write_str(f, "Or"),
Self::Plus => ::core::fmt::Formatter::write_str(f, "Plus"),
Self::Star => ::core::fmt::Formatter::write_str(f, "Star"),
Self::Slash => ::core::fmt::Formatter::write_str(f, "Slash"),
Self::Caret => ::core::fmt::Formatter::write_str(f, "Caret"),
Self::Percent => ::core::fmt::Formatter::write_str(f, "Percent"),
Self::Unknown => ::core::fmt::Formatter::write_str(f, "Unknown"),
Self::Eof => ::core::fmt::Formatter::write_str(f, "Eof"),
}
}
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for TokenKind
{
}
#[automatically_derived]impl ::core::cmp::PartialEq for TokenKind {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other) &&
match (self, other) {
(Self::LineComment { doc_style: __self_0 },
Self::LineComment { doc_style: __arg1_0 }) =>
__self_0 == __arg1_0,
(Self::BlockComment {
doc_style: __self_0, terminated: __self_1 },
Self::BlockComment {
doc_style: __arg1_0, terminated: __arg1_1 }) =>
__self_1 == __arg1_1 && __self_0 == __arg1_0,
(Self::Frontmatter {
has_invalid_preceding_whitespace: __self_0,
invalid_infostring: __self_1 }, Self::Frontmatter {
has_invalid_preceding_whitespace: __arg1_0,
invalid_infostring: __arg1_1 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(Self::Literal { kind: __self_0, suffix_start: __self_1 },
Self::Literal { kind: __arg1_0, suffix_start: __arg1_1 }) =>
__self_1 == __arg1_1 && __self_0 == __arg1_0,
(Self::Lifetime { starts_with_number: __self_0 },
Self::Lifetime { starts_with_number: __arg1_0 }) =>
__self_0 == __arg1_0,
_ => true,
}
}
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for TokenKind {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Option<DocStyle>>;
let _: ::core::cmp::AssertParamIsEq<Option<DocStyle>>;
let _: ::core::cmp::AssertParamIsEq<bool>;
let _: ::core::cmp::AssertParamIsEq<LiteralKind>;
let _: ::core::cmp::AssertParamIsEq<u32>;
}
}Eq)]
72pub enum TokenKind {
73 LineComment {
75 doc_style: Option<DocStyle>,
76 },
77
78 BlockComment {
83 doc_style: Option<DocStyle>,
84 terminated: bool,
85 },
86
87 Whitespace,
89
90 Frontmatter {
91 has_invalid_preceding_whitespace: bool,
92 invalid_infostring: bool,
93 },
94
95 Ident,
97
98 InvalidIdent,
100
101 RawIdent,
103
104 ForcedKeywordIdent,
106
107 UnknownPrefix,
117
118 UnknownPrefixLifetime,
123
124 RawLifetime,
127
128 GuardedStrPrefix,
133
134 Literal {
140 kind: LiteralKind,
141 suffix_start: u32,
142 },
143
144 Lifetime {
146 starts_with_number: bool,
150 },
151
152 Semi,
154 Comma,
156 Dot,
158 OpenParen,
160 CloseParen,
162 OpenBrace,
164 CloseBrace,
166 OpenBracket,
168 CloseBracket,
170 At,
172 Pound,
174 Tilde,
176 Question,
178 Colon,
180 Dollar,
182 Eq,
184 Bang,
186 Lt,
188 Gt,
190 Minus,
192 And,
194 Or,
196 Plus,
198 Star,
200 Slash,
202 Caret,
204 Percent,
206
207 Unknown,
209
210 Eof,
212}
213
214#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for DocStyle {
}
#[automatically_derived]impl ::core::clone::Clone for DocStyle {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for DocStyle { }Copy, #[automatically_derived]impl ::core::fmt::Debug for DocStyle {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
DocStyle::Outer => "Outer",
DocStyle::Inner => "Inner",
})
}
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for DocStyle
{
}
#[automatically_derived]impl ::core::cmp::PartialEq for DocStyle {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for DocStyle { }Eq)]
215pub enum DocStyle {
216 Outer,
217 Inner,
218}
219
220#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for LiteralKind {
}
#[automatically_derived]impl ::core::clone::Clone for LiteralKind {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<Base>;
let _: ::core::clone::AssertParamIsClone<bool>;
let _: ::core::clone::AssertParamIsClone<Option<u8>>;
let _: ::core::clone::AssertParamIsClone<Option<u8>>;
let _: ::core::clone::AssertParamIsClone<Option<u8>>;
*self
}
}Clone, #[automatically_derived]impl ::core::marker::Copy for LiteralKind { }Copy, #[automatically_derived]impl ::core::fmt::Debug for LiteralKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::Int { base: __self_0, empty_int: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Int base empty_int", __self_0, &__self_1),
Self::Float { base: __self_0, empty_exponent: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Float base empty_exponent", __self_0, &__self_1),
Self::Char { terminated: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"Char terminated", &__self_0),
Self::Byte { terminated: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"Byte terminated", &__self_0),
Self::Str { terminated: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"Str terminated", &__self_0),
Self::ByteStr { terminated: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"ByteStr terminated", &__self_0),
Self::CStr { terminated: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"CStr terminated", &__self_0),
Self::RawStr { n_hashes: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"RawStr n_hashes", &__self_0),
Self::RawByteStr { n_hashes: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"RawByteStr n_hashes", &__self_0),
Self::RawCStr { n_hashes: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"RawCStr n_hashes", &__self_0),
}
}
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
LiteralKind {
}
#[automatically_derived]impl ::core::cmp::PartialEq for LiteralKind {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other) &&
match (self, other) {
(Self::Int { base: __self_0, empty_int: __self_1 },
Self::Int { base: __arg1_0, empty_int: __arg1_1 }) =>
__self_1 == __arg1_1 && __self_0 == __arg1_0,
(Self::Float { base: __self_0, empty_exponent: __self_1 },
Self::Float { base: __arg1_0, empty_exponent: __arg1_1 }) =>
__self_1 == __arg1_1 && __self_0 == __arg1_0,
(Self::Char { terminated: __self_0 }, Self::Char {
terminated: __arg1_0 }) => __self_0 == __arg1_0,
(Self::Byte { terminated: __self_0 }, Self::Byte {
terminated: __arg1_0 }) => __self_0 == __arg1_0,
(Self::Str { terminated: __self_0 }, Self::Str {
terminated: __arg1_0 }) => __self_0 == __arg1_0,
(Self::ByteStr { terminated: __self_0 }, Self::ByteStr {
terminated: __arg1_0 }) => __self_0 == __arg1_0,
(Self::CStr { terminated: __self_0 }, Self::CStr {
terminated: __arg1_0 }) => __self_0 == __arg1_0,
(Self::RawStr { n_hashes: __self_0 }, Self::RawStr {
n_hashes: __arg1_0 }) => __self_0 == __arg1_0,
(Self::RawByteStr { n_hashes: __self_0 }, Self::RawByteStr {
n_hashes: __arg1_0 }) => __self_0 == __arg1_0,
(Self::RawCStr { n_hashes: __self_0 }, Self::RawCStr {
n_hashes: __arg1_0 }) => __self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for LiteralKind {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Base>;
let _: ::core::cmp::AssertParamIsEq<bool>;
let _: ::core::cmp::AssertParamIsEq<Option<u8>>;
let _: ::core::cmp::AssertParamIsEq<Option<u8>>;
let _: ::core::cmp::AssertParamIsEq<Option<u8>>;
}
}Eq, #[automatically_derived]impl ::core::cmp::PartialOrd for LiteralKind {
#[inline]
fn partial_cmp(&self, other: &Self)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for LiteralKind {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
match (self, other) {
(Self::Int { base: __self_0, empty_int: __self_1 }, Self::Int {
base: __arg1_0, empty_int: __arg1_1 }) =>
match ::core::cmp::Ord::cmp(__self_0, __arg1_0) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(__self_1, __arg1_1),
cmp => cmp,
},
(Self::Float { base: __self_0, empty_exponent: __self_1 },
Self::Float { base: __arg1_0, empty_exponent: __arg1_1 }) =>
match ::core::cmp::Ord::cmp(__self_0, __arg1_0) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(__self_1, __arg1_1),
cmp => cmp,
},
(Self::Char { terminated: __self_0 }, Self::Char {
terminated: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Self::Byte { terminated: __self_0 }, Self::Byte {
terminated: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Self::Str { terminated: __self_0 }, Self::Str {
terminated: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Self::ByteStr { terminated: __self_0 }, Self::ByteStr {
terminated: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Self::CStr { terminated: __self_0 }, Self::CStr {
terminated: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Self::RawStr { n_hashes: __self_0 }, Self::RawStr {
n_hashes: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Self::RawByteStr { n_hashes: __self_0 }, Self::RawByteStr {
n_hashes: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Self::RawCStr { n_hashes: __self_0 }, Self::RawCStr {
n_hashes: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ =>
::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self),
&::core::intrinsics::discriminant_value(other)),
}
}
}Ord)]
227pub enum LiteralKind {
228 Int { base: Base, empty_int: bool },
230 Float { base: Base, empty_exponent: bool },
232 Char { terminated: bool },
234 Byte { terminated: bool },
236 Str { terminated: bool },
238 ByteStr { terminated: bool },
240 CStr { terminated: bool },
242 RawStr { n_hashes: Option<u8> },
245 RawByteStr { n_hashes: Option<u8> },
248 RawCStr { n_hashes: Option<u8> },
250}
251
252#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for GuardedStr {
}
#[automatically_derived]impl ::core::clone::Clone for GuardedStr {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<u32>;
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}Clone, #[automatically_derived]impl ::core::marker::Copy for GuardedStr { }Copy, #[automatically_derived]impl ::core::fmt::Debug for GuardedStr {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"GuardedStr n_hashes terminated token_len", &self.n_hashes,
&self.terminated, &&self.token_len)
}
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
GuardedStr {
}
#[automatically_derived]impl ::core::cmp::PartialEq for GuardedStr {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.n_hashes == other.n_hashes && self.terminated == other.terminated
&& self.token_len == other.token_len
}
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for GuardedStr {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u32>;
let _: ::core::cmp::AssertParamIsEq<bool>;
}
}Eq, #[automatically_derived]impl ::core::cmp::PartialOrd for GuardedStr {
#[inline]
fn partial_cmp(&self, other: &Self)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for GuardedStr {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.n_hashes, &other.n_hashes) {
::core::cmp::Ordering::Equal =>
match ::core::cmp::Ord::cmp(&self.terminated,
&other.terminated) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.token_len, &other.token_len),
cmp => cmp,
},
cmp => cmp,
}
}
}Ord)]
257pub struct GuardedStr {
258 pub n_hashes: u32,
259 pub terminated: bool,
260 pub token_len: u32,
261}
262
263#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for RawStrError {
}
#[automatically_derived]impl ::core::clone::Clone for RawStrError {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<char>;
let _: ::core::clone::AssertParamIsClone<u32>;
let _: ::core::clone::AssertParamIsClone<Option<u32>>;
*self
}
}Clone, #[automatically_derived]impl ::core::marker::Copy for RawStrError { }Copy, #[automatically_derived]impl ::core::fmt::Debug for RawStrError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Self::InvalidStarter { bad_char: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"InvalidStarter bad_char", &__self_0),
Self::NoTerminator {
expected: __self_0,
found: __self_1,
possible_terminator_offset: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"NoTerminator expected found possible_terminator_offset",
__self_0, __self_1, &__self_2),
Self::TooManyDelimiters { found: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"TooManyDelimiters found", &__self_0),
}
}
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
RawStrError {
}
#[automatically_derived]impl ::core::cmp::PartialEq for RawStrError {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other) &&
match (self, other) {
(Self::InvalidStarter { bad_char: __self_0 },
Self::InvalidStarter { bad_char: __arg1_0 }) =>
__self_0 == __arg1_0,
(Self::NoTerminator {
expected: __self_0,
found: __self_1,
possible_terminator_offset: __self_2 }, Self::NoTerminator {
expected: __arg1_0,
found: __arg1_1,
possible_terminator_offset: __arg1_2 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1 &&
__self_2 == __arg1_2,
(Self::TooManyDelimiters { found: __self_0 },
Self::TooManyDelimiters { found: __arg1_0 }) =>
__self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for RawStrError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<char>;
let _: ::core::cmp::AssertParamIsEq<u32>;
let _: ::core::cmp::AssertParamIsEq<Option<u32>>;
}
}Eq, #[automatically_derived]impl ::core::cmp::PartialOrd for RawStrError {
#[inline]
fn partial_cmp(&self, other: &Self)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for RawStrError {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
match (self, other) {
(Self::InvalidStarter { bad_char: __self_0 },
Self::InvalidStarter { bad_char: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(Self::NoTerminator {
expected: __self_0,
found: __self_1,
possible_terminator_offset: __self_2 }, Self::NoTerminator {
expected: __arg1_0,
found: __arg1_1,
possible_terminator_offset: __arg1_2 }) =>
match ::core::cmp::Ord::cmp(__self_0, __arg1_0) {
::core::cmp::Ordering::Equal =>
match ::core::cmp::Ord::cmp(__self_1, __arg1_1) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(__self_2, __arg1_2),
cmp => cmp,
},
cmp => cmp,
},
(Self::TooManyDelimiters { found: __self_0 },
Self::TooManyDelimiters { found: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ =>
::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self),
&::core::intrinsics::discriminant_value(other)),
}
}
}Ord)]
264pub enum RawStrError {
265 InvalidStarter { bad_char: char },
267 NoTerminator { expected: u32, found: u32, possible_terminator_offset: Option<u32> },
271 TooManyDelimiters { found: u32 },
273}
274
275#[derive(#[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for Base {
}
#[automatically_derived]impl ::core::clone::Clone for Base {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for Base { }Copy, #[automatically_derived]impl ::core::fmt::Debug for Base {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Base::Binary => "Binary",
Base::Octal => "Octal",
Base::Decimal => "Decimal",
Base::Hexadecimal => "Hexadecimal",
})
}
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for Base { }
#[automatically_derived]impl ::core::cmp::PartialEq for Base {
#[inline]
fn eq(&self, other: &Self) -> bool {
::core::intrinsics::discriminant_value(self) ==
::core::intrinsics::discriminant_value(other)
}
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for Base { }Eq, #[automatically_derived]impl ::core::cmp::PartialOrd for Base {
#[inline]
fn partial_cmp(&self, other: &Self)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for Base {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self),
&::core::intrinsics::discriminant_value(other))
}
}Ord)]
277pub enum Base {
278 Binary = 2,
280 Octal = 8,
282 Decimal = 10,
284 Hexadecimal = 16,
286}
287
288pub fn strip_shebang(input: &str) -> Option<usize> {
291 if let Some(input_tail) = input.strip_prefix("#!") {
295 let next_non_whitespace_token =
298 tokenize(input_tail, FrontmatterAllowed::No).map(|tok| tok.kind).find(|tok| {
299 !#[allow(non_exhaustive_omitted_patterns)] match tok {
TokenKind::Whitespace | TokenKind::LineComment { doc_style: None } |
TokenKind::BlockComment { doc_style: None, .. } => true,
_ => false,
}matches!(
300 tok,
301 TokenKind::Whitespace
302 | TokenKind::LineComment { doc_style: None }
303 | TokenKind::BlockComment { doc_style: None, .. }
304 )
305 });
306 if next_non_whitespace_token != Some(TokenKind::OpenBracket) {
307 return Some(2 + input_tail.lines().next().unwrap_or_default().len());
309 }
310 }
311 None
312}
313
314#[inline]
317pub fn validate_raw_str(input: &str, prefix_len: u32) -> Result<(), RawStrError> {
318 if true {
if !!input.is_empty() {
::core::panicking::panic("assertion failed: !input.is_empty()")
};
};debug_assert!(!input.is_empty());
319 let mut cursor = Cursor::new(input, FrontmatterAllowed::No);
320 for _ in 0..prefix_len {
322 cursor.bump().unwrap();
323 }
324 cursor.raw_double_quoted_string(prefix_len).map(|_| ())
325}
326
327pub fn tokenize(
334 input: &str,
335 frontmatter_allowed: FrontmatterAllowed,
336) -> impl Iterator<Item = Token> {
337 let mut cursor = Cursor::new(input, frontmatter_allowed);
338 std::iter::from_fn(move || {
339 let token = cursor.advance_token();
340 if token.kind != TokenKind::Eof { Some(token) } else { None }
341 })
342}
343
344pub fn is_whitespace(c: char) -> bool {
348 #[allow(non_exhaustive_omitted_patterns)] match c {
'\u{000A}' | '\u{000B}' | '\u{000C}' | '\u{000D}' | '\u{0085}' |
'\u{2028}' | '\u{2029}' | '\u{200E}' | '\u{200F}' | '\u{0009}' |
'\u{0020}' => true,
_ => false,
}matches!(
354 c,
355 | '\u{000A}' | '\u{000B}' | '\u{000C}' | '\u{000D}' | '\u{0085}' | '\u{2028}' | '\u{2029}' | '\u{200E}' | '\u{200F}' | '\u{0009}' | '\u{0020}' )
372}
373
374pub fn is_horizontal_whitespace(c: char) -> bool {
376 #[allow(non_exhaustive_omitted_patterns)] match c {
'\u{0009}' | '\u{0020}' => true,
_ => false,
}matches!(
383 c,
384 '\u{0009}' | '\u{0020}' )
388}
389
390pub fn is_id_start(c: char) -> bool {
394 c == '_' || unicode_ident::is_xid_start(c)
396}
397
398pub fn is_id_continue(c: char) -> bool {
402 unicode_ident::is_xid_continue(c)
403}
404
405pub fn is_ident(string: &str) -> bool {
407 let mut chars = string.chars();
408 if let Some(start) = chars.next() {
409 is_id_start(start) && chars.all(is_id_continue)
410 } else {
411 false
412 }
413}
414
415pub enum FrontmatterAllowed {
416 Yes,
417 No,
418}
419
420pub struct Cursor<'a> {
425 len_remaining: usize,
426 chars: Chars<'a>,
428 pub(crate) frontmatter_allowed: FrontmatterAllowed,
429 #[cfg(debug_assertions)]
430 prev: char,
431}
432
433const EOF_CHAR: char = '\0';
434
435impl<'a> Cursor<'a> {
436 pub fn new(input: &'a str, frontmatter_allowed: FrontmatterAllowed) -> Cursor<'a> {
437 Cursor {
438 len_remaining: input.len(),
439 chars: input.chars(),
440 frontmatter_allowed,
441 #[cfg(debug_assertions)]
442 prev: EOF_CHAR,
443 }
444 }
445
446 pub fn as_str(&self) -> &'a str {
447 self.chars.as_str()
448 }
449
450 pub(crate) fn prev(&self) -> char {
453 #[cfg(debug_assertions)]
454 {
455 self.prev
456 }
457
458 #[cfg(not(debug_assertions))]
459 {
460 EOF_CHAR
461 }
462 }
463
464 pub fn first(&self) -> char {
469 self.chars.clone().next().unwrap_or(EOF_CHAR)
471 }
472
473 pub(crate) fn second(&self) -> char {
475 let mut iter = self.chars.clone();
477 iter.next();
478 iter.next().unwrap_or(EOF_CHAR)
479 }
480
481 pub fn third(&self) -> char {
483 let mut iter = self.chars.clone();
485 iter.next();
486 iter.next();
487 iter.next().unwrap_or(EOF_CHAR)
488 }
489
490 pub(crate) fn is_eof(&self) -> bool {
492 self.chars.as_str().is_empty()
493 }
494
495 pub(crate) fn pos_within_token(&self) -> u32 {
497 (self.len_remaining - self.chars.as_str().len()) as u32
498 }
499
500 pub(crate) fn reset_pos_within_token(&mut self) {
502 self.len_remaining = self.chars.as_str().len();
503 }
504
505 pub(crate) fn bump(&mut self) -> Option<char> {
507 let c = self.chars.next()?;
508
509 #[cfg(debug_assertions)]
510 {
511 self.prev = c;
512 }
513
514 Some(c)
515 }
516
517 pub(crate) fn bump_bytes(&mut self, n: usize) {
519 self.chars = self.as_str()[n..].chars();
520 }
521
522 pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) {
524 while predicate(self.first()) && !self.is_eof() {
527 self.bump();
528 }
529 }
530
531 pub(crate) fn eat_until(&mut self, byte: u8) {
532 self.chars = match memchr::memchr(byte, self.as_str().as_bytes()) {
533 Some(index) => self.as_str()[index..].chars(),
534 None => "".chars(),
535 }
536 }
537
538 pub fn advance_token(&mut self) -> Token {
540 let Some(first_char) = self.bump() else {
541 return Token::new(TokenKind::Eof, 0);
542 };
543
544 let token_kind = match first_char {
545 c if #[allow(non_exhaustive_omitted_patterns)] match self.frontmatter_allowed {
FrontmatterAllowed::Yes => true,
_ => false,
}matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes)
546 && is_whitespace(c) =>
547 {
548 let mut last = first_char;
549 while is_whitespace(self.first()) {
550 let Some(c) = self.bump() else {
551 break;
552 };
553 last = c;
554 }
555 if last != '\n' && self.as_str().starts_with("---") {
559 self.bump();
560 self.frontmatter(true)
561 } else {
562 Whitespace
563 }
564 }
565 '-' if #[allow(non_exhaustive_omitted_patterns)] match self.frontmatter_allowed {
FrontmatterAllowed::Yes => true,
_ => false,
}matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes)
566 && self.as_str().starts_with("--") =>
567 {
568 self.frontmatter(false)
570 }
571 '/' => match self.first() {
573 '/' => self.line_comment(),
574 '*' => self.block_comment(),
575 _ => Slash,
576 },
577
578 c if is_whitespace(c) => self.whitespace(),
580
581 'r' => match (self.first(), self.second()) {
583 ('#', c1) if is_id_start(c1) => {
584 self.bump(); self.eat_identifier();
586 RawIdent
587 }
588 ('#', _) | ('"', _) => {
589 let res = self.raw_double_quoted_string(1);
590 let suffix_start = self.pos_within_token();
591 if res.is_ok() {
592 self.eat_literal_suffix();
593 }
594 let kind = RawStr { n_hashes: res.ok() };
595 Literal { kind, suffix_start }
596 }
597 _ => self.ident_or_unknown_prefix(false),
598 },
599
600 'k' => match (self.first(), self.second()) {
602 ('#', c1) if is_id_start(c1) => {
603 self.bump(); self.eat_identifier();
605 ForcedKeywordIdent
606 }
607 _ => self.ident_or_unknown_prefix(false),
608 },
609
610 'b' => self.c_or_byte_string(
612 |terminated| ByteStr { terminated },
613 |n_hashes| RawByteStr { n_hashes },
614 Some(|terminated| Byte { terminated }),
615 ),
616
617 'c' => self.c_or_byte_string(
619 |terminated| CStr { terminated },
620 |n_hashes| RawCStr { n_hashes },
621 None,
622 ),
623
624 c if is_id_start(c) => self.ident_or_unknown_prefix(false),
627
628 c @ '0'..='9' => {
630 let literal_kind = self.number(c);
631 let suffix_start = self.pos_within_token();
632 self.eat_literal_suffix();
633 TokenKind::Literal { kind: literal_kind, suffix_start }
634 }
635
636 '#' if #[allow(non_exhaustive_omitted_patterns)] match self.first() {
'"' | '#' => true,
_ => false,
}matches!(self.first(), '"' | '#') => {
638 self.bump();
639 TokenKind::GuardedStrPrefix
640 }
641
642 ';' => Semi,
644 ',' => Comma,
645 '.' => Dot,
646 '(' => OpenParen,
647 ')' => CloseParen,
648 '{' => OpenBrace,
649 '}' => CloseBrace,
650 '[' => OpenBracket,
651 ']' => CloseBracket,
652 '@' => At,
653 '#' => Pound,
654 '~' => Tilde,
655 '?' => Question,
656 ':' => Colon,
657 '$' => Dollar,
658 '=' => Eq,
659 '!' => Bang,
660 '<' => Lt,
661 '>' => Gt,
662 '-' => Minus,
663 '&' => And,
664 '|' => Or,
665 '+' => Plus,
666 '*' => Star,
667 '^' => Caret,
668 '%' => Percent,
669
670 '\'' => self.lifetime_or_char(),
672
673 '"' => {
675 let terminated = self.double_quoted_string();
676 let suffix_start = self.pos_within_token();
677 if terminated {
678 self.eat_literal_suffix();
679 }
680 let kind = Str { terminated };
681 Literal { kind, suffix_start }
682 }
683 c if is_emoji(c) => self.invalid_ident(),
685 _ => Unknown,
686 };
687 if #[allow(non_exhaustive_omitted_patterns)] match self.frontmatter_allowed {
FrontmatterAllowed::Yes => true,
_ => false,
}matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes)
688 && !#[allow(non_exhaustive_omitted_patterns)] match token_kind {
Whitespace => true,
_ => false,
}matches!(token_kind, Whitespace)
689 {
690 self.frontmatter_allowed = FrontmatterAllowed::No;
692 }
693 let res = Token::new(token_kind, self.pos_within_token());
694 self.reset_pos_within_token();
695 res
696 }
697
698 fn frontmatter(&mut self, has_invalid_preceding_whitespace: bool) -> TokenKind {
700 if true {
{
match (&'-', &self.prev()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};debug_assert_eq!('-', self.prev());
701
702 let pos = self.pos_within_token();
703 self.eat_while(|c| c == '-');
704
705 let length_opening = self.pos_within_token() - pos + 1;
707
708 if true {
if !(length_opening >= 3) {
::core::panicking::panic("assertion failed: length_opening >= 3")
};
};debug_assert!(length_opening >= 3);
710
711 self.eat_while(|ch| ch != '\n' && is_horizontal_whitespace(ch));
713
714 if is_id_start(self.first()) {
717 self.bump();
718 self.eat_while(|c| is_id_continue(c) || c == '-' || c == '.');
719 }
720
721 self.eat_while(|ch| ch != '\n' && is_horizontal_whitespace(ch));
722 let invalid_infostring = self.first() != '\n';
723
724 let mut found = false;
725 let nl_fence_pattern = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("\n{0:-<1$}", "",
length_opening as usize))
})format!("\n{:-<1$}", "", length_opening as usize);
726 if let Some(closing) = self.as_str().find(&nl_fence_pattern) {
727 self.bump_bytes(closing + nl_fence_pattern.len());
729 self.eat_until(b'\n');
737 found = true;
738 }
739
740 if !found {
741 let mut rest = self.as_str();
745 let mut potential_closing = rest
748 .find("\n---")
749 .map(|x| x + 1)
753 .or_else(|| rest.find("\nuse "))
754 .or_else(|| rest.find("\n//!"))
755 .or_else(|| rest.find("\n#!["));
756
757 if potential_closing.is_none() {
758 let mut base_index = 0;
761 while let Some(closing) = rest.find("---") {
762 let preceding_chars_start = rest[..closing].rfind("\n").map_or(0, |i| i + 1);
763 if rest[preceding_chars_start..closing].chars().all(is_horizontal_whitespace) {
764 potential_closing = Some(closing + base_index);
766 break;
767 } else {
768 rest = &rest[closing + 3..];
769 base_index += closing + 3;
770 }
771 }
772 }
773
774 if let Some(potential_closing) = potential_closing {
775 self.bump_bytes(potential_closing);
777 self.eat_until(b'\n');
778 } else {
779 self.eat_while(|_| true);
781 }
782 }
783
784 Frontmatter { has_invalid_preceding_whitespace, invalid_infostring }
785 }
786
787 fn line_comment(&mut self) -> TokenKind {
788 if true {
if !(self.prev() == '/' && self.first() == '/') {
::core::panicking::panic("assertion failed: self.prev() == \'/\' && self.first() == \'/\'")
};
};debug_assert!(self.prev() == '/' && self.first() == '/');
789 self.bump();
790
791 let doc_style = match self.first() {
792 '!' => Some(DocStyle::Inner),
794 '/' if self.second() != '/' => Some(DocStyle::Outer),
796 _ => None,
797 };
798
799 self.eat_until(b'\n');
800 LineComment { doc_style }
801 }
802
803 fn block_comment(&mut self) -> TokenKind {
804 if true {
if !(self.prev() == '/' && self.first() == '*') {
::core::panicking::panic("assertion failed: self.prev() == \'/\' && self.first() == \'*\'")
};
};debug_assert!(self.prev() == '/' && self.first() == '*');
805 self.bump();
806
807 let doc_style = match self.first() {
808 '!' => Some(DocStyle::Inner),
810 '*' if !#[allow(non_exhaustive_omitted_patterns)] match self.second() {
'*' | '/' => true,
_ => false,
}matches!(self.second(), '*' | '/') => Some(DocStyle::Outer),
813 _ => None,
814 };
815
816 let mut depth = 1usize;
817 while let Some(c) = self.bump() {
818 match c {
819 '/' if self.first() == '*' => {
820 self.bump();
821 depth += 1;
822 }
823 '*' if self.first() == '/' => {
824 self.bump();
825 depth -= 1;
826 if depth == 0 {
827 break;
831 }
832 }
833 _ => (),
834 }
835 }
836
837 BlockComment { doc_style, terminated: depth == 0 }
838 }
839
840 fn whitespace(&mut self) -> TokenKind {
841 if true {
if !is_whitespace(self.prev()) {
::core::panicking::panic("assertion failed: is_whitespace(self.prev())")
};
};debug_assert!(is_whitespace(self.prev()));
842 self.eat_while(is_whitespace);
843 Whitespace
844 }
845
846 fn ident_or_unknown_prefix(&mut self, already_invalid: bool) -> TokenKind {
847 if true {
if !(is_id_start(self.prev()) || already_invalid) {
::core::panicking::panic("assertion failed: is_id_start(self.prev()) || already_invalid")
};
};debug_assert!(is_id_start(self.prev()) || already_invalid);
848 self.eat_while(is_id_continue);
850 match self.first() {
853 '#' | '"' | '\'' => UnknownPrefix,
854 c if is_emoji(c) => self.invalid_ident(),
855 _ => Ident,
856 }
857 }
858
859 fn invalid_ident(&mut self) -> TokenKind {
860 self.eat_while(|c| is_id_continue(c) || is_emoji(c));
862 InvalidIdent
867 }
868
869 fn c_or_byte_string(
870 &mut self,
871 mk_kind: fn(bool) -> LiteralKind,
872 mk_kind_raw: fn(Option<u8>) -> LiteralKind,
873 single_quoted: Option<fn(bool) -> LiteralKind>,
874 ) -> TokenKind {
875 match (self.first(), self.second(), single_quoted) {
876 ('\'', _, Some(single_quoted)) => {
877 self.bump();
878 let terminated = self.single_quoted_string();
879 let suffix_start = self.pos_within_token();
880 if terminated {
881 self.eat_literal_suffix();
882 }
883 let kind = single_quoted(terminated);
884 Literal { kind, suffix_start }
885 }
886 ('"', _, _) => {
887 self.bump();
888 let terminated = self.double_quoted_string();
889 let suffix_start = self.pos_within_token();
890 if terminated {
891 self.eat_literal_suffix();
892 }
893 let kind = mk_kind(terminated);
894 Literal { kind, suffix_start }
895 }
896 ('r', '"', _) | ('r', '#', _) => {
897 self.bump();
898 let res = self.raw_double_quoted_string(2);
899 let suffix_start = self.pos_within_token();
900 if res.is_ok() {
901 self.eat_literal_suffix();
902 }
903 let kind = mk_kind_raw(res.ok());
904 Literal { kind, suffix_start }
905 }
906 _ => self.ident_or_unknown_prefix(false),
907 }
908 }
909
910 fn number(&mut self, first_digit: char) -> LiteralKind {
911 if true {
if !('0' <= self.prev() && self.prev() <= '9') {
::core::panicking::panic("assertion failed: \'0\' <= self.prev() && self.prev() <= \'9\'")
};
};debug_assert!('0' <= self.prev() && self.prev() <= '9');
912 let mut base = Base::Decimal;
913 if first_digit == '0' {
914 match self.first() {
916 'b' => {
917 base = Base::Binary;
918 self.bump();
919 if !self.eat_decimal_digits() {
920 return Int { base, empty_int: true };
921 }
922 }
923 'o' => {
924 base = Base::Octal;
925 self.bump();
926 if !self.eat_decimal_digits() {
927 return Int { base, empty_int: true };
928 }
929 }
930 'x' => {
931 base = Base::Hexadecimal;
932 self.bump();
933 if !self.eat_hexadecimal_digits() {
934 return Int { base, empty_int: true };
935 }
936 }
937 '0'..='9' | '_' => {
939 self.eat_decimal_digits();
940 }
941
942 '.' | 'e' | 'E' => {}
944
945 _ => return Int { base, empty_int: false },
947 }
948 } else {
949 self.eat_decimal_digits();
951 }
952
953 match self.first() {
954 '.' if self.second() != '.' && !is_id_start(self.second()) => {
958 self.bump();
961 let mut empty_exponent = false;
962 if self.first().is_ascii_digit() {
963 self.eat_decimal_digits();
964 match self.first() {
965 'e' | 'E' => {
966 self.bump();
967 empty_exponent = !self.eat_float_exponent();
968 }
969 _ => (),
970 }
971 }
972 Float { base, empty_exponent }
973 }
974 'e' | 'E' => {
975 self.bump();
976 let empty_exponent = !self.eat_float_exponent();
977 Float { base, empty_exponent }
978 }
979 _ => Int { base, empty_int: false },
980 }
981 }
982
983 fn lifetime_or_char(&mut self) -> TokenKind {
984 if true {
if !(self.prev() == '\'') {
::core::panicking::panic("assertion failed: self.prev() == \'\\\'\'")
};
};debug_assert!(self.prev() == '\'');
985
986 let mut invalid = false;
987 let can_be_a_lifetime = if self.second() == '\'' {
988 false
990 } else {
991 let c = self.first();
995 invalid |= c.is_ascii_digit();
996 invalid |= is_emoji(c);
997 is_id_start(c) || invalid
998 };
999
1000 if !can_be_a_lifetime {
1001 let terminated = self.single_quoted_string();
1002 let suffix_start = self.pos_within_token();
1003 if terminated {
1004 self.eat_literal_suffix();
1005 }
1006 let kind = Char { terminated };
1007 return Literal { kind, suffix_start };
1008 }
1009
1010 if self.first() == 'r' && self.second() == '#' && is_id_start(self.third()) {
1011 self.bump();
1013 self.bump();
1014 self.bump();
1015 self.eat_while(is_id_continue);
1016 return RawLifetime;
1017 }
1018
1019 let starts_with_number = self.first().is_ascii_digit();
1022
1023 self.bump();
1027 invalid |= #[allow(non_exhaustive_omitted_patterns)] match self.ident_or_unknown_prefix(invalid)
{
InvalidIdent => true,
_ => false,
}matches!(self.ident_or_unknown_prefix(invalid), InvalidIdent);
1028
1029 match self.first() {
1030 '\'' => {
1034 self.bump();
1035 let kind = Char { terminated: true };
1036 Literal { kind, suffix_start: self.pos_within_token() }
1037 }
1038 '#' if !starts_with_number => UnknownPrefixLifetime,
1039 _ => Lifetime { starts_with_number: invalid },
1040 }
1041 }
1042
1043 fn single_quoted_string(&mut self) -> bool {
1044 if true {
if !(self.prev() == '\'') {
::core::panicking::panic("assertion failed: self.prev() == \'\\\'\'")
};
};debug_assert!(self.prev() == '\'');
1045 if self.second() == '\'' && self.first() != '\\' {
1047 self.bump();
1048 self.bump();
1049 return true;
1050 }
1051
1052 loop {
1056 match self.first() {
1057 '\'' => {
1059 self.bump();
1060 return true;
1061 }
1062 '/' => break,
1065 '\n' if self.second() != '\'' => break,
1067 EOF_CHAR if self.is_eof() => break,
1069 '\\' => {
1071 self.bump();
1072 self.bump();
1073 }
1074 _ => {
1076 self.bump();
1077 }
1078 }
1079 }
1080 false
1082 }
1083
1084 fn double_quoted_string(&mut self) -> bool {
1087 if true {
if !(self.prev() == '"') {
::core::panicking::panic("assertion failed: self.prev() == \'\"\'")
};
};debug_assert!(self.prev() == '"');
1088 while let Some(c) = self.bump() {
1089 match c {
1090 '"' => {
1091 return true;
1092 }
1093 '\\' if self.first() == '\\' || self.first() == '"' => {
1094 self.bump();
1096 }
1097 _ => (),
1098 }
1099 }
1100 false
1102 }
1103
1104 pub fn guarded_double_quoted_string(&mut self) -> Option<GuardedStr> {
1113 if true {
if !(self.prev() != '#') {
::core::panicking::panic("assertion failed: self.prev() != \'#\'")
};
};debug_assert!(self.prev() != '#');
1114
1115 let mut n_start_hashes: u32 = 0;
1116 while self.first() == '#' {
1117 n_start_hashes += 1;
1118 self.bump();
1119 }
1120
1121 if self.first() != '"' {
1122 return None;
1123 }
1124 self.bump();
1125 if true {
if !(self.prev() == '"') {
::core::panicking::panic("assertion failed: self.prev() == \'\"\'")
};
};debug_assert!(self.prev() == '"');
1126
1127 let terminated = self.double_quoted_string();
1130 if !terminated {
1131 let token_len = self.pos_within_token();
1132 self.reset_pos_within_token();
1133
1134 return Some(GuardedStr { n_hashes: n_start_hashes, terminated: false, token_len });
1135 }
1136
1137 let mut n_end_hashes = 0;
1142 while self.first() == '#' && n_end_hashes < n_start_hashes {
1143 n_end_hashes += 1;
1144 self.bump();
1145 }
1146
1147 self.eat_literal_suffix();
1151
1152 let token_len = self.pos_within_token();
1153 self.reset_pos_within_token();
1154
1155 Some(GuardedStr { n_hashes: n_start_hashes, terminated: true, token_len })
1156 }
1157
1158 fn raw_double_quoted_string(&mut self, prefix_len: u32) -> Result<u8, RawStrError> {
1160 let n_hashes = self.raw_string_unvalidated(prefix_len)?;
1163 match u8::try_from(n_hashes) {
1165 Ok(num) => Ok(num),
1166 Err(_) => Err(RawStrError::TooManyDelimiters { found: n_hashes }),
1167 }
1168 }
1169
1170 fn raw_string_unvalidated(&mut self, prefix_len: u32) -> Result<u32, RawStrError> {
1171 if true {
if !(self.prev() == 'r') {
::core::panicking::panic("assertion failed: self.prev() == \'r\'")
};
};debug_assert!(self.prev() == 'r');
1172 let start_pos = self.pos_within_token();
1173 let mut possible_terminator_offset = None;
1174 let mut max_hashes = 0;
1175
1176 let mut eaten = 0;
1178 while self.first() == '#' {
1179 eaten += 1;
1180 self.bump();
1181 }
1182 let n_start_hashes = eaten;
1183
1184 match self.bump() {
1186 Some('"') => (),
1187 c => {
1188 let c = c.unwrap_or(EOF_CHAR);
1189 return Err(RawStrError::InvalidStarter { bad_char: c });
1190 }
1191 }
1192
1193 loop {
1196 self.eat_until(b'"');
1197
1198 if self.is_eof() {
1199 return Err(RawStrError::NoTerminator {
1200 expected: n_start_hashes,
1201 found: max_hashes,
1202 possible_terminator_offset,
1203 });
1204 }
1205
1206 self.bump();
1208
1209 let mut n_end_hashes = 0;
1215 while self.first() == '#' && n_end_hashes < n_start_hashes {
1216 n_end_hashes += 1;
1217 self.bump();
1218 }
1219
1220 if n_end_hashes == n_start_hashes {
1221 return Ok(n_start_hashes);
1222 } else if n_end_hashes > max_hashes {
1223 possible_terminator_offset =
1226 Some(self.pos_within_token() - start_pos - n_end_hashes + prefix_len);
1227 max_hashes = n_end_hashes;
1228 }
1229 }
1230 }
1231
1232 fn eat_decimal_digits(&mut self) -> bool {
1233 let mut has_digits = false;
1234 loop {
1235 match self.first() {
1236 '_' => {
1237 self.bump();
1238 }
1239 '0'..='9' => {
1240 has_digits = true;
1241 self.bump();
1242 }
1243 _ => break,
1244 }
1245 }
1246 has_digits
1247 }
1248
1249 fn eat_hexadecimal_digits(&mut self) -> bool {
1250 let mut has_digits = false;
1251 loop {
1252 match self.first() {
1253 '_' => {
1254 self.bump();
1255 }
1256 '0'..='9' | 'a'..='f' | 'A'..='F' => {
1257 has_digits = true;
1258 self.bump();
1259 }
1260 _ => break,
1261 }
1262 }
1263 has_digits
1264 }
1265
1266 fn eat_float_exponent(&mut self) -> bool {
1269 if true {
if !(self.prev() == 'e' || self.prev() == 'E') {
::core::panicking::panic("assertion failed: self.prev() == \'e\' || self.prev() == \'E\'")
};
};debug_assert!(self.prev() == 'e' || self.prev() == 'E');
1270 if self.first() == '-' || self.first() == '+' {
1271 self.bump();
1272 }
1273 self.eat_decimal_digits()
1274 }
1275
1276 fn eat_literal_suffix(&mut self) {
1278 self.eat_identifier();
1279 }
1280
1281 fn eat_identifier(&mut self) {
1284 if !is_id_start(self.first()) {
1285 return;
1286 }
1287 self.bump();
1288
1289 self.eat_while(is_id_continue);
1290 }
1291}
1292
1293fn is_emoji(c: char) -> bool {
1294 !c.is_ascii() && c.is_emoji_char()
1295}