1#![deny(unstable_features)]
26mod cursor;
29
30#[cfg(test)]
31mod tests;
32
33use LiteralKind::*;
34use TokenKind::*;
35use cursor::EOF_CHAR;
36pub use cursor::{Cursor, FrontmatterAllowed};
37pub use unicode_ident::UNICODE_VERSION;
38use unicode_properties::UnicodeEmoji;
39
40const _: () = {
42 let properties = unicode_properties::UNICODE_VERSION;
43 let ident = unicode_ident::UNICODE_VERSION;
44
45 if properties.0 != ident.0 as u64
46 || properties.1 != ident.1 as u64
47 || properties.2 != ident.2 as u64
48 {
49 {
::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!(
50 "unicode-properties and unicode-ident must use the same Unicode version, \
51 `unicode_properties::UNICODE_VERSION` and `unicode_ident::UNICODE_VERSION` are \
52 different."
53 );
54 }
55};
56
57#[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",
&self.kind, "len", &&self.len)
}
}Debug)]
61pub struct Token {
62 pub kind: TokenKind,
63 pub len: u32,
64}
65
66impl Token {
67 fn new(kind: TokenKind, len: u32) -> Token {
68 Token { kind, len }
69 }
70}
71
72#[derive(#[automatically_derived]
impl ::core::clone::Clone for TokenKind {
#[inline]
fn clone(&self) -> TokenKind {
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 {
TokenKind::LineComment { doc_style: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"LineComment", "doc_style", &__self_0),
TokenKind::BlockComment {
doc_style: __self_0, terminated: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"BlockComment", "doc_style", __self_0, "terminated",
&__self_1),
TokenKind::Whitespace =>
::core::fmt::Formatter::write_str(f, "Whitespace"),
TokenKind::Frontmatter {
has_invalid_preceding_whitespace: __self_0,
invalid_infostring: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Frontmatter", "has_invalid_preceding_whitespace", __self_0,
"invalid_infostring", &__self_1),
TokenKind::Ident => ::core::fmt::Formatter::write_str(f, "Ident"),
TokenKind::InvalidIdent =>
::core::fmt::Formatter::write_str(f, "InvalidIdent"),
TokenKind::RawIdent =>
::core::fmt::Formatter::write_str(f, "RawIdent"),
TokenKind::UnknownPrefix =>
::core::fmt::Formatter::write_str(f, "UnknownPrefix"),
TokenKind::UnknownPrefixLifetime =>
::core::fmt::Formatter::write_str(f, "UnknownPrefixLifetime"),
TokenKind::RawLifetime =>
::core::fmt::Formatter::write_str(f, "RawLifetime"),
TokenKind::GuardedStrPrefix =>
::core::fmt::Formatter::write_str(f, "GuardedStrPrefix"),
TokenKind::Literal { kind: __self_0, suffix_start: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Literal", "kind", __self_0, "suffix_start", &__self_1),
TokenKind::Lifetime { starts_with_number: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"Lifetime", "starts_with_number", &__self_0),
TokenKind::Semi => ::core::fmt::Formatter::write_str(f, "Semi"),
TokenKind::Comma => ::core::fmt::Formatter::write_str(f, "Comma"),
TokenKind::Dot => ::core::fmt::Formatter::write_str(f, "Dot"),
TokenKind::OpenParen =>
::core::fmt::Formatter::write_str(f, "OpenParen"),
TokenKind::CloseParen =>
::core::fmt::Formatter::write_str(f, "CloseParen"),
TokenKind::OpenBrace =>
::core::fmt::Formatter::write_str(f, "OpenBrace"),
TokenKind::CloseBrace =>
::core::fmt::Formatter::write_str(f, "CloseBrace"),
TokenKind::OpenBracket =>
::core::fmt::Formatter::write_str(f, "OpenBracket"),
TokenKind::CloseBracket =>
::core::fmt::Formatter::write_str(f, "CloseBracket"),
TokenKind::At => ::core::fmt::Formatter::write_str(f, "At"),
TokenKind::Pound => ::core::fmt::Formatter::write_str(f, "Pound"),
TokenKind::Tilde => ::core::fmt::Formatter::write_str(f, "Tilde"),
TokenKind::Question =>
::core::fmt::Formatter::write_str(f, "Question"),
TokenKind::Colon => ::core::fmt::Formatter::write_str(f, "Colon"),
TokenKind::Dollar =>
::core::fmt::Formatter::write_str(f, "Dollar"),
TokenKind::Eq => ::core::fmt::Formatter::write_str(f, "Eq"),
TokenKind::Bang => ::core::fmt::Formatter::write_str(f, "Bang"),
TokenKind::Lt => ::core::fmt::Formatter::write_str(f, "Lt"),
TokenKind::Gt => ::core::fmt::Formatter::write_str(f, "Gt"),
TokenKind::Minus => ::core::fmt::Formatter::write_str(f, "Minus"),
TokenKind::And => ::core::fmt::Formatter::write_str(f, "And"),
TokenKind::Or => ::core::fmt::Formatter::write_str(f, "Or"),
TokenKind::Plus => ::core::fmt::Formatter::write_str(f, "Plus"),
TokenKind::Star => ::core::fmt::Formatter::write_str(f, "Star"),
TokenKind::Slash => ::core::fmt::Formatter::write_str(f, "Slash"),
TokenKind::Caret => ::core::fmt::Formatter::write_str(f, "Caret"),
TokenKind::Percent =>
::core::fmt::Formatter::write_str(f, "Percent"),
TokenKind::Unknown =>
::core::fmt::Formatter::write_str(f, "Unknown"),
TokenKind::Eof => ::core::fmt::Formatter::write_str(f, "Eof"),
}
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for TokenKind {
#[inline]
fn eq(&self, other: &TokenKind) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(TokenKind::LineComment { doc_style: __self_0 },
TokenKind::LineComment { doc_style: __arg1_0 }) =>
__self_0 == __arg1_0,
(TokenKind::BlockComment {
doc_style: __self_0, terminated: __self_1 },
TokenKind::BlockComment {
doc_style: __arg1_0, terminated: __arg1_1 }) =>
__self_1 == __arg1_1 && __self_0 == __arg1_0,
(TokenKind::Frontmatter {
has_invalid_preceding_whitespace: __self_0,
invalid_infostring: __self_1 }, TokenKind::Frontmatter {
has_invalid_preceding_whitespace: __arg1_0,
invalid_infostring: __arg1_1 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(TokenKind::Literal { kind: __self_0, suffix_start: __self_1
}, TokenKind::Literal {
kind: __arg1_0, suffix_start: __arg1_1 }) =>
__self_1 == __arg1_1 && __self_0 == __arg1_0,
(TokenKind::Lifetime { starts_with_number: __self_0 },
TokenKind::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_receiver_is_total_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)]
74pub enum TokenKind {
75 LineComment {
77 doc_style: Option<DocStyle>,
78 },
79
80 BlockComment {
85 doc_style: Option<DocStyle>,
86 terminated: bool,
87 },
88
89 Whitespace,
91
92 Frontmatter {
93 has_invalid_preceding_whitespace: bool,
94 invalid_infostring: bool,
95 },
96
97 Ident,
99
100 InvalidIdent,
102
103 RawIdent,
105
106 UnknownPrefix,
116
117 UnknownPrefixLifetime,
122
123 RawLifetime,
126
127 GuardedStrPrefix,
132
133 Literal {
139 kind: LiteralKind,
140 suffix_start: u32,
141 },
142
143 Lifetime {
145 starts_with_number: bool,
146 },
147
148 Semi,
150 Comma,
152 Dot,
154 OpenParen,
156 CloseParen,
158 OpenBrace,
160 CloseBrace,
162 OpenBracket,
164 CloseBracket,
166 At,
168 Pound,
170 Tilde,
172 Question,
174 Colon,
176 Dollar,
178 Eq,
180 Bang,
182 Lt,
184 Gt,
186 Minus,
188 And,
190 Or,
192 Plus,
194 Star,
196 Slash,
198 Caret,
200 Percent,
202
203 Unknown,
205
206 Eof,
208}
209
210#[derive(#[automatically_derived]
impl ::core::clone::Clone for DocStyle {
#[inline]
fn clone(&self) -> DocStyle { *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::cmp::PartialEq for DocStyle {
#[inline]
fn eq(&self, other: &DocStyle) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for DocStyle {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}Eq)]
211pub enum DocStyle {
212 Outer,
213 Inner,
214}
215
216#[derive(#[automatically_derived]
impl ::core::clone::Clone for LiteralKind {
#[inline]
fn clone(&self) -> LiteralKind {
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 {
LiteralKind::Int { base: __self_0, empty_int: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f, "Int",
"base", __self_0, "empty_int", &__self_1),
LiteralKind::Float { base: __self_0, empty_exponent: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f, "Float",
"base", __self_0, "empty_exponent", &__self_1),
LiteralKind::Char { terminated: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f, "Char",
"terminated", &__self_0),
LiteralKind::Byte { terminated: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f, "Byte",
"terminated", &__self_0),
LiteralKind::Str { terminated: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f, "Str",
"terminated", &__self_0),
LiteralKind::ByteStr { terminated: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"ByteStr", "terminated", &__self_0),
LiteralKind::CStr { terminated: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f, "CStr",
"terminated", &__self_0),
LiteralKind::RawStr { n_hashes: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"RawStr", "n_hashes", &__self_0),
LiteralKind::RawByteStr { n_hashes: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"RawByteStr", "n_hashes", &__self_0),
LiteralKind::RawCStr { n_hashes: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"RawCStr", "n_hashes", &__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for LiteralKind {
#[inline]
fn eq(&self, other: &LiteralKind) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(LiteralKind::Int { base: __self_0, empty_int: __self_1 },
LiteralKind::Int { base: __arg1_0, empty_int: __arg1_1 }) =>
__self_1 == __arg1_1 && __self_0 == __arg1_0,
(LiteralKind::Float { base: __self_0, empty_exponent: __self_1
}, LiteralKind::Float {
base: __arg1_0, empty_exponent: __arg1_1 }) =>
__self_1 == __arg1_1 && __self_0 == __arg1_0,
(LiteralKind::Char { terminated: __self_0 },
LiteralKind::Char { terminated: __arg1_0 }) =>
__self_0 == __arg1_0,
(LiteralKind::Byte { terminated: __self_0 },
LiteralKind::Byte { terminated: __arg1_0 }) =>
__self_0 == __arg1_0,
(LiteralKind::Str { terminated: __self_0 }, LiteralKind::Str {
terminated: __arg1_0 }) => __self_0 == __arg1_0,
(LiteralKind::ByteStr { terminated: __self_0 },
LiteralKind::ByteStr { terminated: __arg1_0 }) =>
__self_0 == __arg1_0,
(LiteralKind::CStr { terminated: __self_0 },
LiteralKind::CStr { terminated: __arg1_0 }) =>
__self_0 == __arg1_0,
(LiteralKind::RawStr { n_hashes: __self_0 },
LiteralKind::RawStr { n_hashes: __arg1_0 }) =>
__self_0 == __arg1_0,
(LiteralKind::RawByteStr { n_hashes: __self_0 },
LiteralKind::RawByteStr { n_hashes: __arg1_0 }) =>
__self_0 == __arg1_0,
(LiteralKind::RawCStr { n_hashes: __self_0 },
LiteralKind::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_receiver_is_total_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: &LiteralKind)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match (self, other) {
(LiteralKind::Int { base: __self_0, empty_int: __self_1 },
LiteralKind::Int { base: __arg1_0, empty_int: __arg1_1 }) =>
match ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0)
{
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=> ::core::cmp::PartialOrd::partial_cmp(__self_1, __arg1_1),
cmp => cmp,
},
(LiteralKind::Float { base: __self_0, empty_exponent: __self_1 },
LiteralKind::Float { base: __arg1_0, empty_exponent: __arg1_1
}) =>
match ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0)
{
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=> ::core::cmp::PartialOrd::partial_cmp(__self_1, __arg1_1),
cmp => cmp,
},
(LiteralKind::Char { terminated: __self_0 }, LiteralKind::Char {
terminated: __arg1_0 }) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(LiteralKind::Byte { terminated: __self_0 }, LiteralKind::Byte {
terminated: __arg1_0 }) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(LiteralKind::Str { terminated: __self_0 }, LiteralKind::Str {
terminated: __arg1_0 }) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(LiteralKind::ByteStr { terminated: __self_0 },
LiteralKind::ByteStr { terminated: __arg1_0 }) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(LiteralKind::CStr { terminated: __self_0 }, LiteralKind::CStr {
terminated: __arg1_0 }) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(LiteralKind::RawStr { n_hashes: __self_0 }, LiteralKind::RawStr {
n_hashes: __arg1_0 }) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(LiteralKind::RawByteStr { n_hashes: __self_0 },
LiteralKind::RawByteStr { n_hashes: __arg1_0 }) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(LiteralKind::RawCStr { n_hashes: __self_0 },
LiteralKind::RawCStr { n_hashes: __arg1_0 }) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
_ =>
::core::cmp::PartialOrd::partial_cmp(&__self_discr,
&__arg1_discr),
}
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for LiteralKind {
#[inline]
fn cmp(&self, other: &LiteralKind) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
::core::cmp::Ordering::Equal =>
match (self, other) {
(LiteralKind::Int { base: __self_0, empty_int: __self_1 },
LiteralKind::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,
},
(LiteralKind::Float {
base: __self_0, empty_exponent: __self_1 },
LiteralKind::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,
},
(LiteralKind::Char { terminated: __self_0 },
LiteralKind::Char { terminated: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(LiteralKind::Byte { terminated: __self_0 },
LiteralKind::Byte { terminated: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(LiteralKind::Str { terminated: __self_0 },
LiteralKind::Str { terminated: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(LiteralKind::ByteStr { terminated: __self_0 },
LiteralKind::ByteStr { terminated: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(LiteralKind::CStr { terminated: __self_0 },
LiteralKind::CStr { terminated: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(LiteralKind::RawStr { n_hashes: __self_0 },
LiteralKind::RawStr { n_hashes: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(LiteralKind::RawByteStr { n_hashes: __self_0 },
LiteralKind::RawByteStr { n_hashes: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(LiteralKind::RawCStr { n_hashes: __self_0 },
LiteralKind::RawCStr { n_hashes: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ => unsafe { ::core::intrinsics::unreachable() }
},
cmp => cmp,
}
}
}Ord)]
223pub enum LiteralKind {
224 Int { base: Base, empty_int: bool },
226 Float { base: Base, empty_exponent: bool },
228 Char { terminated: bool },
230 Byte { terminated: bool },
232 Str { terminated: bool },
234 ByteStr { terminated: bool },
236 CStr { terminated: bool },
238 RawStr { n_hashes: Option<u8> },
241 RawByteStr { n_hashes: Option<u8> },
244 RawCStr { n_hashes: Option<u8> },
246}
247
248#[derive(#[automatically_derived]
impl ::core::clone::Clone for GuardedStr {
#[inline]
fn clone(&self) -> GuardedStr {
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", &self.n_hashes, "terminated", &self.terminated,
"token_len", &&self.token_len)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for GuardedStr {
#[inline]
fn eq(&self, other: &GuardedStr) -> 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_receiver_is_total_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: &GuardedStr)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.n_hashes,
&other.n_hashes) {
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
match ::core::cmp::PartialOrd::partial_cmp(&self.terminated,
&other.terminated) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=>
::core::cmp::PartialOrd::partial_cmp(&self.token_len,
&other.token_len),
cmp => cmp,
},
cmp => cmp,
}
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for GuardedStr {
#[inline]
fn cmp(&self, other: &GuardedStr) -> ::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)]
253pub struct GuardedStr {
254 pub n_hashes: u32,
255 pub terminated: bool,
256 pub token_len: u32,
257}
258
259#[derive(#[automatically_derived]
impl ::core::clone::Clone for RawStrError {
#[inline]
fn clone(&self) -> RawStrError {
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 {
RawStrError::InvalidStarter { bad_char: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"InvalidStarter", "bad_char", &__self_0),
RawStrError::NoTerminator {
expected: __self_0,
found: __self_1,
possible_terminator_offset: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"NoTerminator", "expected", __self_0, "found", __self_1,
"possible_terminator_offset", &__self_2),
RawStrError::TooManyDelimiters { found: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"TooManyDelimiters", "found", &__self_0),
}
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for RawStrError {
#[inline]
fn eq(&self, other: &RawStrError) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(RawStrError::InvalidStarter { bad_char: __self_0 },
RawStrError::InvalidStarter { bad_char: __arg1_0 }) =>
__self_0 == __arg1_0,
(RawStrError::NoTerminator {
expected: __self_0,
found: __self_1,
possible_terminator_offset: __self_2 },
RawStrError::NoTerminator {
expected: __arg1_0,
found: __arg1_1,
possible_terminator_offset: __arg1_2 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1 &&
__self_2 == __arg1_2,
(RawStrError::TooManyDelimiters { found: __self_0 },
RawStrError::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_receiver_is_total_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: &RawStrError)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match (self, other) {
(RawStrError::InvalidStarter { bad_char: __self_0 },
RawStrError::InvalidStarter { bad_char: __arg1_0 }) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(RawStrError::NoTerminator {
expected: __self_0,
found: __self_1,
possible_terminator_offset: __self_2 },
RawStrError::NoTerminator {
expected: __arg1_0,
found: __arg1_1,
possible_terminator_offset: __arg1_2 }) =>
match ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0)
{
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=>
match ::core::cmp::PartialOrd::partial_cmp(__self_1,
__arg1_1) {
::core::option::Option::Some(::core::cmp::Ordering::Equal)
=> ::core::cmp::PartialOrd::partial_cmp(__self_2, __arg1_2),
cmp => cmp,
},
cmp => cmp,
},
(RawStrError::TooManyDelimiters { found: __self_0 },
RawStrError::TooManyDelimiters { found: __arg1_0 }) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
_ =>
::core::cmp::PartialOrd::partial_cmp(&__self_discr,
&__arg1_discr),
}
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for RawStrError {
#[inline]
fn cmp(&self, other: &RawStrError) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
::core::cmp::Ordering::Equal =>
match (self, other) {
(RawStrError::InvalidStarter { bad_char: __self_0 },
RawStrError::InvalidStarter { bad_char: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(RawStrError::NoTerminator {
expected: __self_0,
found: __self_1,
possible_terminator_offset: __self_2 },
RawStrError::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,
},
(RawStrError::TooManyDelimiters { found: __self_0 },
RawStrError::TooManyDelimiters { found: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ => unsafe { ::core::intrinsics::unreachable() }
},
cmp => cmp,
}
}
}Ord)]
260pub enum RawStrError {
261 InvalidStarter { bad_char: char },
263 NoTerminator { expected: u32, found: u32, possible_terminator_offset: Option<u32> },
267 TooManyDelimiters { found: u32 },
269}
270
271#[derive(#[automatically_derived]
impl ::core::clone::Clone for Base {
#[inline]
fn clone(&self) -> Base { *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::cmp::PartialEq for Base {
#[inline]
fn eq(&self, other: &Base) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Base {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for Base {
#[inline]
fn partial_cmp(&self, other: &Base)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for Base {
#[inline]
fn cmp(&self, other: &Base) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
}
}Ord)]
273pub enum Base {
274 Binary = 2,
276 Octal = 8,
278 Decimal = 10,
280 Hexadecimal = 16,
282}
283
284pub fn strip_shebang(input: &str) -> Option<usize> {
287 if let Some(input_tail) = input.strip_prefix("#!") {
291 let next_non_whitespace_token =
294 tokenize(input_tail, FrontmatterAllowed::No).map(|tok| tok.kind).find(|tok| {
295 !#[allow(non_exhaustive_omitted_patterns)] match tok {
TokenKind::Whitespace | TokenKind::LineComment { doc_style: None } |
TokenKind::BlockComment { doc_style: None, .. } => true,
_ => false,
}matches!(
296 tok,
297 TokenKind::Whitespace
298 | TokenKind::LineComment { doc_style: None }
299 | TokenKind::BlockComment { doc_style: None, .. }
300 )
301 });
302 if next_non_whitespace_token != Some(TokenKind::OpenBracket) {
303 return Some(2 + input_tail.lines().next().unwrap_or_default().len());
305 }
306 }
307 None
308}
309
310#[inline]
313pub fn validate_raw_str(input: &str, prefix_len: u32) -> Result<(), RawStrError> {
314 if true {
if !!input.is_empty() {
::core::panicking::panic("assertion failed: !input.is_empty()")
};
};debug_assert!(!input.is_empty());
315 let mut cursor = Cursor::new(input, FrontmatterAllowed::No);
316 for _ in 0..prefix_len {
318 cursor.bump().unwrap();
319 }
320 cursor.raw_double_quoted_string(prefix_len).map(|_| ())
321}
322
323pub fn tokenize(
330 input: &str,
331 frontmatter_allowed: FrontmatterAllowed,
332) -> impl Iterator<Item = Token> {
333 let mut cursor = Cursor::new(input, frontmatter_allowed);
334 std::iter::from_fn(move || {
335 let token = cursor.advance_token();
336 if token.kind != TokenKind::Eof { Some(token) } else { None }
337 })
338}
339
340pub fn is_whitespace(c: char) -> bool {
344 #[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!(
350 c,
351 | '\u{000A}' | '\u{000B}' | '\u{000C}' | '\u{000D}' | '\u{0085}' | '\u{2028}' | '\u{2029}' | '\u{200E}' | '\u{200F}' | '\u{0009}' | '\u{0020}' )
368}
369
370pub fn is_horizontal_whitespace(c: char) -> bool {
372 #[allow(non_exhaustive_omitted_patterns)] match c {
'\u{0009}' | '\u{0020}' => true,
_ => false,
}matches!(
378 c,
379 '\u{0009}' | '\u{0020}' )
383}
384
385pub fn is_id_start(c: char) -> bool {
389 c == '_' || unicode_ident::is_xid_start(c)
391}
392
393pub fn is_id_continue(c: char) -> bool {
397 unicode_ident::is_xid_continue(c)
398}
399
400pub fn is_ident(string: &str) -> bool {
402 let mut chars = string.chars();
403 if let Some(start) = chars.next() {
404 is_id_start(start) && chars.all(is_id_continue)
405 } else {
406 false
407 }
408}
409
410impl Cursor<'_> {
411 pub fn advance_token(&mut self) -> Token {
413 let Some(first_char) = self.bump() else {
414 return Token::new(TokenKind::Eof, 0);
415 };
416
417 let token_kind = match first_char {
418 c if #[allow(non_exhaustive_omitted_patterns)] match self.frontmatter_allowed {
FrontmatterAllowed::Yes => true,
_ => false,
}matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes)
419 && is_whitespace(c) =>
420 {
421 let mut last = first_char;
422 while is_whitespace(self.first()) {
423 let Some(c) = self.bump() else {
424 break;
425 };
426 last = c;
427 }
428 if last != '\n' && self.as_str().starts_with("---") {
432 self.bump();
433 self.frontmatter(true)
434 } else {
435 Whitespace
436 }
437 }
438 '-' if #[allow(non_exhaustive_omitted_patterns)] match self.frontmatter_allowed {
FrontmatterAllowed::Yes => true,
_ => false,
}matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes)
439 && self.as_str().starts_with("--") =>
440 {
441 self.frontmatter(false)
443 }
444 '/' => match self.first() {
446 '/' => self.line_comment(),
447 '*' => self.block_comment(),
448 _ => Slash,
449 },
450
451 c if is_whitespace(c) => self.whitespace(),
453
454 'r' => match (self.first(), self.second()) {
456 ('#', c1) if is_id_start(c1) => self.raw_ident(),
457 ('#', _) | ('"', _) => {
458 let res = self.raw_double_quoted_string(1);
459 let suffix_start = self.pos_within_token();
460 if res.is_ok() {
461 self.eat_literal_suffix();
462 }
463 let kind = RawStr { n_hashes: res.ok() };
464 Literal { kind, suffix_start }
465 }
466 _ => self.ident_or_unknown_prefix(),
467 },
468
469 'b' => self.c_or_byte_string(
471 |terminated| ByteStr { terminated },
472 |n_hashes| RawByteStr { n_hashes },
473 Some(|terminated| Byte { terminated }),
474 ),
475
476 'c' => self.c_or_byte_string(
478 |terminated| CStr { terminated },
479 |n_hashes| RawCStr { n_hashes },
480 None,
481 ),
482
483 c if is_id_start(c) => self.ident_or_unknown_prefix(),
486
487 c @ '0'..='9' => {
489 let literal_kind = self.number(c);
490 let suffix_start = self.pos_within_token();
491 self.eat_literal_suffix();
492 TokenKind::Literal { kind: literal_kind, suffix_start }
493 }
494
495 '#' if #[allow(non_exhaustive_omitted_patterns)] match self.first() {
'"' | '#' => true,
_ => false,
}matches!(self.first(), '"' | '#') => {
497 self.bump();
498 TokenKind::GuardedStrPrefix
499 }
500
501 ';' => Semi,
503 ',' => Comma,
504 '.' => Dot,
505 '(' => OpenParen,
506 ')' => CloseParen,
507 '{' => OpenBrace,
508 '}' => CloseBrace,
509 '[' => OpenBracket,
510 ']' => CloseBracket,
511 '@' => At,
512 '#' => Pound,
513 '~' => Tilde,
514 '?' => Question,
515 ':' => Colon,
516 '$' => Dollar,
517 '=' => Eq,
518 '!' => Bang,
519 '<' => Lt,
520 '>' => Gt,
521 '-' => Minus,
522 '&' => And,
523 '|' => Or,
524 '+' => Plus,
525 '*' => Star,
526 '^' => Caret,
527 '%' => Percent,
528
529 '\'' => self.lifetime_or_char(),
531
532 '"' => {
534 let terminated = self.double_quoted_string();
535 let suffix_start = self.pos_within_token();
536 if terminated {
537 self.eat_literal_suffix();
538 }
539 let kind = Str { terminated };
540 Literal { kind, suffix_start }
541 }
542 c if !c.is_ascii() && c.is_emoji_char() => self.invalid_ident(),
544 _ => Unknown,
545 };
546 if #[allow(non_exhaustive_omitted_patterns)] match self.frontmatter_allowed {
FrontmatterAllowed::Yes => true,
_ => false,
}matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes)
547 && !#[allow(non_exhaustive_omitted_patterns)] match token_kind {
Whitespace => true,
_ => false,
}matches!(token_kind, Whitespace)
548 {
549 self.frontmatter_allowed = FrontmatterAllowed::No;
551 }
552 let res = Token::new(token_kind, self.pos_within_token());
553 self.reset_pos_within_token();
554 res
555 }
556
557 fn frontmatter(&mut self, has_invalid_preceding_whitespace: bool) -> TokenKind {
559 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());
560
561 let pos = self.pos_within_token();
562 self.eat_while(|c| c == '-');
563
564 let length_opening = self.pos_within_token() - pos + 1;
566
567 if true {
if !(length_opening >= 3) {
::core::panicking::panic("assertion failed: length_opening >= 3")
};
};debug_assert!(length_opening >= 3);
569
570 self.eat_while(|ch| ch != '\n' && is_horizontal_whitespace(ch));
572
573 if is_id_start(self.first()) {
576 self.bump();
577 self.eat_while(|c| is_id_continue(c) || c == '-' || c == '.');
578 }
579
580 self.eat_while(|ch| ch != '\n' && is_horizontal_whitespace(ch));
581 let invalid_infostring = self.first() != '\n';
582
583 let mut found = false;
584 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);
585 if let Some(closing) = self.as_str().find(&nl_fence_pattern) {
586 self.bump_bytes(closing + nl_fence_pattern.len());
588 self.eat_until(b'\n');
596 found = true;
597 }
598
599 if !found {
600 let mut rest = self.as_str();
604 let mut potential_closing = rest
607 .find("\n---")
608 .map(|x| x + 1)
612 .or_else(|| rest.find("\nuse "))
613 .or_else(|| rest.find("\n//!"))
614 .or_else(|| rest.find("\n#!["));
615
616 if potential_closing.is_none() {
617 let mut base_index = 0;
620 while let Some(closing) = rest.find("---") {
621 let preceding_chars_start = rest[..closing].rfind("\n").map_or(0, |i| i + 1);
622 if rest[preceding_chars_start..closing].chars().all(is_horizontal_whitespace) {
623 potential_closing = Some(closing + base_index);
625 break;
626 } else {
627 rest = &rest[closing + 3..];
628 base_index += closing + 3;
629 }
630 }
631 }
632
633 if let Some(potential_closing) = potential_closing {
634 self.bump_bytes(potential_closing);
636 self.eat_until(b'\n');
637 } else {
638 self.eat_while(|_| true);
640 }
641 }
642
643 Frontmatter { has_invalid_preceding_whitespace, invalid_infostring }
644 }
645
646 fn line_comment(&mut self) -> TokenKind {
647 if true {
if !(self.prev() == '/' && self.first() == '/') {
::core::panicking::panic("assertion failed: self.prev() == \'/\' && self.first() == \'/\'")
};
};debug_assert!(self.prev() == '/' && self.first() == '/');
648 self.bump();
649
650 let doc_style = match self.first() {
651 '!' => Some(DocStyle::Inner),
653 '/' if self.second() != '/' => Some(DocStyle::Outer),
655 _ => None,
656 };
657
658 self.eat_until(b'\n');
659 LineComment { doc_style }
660 }
661
662 fn block_comment(&mut self) -> TokenKind {
663 if true {
if !(self.prev() == '/' && self.first() == '*') {
::core::panicking::panic("assertion failed: self.prev() == \'/\' && self.first() == \'*\'")
};
};debug_assert!(self.prev() == '/' && self.first() == '*');
664 self.bump();
665
666 let doc_style = match self.first() {
667 '!' => Some(DocStyle::Inner),
669 '*' if !#[allow(non_exhaustive_omitted_patterns)] match self.second() {
'*' | '/' => true,
_ => false,
}matches!(self.second(), '*' | '/') => Some(DocStyle::Outer),
672 _ => None,
673 };
674
675 let mut depth = 1usize;
676 while let Some(c) = self.bump() {
677 match c {
678 '/' if self.first() == '*' => {
679 self.bump();
680 depth += 1;
681 }
682 '*' if self.first() == '/' => {
683 self.bump();
684 depth -= 1;
685 if depth == 0 {
686 break;
690 }
691 }
692 _ => (),
693 }
694 }
695
696 BlockComment { doc_style, terminated: depth == 0 }
697 }
698
699 fn whitespace(&mut self) -> TokenKind {
700 if true {
if !is_whitespace(self.prev()) {
::core::panicking::panic("assertion failed: is_whitespace(self.prev())")
};
};debug_assert!(is_whitespace(self.prev()));
701 self.eat_while(is_whitespace);
702 Whitespace
703 }
704
705 fn raw_ident(&mut self) -> TokenKind {
706 if true {
if !(self.prev() == 'r' && self.first() == '#' &&
is_id_start(self.second())) {
::core::panicking::panic("assertion failed: self.prev() == \'r\' && self.first() == \'#\' && is_id_start(self.second())")
};
};debug_assert!(self.prev() == 'r' && self.first() == '#' && is_id_start(self.second()));
707 self.bump();
709 self.eat_identifier();
711 RawIdent
712 }
713
714 fn ident_or_unknown_prefix(&mut self) -> TokenKind {
715 if true {
if !is_id_start(self.prev()) {
::core::panicking::panic("assertion failed: is_id_start(self.prev())")
};
};debug_assert!(is_id_start(self.prev()));
716 self.eat_while(is_id_continue);
718 match self.first() {
721 '#' | '"' | '\'' => UnknownPrefix,
722 c if !c.is_ascii() && c.is_emoji_char() => self.invalid_ident(),
723 _ => Ident,
724 }
725 }
726
727 fn invalid_ident(&mut self) -> TokenKind {
728 self.eat_while(|c| {
730 const ZERO_WIDTH_JOINER: char = '\u{200d}';
731 is_id_continue(c) || (!c.is_ascii() && c.is_emoji_char()) || c == ZERO_WIDTH_JOINER
732 });
733 InvalidIdent
738 }
739
740 fn c_or_byte_string(
741 &mut self,
742 mk_kind: fn(bool) -> LiteralKind,
743 mk_kind_raw: fn(Option<u8>) -> LiteralKind,
744 single_quoted: Option<fn(bool) -> LiteralKind>,
745 ) -> TokenKind {
746 match (self.first(), self.second(), single_quoted) {
747 ('\'', _, Some(single_quoted)) => {
748 self.bump();
749 let terminated = self.single_quoted_string();
750 let suffix_start = self.pos_within_token();
751 if terminated {
752 self.eat_literal_suffix();
753 }
754 let kind = single_quoted(terminated);
755 Literal { kind, suffix_start }
756 }
757 ('"', _, _) => {
758 self.bump();
759 let terminated = self.double_quoted_string();
760 let suffix_start = self.pos_within_token();
761 if terminated {
762 self.eat_literal_suffix();
763 }
764 let kind = mk_kind(terminated);
765 Literal { kind, suffix_start }
766 }
767 ('r', '"', _) | ('r', '#', _) => {
768 self.bump();
769 let res = self.raw_double_quoted_string(2);
770 let suffix_start = self.pos_within_token();
771 if res.is_ok() {
772 self.eat_literal_suffix();
773 }
774 let kind = mk_kind_raw(res.ok());
775 Literal { kind, suffix_start }
776 }
777 _ => self.ident_or_unknown_prefix(),
778 }
779 }
780
781 fn number(&mut self, first_digit: char) -> LiteralKind {
782 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');
783 let mut base = Base::Decimal;
784 if first_digit == '0' {
785 match self.first() {
787 'b' => {
788 base = Base::Binary;
789 self.bump();
790 if !self.eat_decimal_digits() {
791 return Int { base, empty_int: true };
792 }
793 }
794 'o' => {
795 base = Base::Octal;
796 self.bump();
797 if !self.eat_decimal_digits() {
798 return Int { base, empty_int: true };
799 }
800 }
801 'x' => {
802 base = Base::Hexadecimal;
803 self.bump();
804 if !self.eat_hexadecimal_digits() {
805 return Int { base, empty_int: true };
806 }
807 }
808 '0'..='9' | '_' => {
810 self.eat_decimal_digits();
811 }
812
813 '.' | 'e' | 'E' => {}
815
816 _ => return Int { base, empty_int: false },
818 }
819 } else {
820 self.eat_decimal_digits();
822 }
823
824 match self.first() {
825 '.' if self.second() != '.' && !is_id_start(self.second()) => {
829 self.bump();
832 let mut empty_exponent = false;
833 if self.first().is_ascii_digit() {
834 self.eat_decimal_digits();
835 match self.first() {
836 'e' | 'E' => {
837 self.bump();
838 empty_exponent = !self.eat_float_exponent();
839 }
840 _ => (),
841 }
842 }
843 Float { base, empty_exponent }
844 }
845 'e' | 'E' => {
846 self.bump();
847 let empty_exponent = !self.eat_float_exponent();
848 Float { base, empty_exponent }
849 }
850 _ => Int { base, empty_int: false },
851 }
852 }
853
854 fn lifetime_or_char(&mut self) -> TokenKind {
855 if true {
if !(self.prev() == '\'') {
::core::panicking::panic("assertion failed: self.prev() == \'\\\'\'")
};
};debug_assert!(self.prev() == '\'');
856
857 let can_be_a_lifetime = if self.second() == '\'' {
858 false
860 } else {
861 is_id_start(self.first()) || self.first().is_ascii_digit()
865 };
866
867 if !can_be_a_lifetime {
868 let terminated = self.single_quoted_string();
869 let suffix_start = self.pos_within_token();
870 if terminated {
871 self.eat_literal_suffix();
872 }
873 let kind = Char { terminated };
874 return Literal { kind, suffix_start };
875 }
876
877 if self.first() == 'r' && self.second() == '#' && is_id_start(self.third()) {
878 self.bump();
880 self.bump();
881 self.bump();
882 self.eat_while(is_id_continue);
883 return RawLifetime;
884 }
885
886 let starts_with_number = self.first().is_ascii_digit();
889
890 self.bump();
894 self.eat_while(is_id_continue);
895
896 match self.first() {
897 '\'' => {
901 self.bump();
902 let kind = Char { terminated: true };
903 Literal { kind, suffix_start: self.pos_within_token() }
904 }
905 '#' if !starts_with_number => UnknownPrefixLifetime,
906 _ => Lifetime { starts_with_number },
907 }
908 }
909
910 fn single_quoted_string(&mut self) -> bool {
911 if true {
if !(self.prev() == '\'') {
::core::panicking::panic("assertion failed: self.prev() == \'\\\'\'")
};
};debug_assert!(self.prev() == '\'');
912 if self.second() == '\'' && self.first() != '\\' {
914 self.bump();
915 self.bump();
916 return true;
917 }
918
919 loop {
923 match self.first() {
924 '\'' => {
926 self.bump();
927 return true;
928 }
929 '/' => break,
932 '\n' if self.second() != '\'' => break,
934 EOF_CHAR if self.is_eof() => break,
936 '\\' => {
938 self.bump();
939 self.bump();
940 }
941 _ => {
943 self.bump();
944 }
945 }
946 }
947 false
949 }
950
951 fn double_quoted_string(&mut self) -> bool {
954 if true {
if !(self.prev() == '"') {
::core::panicking::panic("assertion failed: self.prev() == \'\"\'")
};
};debug_assert!(self.prev() == '"');
955 while let Some(c) = self.bump() {
956 match c {
957 '"' => {
958 return true;
959 }
960 '\\' if self.first() == '\\' || self.first() == '"' => {
961 self.bump();
963 }
964 _ => (),
965 }
966 }
967 false
969 }
970
971 pub fn guarded_double_quoted_string(&mut self) -> Option<GuardedStr> {
980 if true {
if !(self.prev() != '#') {
::core::panicking::panic("assertion failed: self.prev() != \'#\'")
};
};debug_assert!(self.prev() != '#');
981
982 let mut n_start_hashes: u32 = 0;
983 while self.first() == '#' {
984 n_start_hashes += 1;
985 self.bump();
986 }
987
988 if self.first() != '"' {
989 return None;
990 }
991 self.bump();
992 if true {
if !(self.prev() == '"') {
::core::panicking::panic("assertion failed: self.prev() == \'\"\'")
};
};debug_assert!(self.prev() == '"');
993
994 let terminated = self.double_quoted_string();
997 if !terminated {
998 let token_len = self.pos_within_token();
999 self.reset_pos_within_token();
1000
1001 return Some(GuardedStr { n_hashes: n_start_hashes, terminated: false, token_len });
1002 }
1003
1004 let mut n_end_hashes = 0;
1009 while self.first() == '#' && n_end_hashes < n_start_hashes {
1010 n_end_hashes += 1;
1011 self.bump();
1012 }
1013
1014 self.eat_literal_suffix();
1018
1019 let token_len = self.pos_within_token();
1020 self.reset_pos_within_token();
1021
1022 Some(GuardedStr { n_hashes: n_start_hashes, terminated: true, token_len })
1023 }
1024
1025 fn raw_double_quoted_string(&mut self, prefix_len: u32) -> Result<u8, RawStrError> {
1027 let n_hashes = self.raw_string_unvalidated(prefix_len)?;
1030 match u8::try_from(n_hashes) {
1032 Ok(num) => Ok(num),
1033 Err(_) => Err(RawStrError::TooManyDelimiters { found: n_hashes }),
1034 }
1035 }
1036
1037 fn raw_string_unvalidated(&mut self, prefix_len: u32) -> Result<u32, RawStrError> {
1038 if true {
if !(self.prev() == 'r') {
::core::panicking::panic("assertion failed: self.prev() == \'r\'")
};
};debug_assert!(self.prev() == 'r');
1039 let start_pos = self.pos_within_token();
1040 let mut possible_terminator_offset = None;
1041 let mut max_hashes = 0;
1042
1043 let mut eaten = 0;
1045 while self.first() == '#' {
1046 eaten += 1;
1047 self.bump();
1048 }
1049 let n_start_hashes = eaten;
1050
1051 match self.bump() {
1053 Some('"') => (),
1054 c => {
1055 let c = c.unwrap_or(EOF_CHAR);
1056 return Err(RawStrError::InvalidStarter { bad_char: c });
1057 }
1058 }
1059
1060 loop {
1063 self.eat_until(b'"');
1064
1065 if self.is_eof() {
1066 return Err(RawStrError::NoTerminator {
1067 expected: n_start_hashes,
1068 found: max_hashes,
1069 possible_terminator_offset,
1070 });
1071 }
1072
1073 self.bump();
1075
1076 let mut n_end_hashes = 0;
1082 while self.first() == '#' && n_end_hashes < n_start_hashes {
1083 n_end_hashes += 1;
1084 self.bump();
1085 }
1086
1087 if n_end_hashes == n_start_hashes {
1088 return Ok(n_start_hashes);
1089 } else if n_end_hashes > max_hashes {
1090 possible_terminator_offset =
1093 Some(self.pos_within_token() - start_pos - n_end_hashes + prefix_len);
1094 max_hashes = n_end_hashes;
1095 }
1096 }
1097 }
1098
1099 fn eat_decimal_digits(&mut self) -> bool {
1100 let mut has_digits = false;
1101 loop {
1102 match self.first() {
1103 '_' => {
1104 self.bump();
1105 }
1106 '0'..='9' => {
1107 has_digits = true;
1108 self.bump();
1109 }
1110 _ => break,
1111 }
1112 }
1113 has_digits
1114 }
1115
1116 fn eat_hexadecimal_digits(&mut self) -> bool {
1117 let mut has_digits = false;
1118 loop {
1119 match self.first() {
1120 '_' => {
1121 self.bump();
1122 }
1123 '0'..='9' | 'a'..='f' | 'A'..='F' => {
1124 has_digits = true;
1125 self.bump();
1126 }
1127 _ => break,
1128 }
1129 }
1130 has_digits
1131 }
1132
1133 fn eat_float_exponent(&mut self) -> bool {
1136 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');
1137 if self.first() == '-' || self.first() == '+' {
1138 self.bump();
1139 }
1140 self.eat_decimal_digits()
1141 }
1142
1143 fn eat_literal_suffix(&mut self) {
1145 self.eat_identifier();
1146 }
1147
1148 fn eat_identifier(&mut self) {
1151 if !is_id_start(self.first()) {
1152 return;
1153 }
1154 self.bump();
1155
1156 self.eat_while(is_id_continue);
1157 }
1158}