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",
&self.kind, "len", &&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]
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)]
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 UnknownPrefix,
114
115 UnknownPrefixLifetime,
120
121 RawLifetime,
124
125 GuardedStrPrefix,
130
131 Literal {
137 kind: LiteralKind,
138 suffix_start: u32,
139 },
140
141 Lifetime {
143 starts_with_number: bool,
144 },
145
146 Semi,
148 Comma,
150 Dot,
152 OpenParen,
154 CloseParen,
156 OpenBrace,
158 CloseBrace,
160 OpenBracket,
162 CloseBracket,
164 At,
166 Pound,
168 Tilde,
170 Question,
172 Colon,
174 Dollar,
176 Eq,
178 Bang,
180 Lt,
182 Gt,
184 Minus,
186 And,
188 Or,
190 Plus,
192 Star,
194 Slash,
196 Caret,
198 Percent,
200
201 Unknown,
203
204 Eof,
206}
207
208#[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)]
209pub enum DocStyle {
210 Outer,
211 Inner,
212}
213
214#[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)]
221pub enum LiteralKind {
222 Int { base: Base, empty_int: bool },
224 Float { base: Base, empty_exponent: bool },
226 Char { terminated: bool },
228 Byte { terminated: bool },
230 Str { terminated: bool },
232 ByteStr { terminated: bool },
234 CStr { terminated: bool },
236 RawStr { n_hashes: Option<u8> },
239 RawByteStr { n_hashes: Option<u8> },
242 RawCStr { n_hashes: Option<u8> },
244}
245
246#[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)]
251pub struct GuardedStr {
252 pub n_hashes: u32,
253 pub terminated: bool,
254 pub token_len: u32,
255}
256
257#[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)]
258pub enum RawStrError {
259 InvalidStarter { bad_char: char },
261 NoTerminator { expected: u32, found: u32, possible_terminator_offset: Option<u32> },
265 TooManyDelimiters { found: u32 },
267}
268
269#[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)]
271pub enum Base {
272 Binary = 2,
274 Octal = 8,
276 Decimal = 10,
278 Hexadecimal = 16,
280}
281
282pub fn strip_shebang(input: &str) -> Option<usize> {
285 if let Some(input_tail) = input.strip_prefix("#!") {
289 let next_non_whitespace_token =
292 tokenize(input_tail, FrontmatterAllowed::No).map(|tok| tok.kind).find(|tok| {
293 !#[allow(non_exhaustive_omitted_patterns)] match tok {
TokenKind::Whitespace | TokenKind::LineComment { doc_style: None } |
TokenKind::BlockComment { doc_style: None, .. } => true,
_ => false,
}matches!(
294 tok,
295 TokenKind::Whitespace
296 | TokenKind::LineComment { doc_style: None }
297 | TokenKind::BlockComment { doc_style: None, .. }
298 )
299 });
300 if next_non_whitespace_token != Some(TokenKind::OpenBracket) {
301 return Some(2 + input_tail.lines().next().unwrap_or_default().len());
303 }
304 }
305 None
306}
307
308#[inline]
311pub fn validate_raw_str(input: &str, prefix_len: u32) -> Result<(), RawStrError> {
312 if true {
if !!input.is_empty() {
::core::panicking::panic("assertion failed: !input.is_empty()")
};
};debug_assert!(!input.is_empty());
313 let mut cursor = Cursor::new(input, FrontmatterAllowed::No);
314 for _ in 0..prefix_len {
316 cursor.bump().unwrap();
317 }
318 cursor.raw_double_quoted_string(prefix_len).map(|_| ())
319}
320
321pub fn tokenize(
328 input: &str,
329 frontmatter_allowed: FrontmatterAllowed,
330) -> impl Iterator<Item = Token> {
331 let mut cursor = Cursor::new(input, frontmatter_allowed);
332 std::iter::from_fn(move || {
333 let token = cursor.advance_token();
334 if token.kind != TokenKind::Eof { Some(token) } else { None }
335 })
336}
337
338pub fn is_whitespace(c: char) -> bool {
342 #[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!(
348 c,
349 | '\u{000A}' | '\u{000B}' | '\u{000C}' | '\u{000D}' | '\u{0085}' | '\u{2028}' | '\u{2029}' | '\u{200E}' | '\u{200F}' | '\u{0009}' | '\u{0020}' )
366}
367
368pub fn is_horizontal_whitespace(c: char) -> bool {
370 #[allow(non_exhaustive_omitted_patterns)] match c {
'\u{0009}' | '\u{0020}' => true,
_ => false,
}matches!(
376 c,
377 '\u{0009}' | '\u{0020}' )
381}
382
383pub fn is_id_start(c: char) -> bool {
387 c == '_' || unicode_ident::is_xid_start(c)
389}
390
391pub fn is_id_continue(c: char) -> bool {
395 unicode_ident::is_xid_continue(c)
396}
397
398pub fn is_ident(string: &str) -> bool {
400 let mut chars = string.chars();
401 if let Some(start) = chars.next() {
402 is_id_start(start) && chars.all(is_id_continue)
403 } else {
404 false
405 }
406}
407
408pub enum FrontmatterAllowed {
409 Yes,
410 No,
411}
412
413pub struct Cursor<'a> {
418 len_remaining: usize,
419 chars: Chars<'a>,
421 pub(crate) frontmatter_allowed: FrontmatterAllowed,
422 #[cfg(debug_assertions)]
423 prev: char,
424}
425
426const EOF_CHAR: char = '\0';
427
428impl<'a> Cursor<'a> {
429 pub fn new(input: &'a str, frontmatter_allowed: FrontmatterAllowed) -> Cursor<'a> {
430 Cursor {
431 len_remaining: input.len(),
432 chars: input.chars(),
433 frontmatter_allowed,
434 #[cfg(debug_assertions)]
435 prev: EOF_CHAR,
436 }
437 }
438
439 pub fn as_str(&self) -> &'a str {
440 self.chars.as_str()
441 }
442
443 pub(crate) fn prev(&self) -> char {
446 #[cfg(debug_assertions)]
447 {
448 self.prev
449 }
450
451 #[cfg(not(debug_assertions))]
452 {
453 EOF_CHAR
454 }
455 }
456
457 pub fn first(&self) -> char {
462 self.chars.clone().next().unwrap_or(EOF_CHAR)
464 }
465
466 pub(crate) fn second(&self) -> char {
468 let mut iter = self.chars.clone();
470 iter.next();
471 iter.next().unwrap_or(EOF_CHAR)
472 }
473
474 pub fn third(&self) -> char {
476 let mut iter = self.chars.clone();
478 iter.next();
479 iter.next();
480 iter.next().unwrap_or(EOF_CHAR)
481 }
482
483 pub(crate) fn is_eof(&self) -> bool {
485 self.chars.as_str().is_empty()
486 }
487
488 pub(crate) fn pos_within_token(&self) -> u32 {
490 (self.len_remaining - self.chars.as_str().len()) as u32
491 }
492
493 pub(crate) fn reset_pos_within_token(&mut self) {
495 self.len_remaining = self.chars.as_str().len();
496 }
497
498 pub(crate) fn bump(&mut self) -> Option<char> {
500 let c = self.chars.next()?;
501
502 #[cfg(debug_assertions)]
503 {
504 self.prev = c;
505 }
506
507 Some(c)
508 }
509
510 pub(crate) fn bump_bytes(&mut self, n: usize) {
512 self.chars = self.as_str()[n..].chars();
513 }
514
515 pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) {
517 while predicate(self.first()) && !self.is_eof() {
520 self.bump();
521 }
522 }
523
524 pub(crate) fn eat_until(&mut self, byte: u8) {
525 self.chars = match memchr::memchr(byte, self.as_str().as_bytes()) {
526 Some(index) => self.as_str()[index..].chars(),
527 None => "".chars(),
528 }
529 }
530
531 pub fn advance_token(&mut self) -> Token {
533 let Some(first_char) = self.bump() else {
534 return Token::new(TokenKind::Eof, 0);
535 };
536
537 let token_kind = match first_char {
538 c if #[allow(non_exhaustive_omitted_patterns)] match self.frontmatter_allowed {
FrontmatterAllowed::Yes => true,
_ => false,
}matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes)
539 && is_whitespace(c) =>
540 {
541 let mut last = first_char;
542 while is_whitespace(self.first()) {
543 let Some(c) = self.bump() else {
544 break;
545 };
546 last = c;
547 }
548 if last != '\n' && self.as_str().starts_with("---") {
552 self.bump();
553 self.frontmatter(true)
554 } else {
555 Whitespace
556 }
557 }
558 '-' if #[allow(non_exhaustive_omitted_patterns)] match self.frontmatter_allowed {
FrontmatterAllowed::Yes => true,
_ => false,
}matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes)
559 && self.as_str().starts_with("--") =>
560 {
561 self.frontmatter(false)
563 }
564 '/' => match self.first() {
566 '/' => self.line_comment(),
567 '*' => self.block_comment(),
568 _ => Slash,
569 },
570
571 c if is_whitespace(c) => self.whitespace(),
573
574 'r' => match (self.first(), self.second()) {
576 ('#', c1) if is_id_start(c1) => self.raw_ident(),
577 ('#', _) | ('"', _) => {
578 let res = self.raw_double_quoted_string(1);
579 let suffix_start = self.pos_within_token();
580 if res.is_ok() {
581 self.eat_literal_suffix();
582 }
583 let kind = RawStr { n_hashes: res.ok() };
584 Literal { kind, suffix_start }
585 }
586 _ => self.ident_or_unknown_prefix(),
587 },
588
589 'b' => self.c_or_byte_string(
591 |terminated| ByteStr { terminated },
592 |n_hashes| RawByteStr { n_hashes },
593 Some(|terminated| Byte { terminated }),
594 ),
595
596 'c' => self.c_or_byte_string(
598 |terminated| CStr { terminated },
599 |n_hashes| RawCStr { n_hashes },
600 None,
601 ),
602
603 c if is_id_start(c) => self.ident_or_unknown_prefix(),
606
607 c @ '0'..='9' => {
609 let literal_kind = self.number(c);
610 let suffix_start = self.pos_within_token();
611 self.eat_literal_suffix();
612 TokenKind::Literal { kind: literal_kind, suffix_start }
613 }
614
615 '#' if #[allow(non_exhaustive_omitted_patterns)] match self.first() {
'"' | '#' => true,
_ => false,
}matches!(self.first(), '"' | '#') => {
617 self.bump();
618 TokenKind::GuardedStrPrefix
619 }
620
621 ';' => Semi,
623 ',' => Comma,
624 '.' => Dot,
625 '(' => OpenParen,
626 ')' => CloseParen,
627 '{' => OpenBrace,
628 '}' => CloseBrace,
629 '[' => OpenBracket,
630 ']' => CloseBracket,
631 '@' => At,
632 '#' => Pound,
633 '~' => Tilde,
634 '?' => Question,
635 ':' => Colon,
636 '$' => Dollar,
637 '=' => Eq,
638 '!' => Bang,
639 '<' => Lt,
640 '>' => Gt,
641 '-' => Minus,
642 '&' => And,
643 '|' => Or,
644 '+' => Plus,
645 '*' => Star,
646 '^' => Caret,
647 '%' => Percent,
648
649 '\'' => self.lifetime_or_char(),
651
652 '"' => {
654 let terminated = self.double_quoted_string();
655 let suffix_start = self.pos_within_token();
656 if terminated {
657 self.eat_literal_suffix();
658 }
659 let kind = Str { terminated };
660 Literal { kind, suffix_start }
661 }
662 c if !c.is_ascii() && c.is_emoji_char() => self.invalid_ident(),
664 _ => Unknown,
665 };
666 if #[allow(non_exhaustive_omitted_patterns)] match self.frontmatter_allowed {
FrontmatterAllowed::Yes => true,
_ => false,
}matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes)
667 && !#[allow(non_exhaustive_omitted_patterns)] match token_kind {
Whitespace => true,
_ => false,
}matches!(token_kind, Whitespace)
668 {
669 self.frontmatter_allowed = FrontmatterAllowed::No;
671 }
672 let res = Token::new(token_kind, self.pos_within_token());
673 self.reset_pos_within_token();
674 res
675 }
676
677 fn frontmatter(&mut self, has_invalid_preceding_whitespace: bool) -> TokenKind {
679 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());
680
681 let pos = self.pos_within_token();
682 self.eat_while(|c| c == '-');
683
684 let length_opening = self.pos_within_token() - pos + 1;
686
687 if true {
if !(length_opening >= 3) {
::core::panicking::panic("assertion failed: length_opening >= 3")
};
};debug_assert!(length_opening >= 3);
689
690 self.eat_while(|ch| ch != '\n' && is_horizontal_whitespace(ch));
692
693 if is_id_start(self.first()) {
696 self.bump();
697 self.eat_while(|c| is_id_continue(c) || c == '-' || c == '.');
698 }
699
700 self.eat_while(|ch| ch != '\n' && is_horizontal_whitespace(ch));
701 let invalid_infostring = self.first() != '\n';
702
703 let mut found = false;
704 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);
705 if let Some(closing) = self.as_str().find(&nl_fence_pattern) {
706 self.bump_bytes(closing + nl_fence_pattern.len());
708 self.eat_until(b'\n');
716 found = true;
717 }
718
719 if !found {
720 let mut rest = self.as_str();
724 let mut potential_closing = rest
727 .find("\n---")
728 .map(|x| x + 1)
732 .or_else(|| rest.find("\nuse "))
733 .or_else(|| rest.find("\n//!"))
734 .or_else(|| rest.find("\n#!["));
735
736 if potential_closing.is_none() {
737 let mut base_index = 0;
740 while let Some(closing) = rest.find("---") {
741 let preceding_chars_start = rest[..closing].rfind("\n").map_or(0, |i| i + 1);
742 if rest[preceding_chars_start..closing].chars().all(is_horizontal_whitespace) {
743 potential_closing = Some(closing + base_index);
745 break;
746 } else {
747 rest = &rest[closing + 3..];
748 base_index += closing + 3;
749 }
750 }
751 }
752
753 if let Some(potential_closing) = potential_closing {
754 self.bump_bytes(potential_closing);
756 self.eat_until(b'\n');
757 } else {
758 self.eat_while(|_| true);
760 }
761 }
762
763 Frontmatter { has_invalid_preceding_whitespace, invalid_infostring }
764 }
765
766 fn line_comment(&mut self) -> TokenKind {
767 if true {
if !(self.prev() == '/' && self.first() == '/') {
::core::panicking::panic("assertion failed: self.prev() == \'/\' && self.first() == \'/\'")
};
};debug_assert!(self.prev() == '/' && self.first() == '/');
768 self.bump();
769
770 let doc_style = match self.first() {
771 '!' => Some(DocStyle::Inner),
773 '/' if self.second() != '/' => Some(DocStyle::Outer),
775 _ => None,
776 };
777
778 self.eat_until(b'\n');
779 LineComment { doc_style }
780 }
781
782 fn block_comment(&mut self) -> TokenKind {
783 if true {
if !(self.prev() == '/' && self.first() == '*') {
::core::panicking::panic("assertion failed: self.prev() == \'/\' && self.first() == \'*\'")
};
};debug_assert!(self.prev() == '/' && self.first() == '*');
784 self.bump();
785
786 let doc_style = match self.first() {
787 '!' => Some(DocStyle::Inner),
789 '*' if !#[allow(non_exhaustive_omitted_patterns)] match self.second() {
'*' | '/' => true,
_ => false,
}matches!(self.second(), '*' | '/') => Some(DocStyle::Outer),
792 _ => None,
793 };
794
795 let mut depth = 1usize;
796 while let Some(c) = self.bump() {
797 match c {
798 '/' if self.first() == '*' => {
799 self.bump();
800 depth += 1;
801 }
802 '*' if self.first() == '/' => {
803 self.bump();
804 depth -= 1;
805 if depth == 0 {
806 break;
810 }
811 }
812 _ => (),
813 }
814 }
815
816 BlockComment { doc_style, terminated: depth == 0 }
817 }
818
819 fn whitespace(&mut self) -> TokenKind {
820 if true {
if !is_whitespace(self.prev()) {
::core::panicking::panic("assertion failed: is_whitespace(self.prev())")
};
};debug_assert!(is_whitespace(self.prev()));
821 self.eat_while(is_whitespace);
822 Whitespace
823 }
824
825 fn raw_ident(&mut self) -> TokenKind {
826 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()));
827 self.bump();
829 self.eat_identifier();
831 RawIdent
832 }
833
834 fn ident_or_unknown_prefix(&mut self) -> TokenKind {
835 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()));
836 self.eat_while(is_id_continue);
838 match self.first() {
841 '#' | '"' | '\'' => UnknownPrefix,
842 c if !c.is_ascii() && c.is_emoji_char() => self.invalid_ident(),
843 _ => Ident,
844 }
845 }
846
847 fn invalid_ident(&mut self) -> TokenKind {
848 self.eat_while(|c| {
850 const ZERO_WIDTH_JOINER: char = '\u{200d}';
851 is_id_continue(c) || (!c.is_ascii() && c.is_emoji_char()) || c == ZERO_WIDTH_JOINER
852 });
853 InvalidIdent
858 }
859
860 fn c_or_byte_string(
861 &mut self,
862 mk_kind: fn(bool) -> LiteralKind,
863 mk_kind_raw: fn(Option<u8>) -> LiteralKind,
864 single_quoted: Option<fn(bool) -> LiteralKind>,
865 ) -> TokenKind {
866 match (self.first(), self.second(), single_quoted) {
867 ('\'', _, Some(single_quoted)) => {
868 self.bump();
869 let terminated = self.single_quoted_string();
870 let suffix_start = self.pos_within_token();
871 if terminated {
872 self.eat_literal_suffix();
873 }
874 let kind = single_quoted(terminated);
875 Literal { kind, suffix_start }
876 }
877 ('"', _, _) => {
878 self.bump();
879 let terminated = self.double_quoted_string();
880 let suffix_start = self.pos_within_token();
881 if terminated {
882 self.eat_literal_suffix();
883 }
884 let kind = mk_kind(terminated);
885 Literal { kind, suffix_start }
886 }
887 ('r', '"', _) | ('r', '#', _) => {
888 self.bump();
889 let res = self.raw_double_quoted_string(2);
890 let suffix_start = self.pos_within_token();
891 if res.is_ok() {
892 self.eat_literal_suffix();
893 }
894 let kind = mk_kind_raw(res.ok());
895 Literal { kind, suffix_start }
896 }
897 _ => self.ident_or_unknown_prefix(),
898 }
899 }
900
901 fn number(&mut self, first_digit: char) -> LiteralKind {
902 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');
903 let mut base = Base::Decimal;
904 if first_digit == '0' {
905 match self.first() {
907 'b' => {
908 base = Base::Binary;
909 self.bump();
910 if !self.eat_decimal_digits() {
911 return Int { base, empty_int: true };
912 }
913 }
914 'o' => {
915 base = Base::Octal;
916 self.bump();
917 if !self.eat_decimal_digits() {
918 return Int { base, empty_int: true };
919 }
920 }
921 'x' => {
922 base = Base::Hexadecimal;
923 self.bump();
924 if !self.eat_hexadecimal_digits() {
925 return Int { base, empty_int: true };
926 }
927 }
928 '0'..='9' | '_' => {
930 self.eat_decimal_digits();
931 }
932
933 '.' | 'e' | 'E' => {}
935
936 _ => return Int { base, empty_int: false },
938 }
939 } else {
940 self.eat_decimal_digits();
942 }
943
944 match self.first() {
945 '.' if self.second() != '.' && !is_id_start(self.second()) => {
949 self.bump();
952 let mut empty_exponent = false;
953 if self.first().is_ascii_digit() {
954 self.eat_decimal_digits();
955 match self.first() {
956 'e' | 'E' => {
957 self.bump();
958 empty_exponent = !self.eat_float_exponent();
959 }
960 _ => (),
961 }
962 }
963 Float { base, empty_exponent }
964 }
965 'e' | 'E' => {
966 self.bump();
967 let empty_exponent = !self.eat_float_exponent();
968 Float { base, empty_exponent }
969 }
970 _ => Int { base, empty_int: false },
971 }
972 }
973
974 fn lifetime_or_char(&mut self) -> TokenKind {
975 if true {
if !(self.prev() == '\'') {
::core::panicking::panic("assertion failed: self.prev() == \'\\\'\'")
};
};debug_assert!(self.prev() == '\'');
976
977 let can_be_a_lifetime = if self.second() == '\'' {
978 false
980 } else {
981 is_id_start(self.first()) || self.first().is_ascii_digit()
985 };
986
987 if !can_be_a_lifetime {
988 let terminated = self.single_quoted_string();
989 let suffix_start = self.pos_within_token();
990 if terminated {
991 self.eat_literal_suffix();
992 }
993 let kind = Char { terminated };
994 return Literal { kind, suffix_start };
995 }
996
997 if self.first() == 'r' && self.second() == '#' && is_id_start(self.third()) {
998 self.bump();
1000 self.bump();
1001 self.bump();
1002 self.eat_while(is_id_continue);
1003 return RawLifetime;
1004 }
1005
1006 let starts_with_number = self.first().is_ascii_digit();
1009
1010 self.bump();
1014 self.eat_while(is_id_continue);
1015
1016 match self.first() {
1017 '\'' => {
1021 self.bump();
1022 let kind = Char { terminated: true };
1023 Literal { kind, suffix_start: self.pos_within_token() }
1024 }
1025 '#' if !starts_with_number => UnknownPrefixLifetime,
1026 _ => Lifetime { starts_with_number },
1027 }
1028 }
1029
1030 fn single_quoted_string(&mut self) -> bool {
1031 if true {
if !(self.prev() == '\'') {
::core::panicking::panic("assertion failed: self.prev() == \'\\\'\'")
};
};debug_assert!(self.prev() == '\'');
1032 if self.second() == '\'' && self.first() != '\\' {
1034 self.bump();
1035 self.bump();
1036 return true;
1037 }
1038
1039 loop {
1043 match self.first() {
1044 '\'' => {
1046 self.bump();
1047 return true;
1048 }
1049 '/' => break,
1052 '\n' if self.second() != '\'' => break,
1054 EOF_CHAR if self.is_eof() => break,
1056 '\\' => {
1058 self.bump();
1059 self.bump();
1060 }
1061 _ => {
1063 self.bump();
1064 }
1065 }
1066 }
1067 false
1069 }
1070
1071 fn double_quoted_string(&mut self) -> bool {
1074 if true {
if !(self.prev() == '"') {
::core::panicking::panic("assertion failed: self.prev() == \'\"\'")
};
};debug_assert!(self.prev() == '"');
1075 while let Some(c) = self.bump() {
1076 match c {
1077 '"' => {
1078 return true;
1079 }
1080 '\\' if self.first() == '\\' || self.first() == '"' => {
1081 self.bump();
1083 }
1084 _ => (),
1085 }
1086 }
1087 false
1089 }
1090
1091 pub fn guarded_double_quoted_string(&mut self) -> Option<GuardedStr> {
1100 if true {
if !(self.prev() != '#') {
::core::panicking::panic("assertion failed: self.prev() != \'#\'")
};
};debug_assert!(self.prev() != '#');
1101
1102 let mut n_start_hashes: u32 = 0;
1103 while self.first() == '#' {
1104 n_start_hashes += 1;
1105 self.bump();
1106 }
1107
1108 if self.first() != '"' {
1109 return None;
1110 }
1111 self.bump();
1112 if true {
if !(self.prev() == '"') {
::core::panicking::panic("assertion failed: self.prev() == \'\"\'")
};
};debug_assert!(self.prev() == '"');
1113
1114 let terminated = self.double_quoted_string();
1117 if !terminated {
1118 let token_len = self.pos_within_token();
1119 self.reset_pos_within_token();
1120
1121 return Some(GuardedStr { n_hashes: n_start_hashes, terminated: false, token_len });
1122 }
1123
1124 let mut n_end_hashes = 0;
1129 while self.first() == '#' && n_end_hashes < n_start_hashes {
1130 n_end_hashes += 1;
1131 self.bump();
1132 }
1133
1134 self.eat_literal_suffix();
1138
1139 let token_len = self.pos_within_token();
1140 self.reset_pos_within_token();
1141
1142 Some(GuardedStr { n_hashes: n_start_hashes, terminated: true, token_len })
1143 }
1144
1145 fn raw_double_quoted_string(&mut self, prefix_len: u32) -> Result<u8, RawStrError> {
1147 let n_hashes = self.raw_string_unvalidated(prefix_len)?;
1150 match u8::try_from(n_hashes) {
1152 Ok(num) => Ok(num),
1153 Err(_) => Err(RawStrError::TooManyDelimiters { found: n_hashes }),
1154 }
1155 }
1156
1157 fn raw_string_unvalidated(&mut self, prefix_len: u32) -> Result<u32, RawStrError> {
1158 if true {
if !(self.prev() == 'r') {
::core::panicking::panic("assertion failed: self.prev() == \'r\'")
};
};debug_assert!(self.prev() == 'r');
1159 let start_pos = self.pos_within_token();
1160 let mut possible_terminator_offset = None;
1161 let mut max_hashes = 0;
1162
1163 let mut eaten = 0;
1165 while self.first() == '#' {
1166 eaten += 1;
1167 self.bump();
1168 }
1169 let n_start_hashes = eaten;
1170
1171 match self.bump() {
1173 Some('"') => (),
1174 c => {
1175 let c = c.unwrap_or(EOF_CHAR);
1176 return Err(RawStrError::InvalidStarter { bad_char: c });
1177 }
1178 }
1179
1180 loop {
1183 self.eat_until(b'"');
1184
1185 if self.is_eof() {
1186 return Err(RawStrError::NoTerminator {
1187 expected: n_start_hashes,
1188 found: max_hashes,
1189 possible_terminator_offset,
1190 });
1191 }
1192
1193 self.bump();
1195
1196 let mut n_end_hashes = 0;
1202 while self.first() == '#' && n_end_hashes < n_start_hashes {
1203 n_end_hashes += 1;
1204 self.bump();
1205 }
1206
1207 if n_end_hashes == n_start_hashes {
1208 return Ok(n_start_hashes);
1209 } else if n_end_hashes > max_hashes {
1210 possible_terminator_offset =
1213 Some(self.pos_within_token() - start_pos - n_end_hashes + prefix_len);
1214 max_hashes = n_end_hashes;
1215 }
1216 }
1217 }
1218
1219 fn eat_decimal_digits(&mut self) -> bool {
1220 let mut has_digits = false;
1221 loop {
1222 match self.first() {
1223 '_' => {
1224 self.bump();
1225 }
1226 '0'..='9' => {
1227 has_digits = true;
1228 self.bump();
1229 }
1230 _ => break,
1231 }
1232 }
1233 has_digits
1234 }
1235
1236 fn eat_hexadecimal_digits(&mut self) -> bool {
1237 let mut has_digits = false;
1238 loop {
1239 match self.first() {
1240 '_' => {
1241 self.bump();
1242 }
1243 '0'..='9' | 'a'..='f' | 'A'..='F' => {
1244 has_digits = true;
1245 self.bump();
1246 }
1247 _ => break,
1248 }
1249 }
1250 has_digits
1251 }
1252
1253 fn eat_float_exponent(&mut self) -> bool {
1256 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');
1257 if self.first() == '-' || self.first() == '+' {
1258 self.bump();
1259 }
1260 self.eat_decimal_digits()
1261 }
1262
1263 fn eat_literal_suffix(&mut self) {
1265 self.eat_identifier();
1266 }
1267
1268 fn eat_identifier(&mut self) {
1271 if !is_id_start(self.first()) {
1272 return;
1273 }
1274 self.bump();
1275
1276 self.eat_while(is_id_continue);
1277 }
1278}