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_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Option<DocStyle>>;
let _: ::core::cmp::AssertParamIsEq<Option<DocStyle>>;
let _: ::core::cmp::AssertParamIsEq<bool>;
let _: ::core::cmp::AssertParamIsEq<LiteralKind>;
let _: ::core::cmp::AssertParamIsEq<u32>;
}
}Eq)]
72pub enum TokenKind {
73 LineComment {
75 doc_style: Option<DocStyle>,
76 },
77
78 BlockComment {
83 doc_style: Option<DocStyle>,
84 terminated: bool,
85 },
86
87 Whitespace,
89
90 Frontmatter {
91 has_invalid_preceding_whitespace: bool,
92 invalid_infostring: bool,
93 },
94
95 Ident,
97
98 InvalidIdent,
100
101 RawIdent,
103
104 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_fields_are_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_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Base>;
let _: ::core::cmp::AssertParamIsEq<bool>;
let _: ::core::cmp::AssertParamIsEq<Option<u8>>;
let _: ::core::cmp::AssertParamIsEq<Option<u8>>;
let _: ::core::cmp::AssertParamIsEq<Option<u8>>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for LiteralKind {
#[inline]
fn partial_cmp(&self, other: &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_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u32>;
let _: ::core::cmp::AssertParamIsEq<bool>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for GuardedStr {
#[inline]
fn partial_cmp(&self, other: &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_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<char>;
let _: ::core::cmp::AssertParamIsEq<u32>;
let _: ::core::cmp::AssertParamIsEq<Option<u32>>;
}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for RawStrError {
#[inline]
fn partial_cmp(&self, other: &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_fields_are_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!(
377 c,
378 '\u{0009}' | '\u{0020}' )
382}
383
384pub fn is_id_start(c: char) -> bool {
388 c == '_' || unicode_ident::is_xid_start(c)
390}
391
392pub fn is_id_continue(c: char) -> bool {
396 unicode_ident::is_xid_continue(c)
397}
398
399pub fn is_ident(string: &str) -> bool {
401 let mut chars = string.chars();
402 if let Some(start) = chars.next() {
403 is_id_start(start) && chars.all(is_id_continue)
404 } else {
405 false
406 }
407}
408
409pub enum FrontmatterAllowed {
410 Yes,
411 No,
412}
413
414pub struct Cursor<'a> {
419 len_remaining: usize,
420 chars: Chars<'a>,
422 pub(crate) frontmatter_allowed: FrontmatterAllowed,
423 #[cfg(debug_assertions)]
424 prev: char,
425}
426
427const EOF_CHAR: char = '\0';
428
429impl<'a> Cursor<'a> {
430 pub fn new(input: &'a str, frontmatter_allowed: FrontmatterAllowed) -> Cursor<'a> {
431 Cursor {
432 len_remaining: input.len(),
433 chars: input.chars(),
434 frontmatter_allowed,
435 #[cfg(debug_assertions)]
436 prev: EOF_CHAR,
437 }
438 }
439
440 pub fn as_str(&self) -> &'a str {
441 self.chars.as_str()
442 }
443
444 pub(crate) fn prev(&self) -> char {
447 #[cfg(debug_assertions)]
448 {
449 self.prev
450 }
451
452 #[cfg(not(debug_assertions))]
453 {
454 EOF_CHAR
455 }
456 }
457
458 pub fn first(&self) -> char {
463 self.chars.clone().next().unwrap_or(EOF_CHAR)
465 }
466
467 pub(crate) fn second(&self) -> char {
469 let mut iter = self.chars.clone();
471 iter.next();
472 iter.next().unwrap_or(EOF_CHAR)
473 }
474
475 pub fn third(&self) -> char {
477 let mut iter = self.chars.clone();
479 iter.next();
480 iter.next();
481 iter.next().unwrap_or(EOF_CHAR)
482 }
483
484 pub(crate) fn is_eof(&self) -> bool {
486 self.chars.as_str().is_empty()
487 }
488
489 pub(crate) fn pos_within_token(&self) -> u32 {
491 (self.len_remaining - self.chars.as_str().len()) as u32
492 }
493
494 pub(crate) fn reset_pos_within_token(&mut self) {
496 self.len_remaining = self.chars.as_str().len();
497 }
498
499 pub(crate) fn bump(&mut self) -> Option<char> {
501 let c = self.chars.next()?;
502
503 #[cfg(debug_assertions)]
504 {
505 self.prev = c;
506 }
507
508 Some(c)
509 }
510
511 pub(crate) fn bump_bytes(&mut self, n: usize) {
513 self.chars = self.as_str()[n..].chars();
514 }
515
516 pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) {
518 while predicate(self.first()) && !self.is_eof() {
521 self.bump();
522 }
523 }
524
525 pub(crate) fn eat_until(&mut self, byte: u8) {
526 self.chars = match memchr::memchr(byte, self.as_str().as_bytes()) {
527 Some(index) => self.as_str()[index..].chars(),
528 None => "".chars(),
529 }
530 }
531
532 pub fn advance_token(&mut self) -> Token {
534 let Some(first_char) = self.bump() else {
535 return Token::new(TokenKind::Eof, 0);
536 };
537
538 let token_kind = match first_char {
539 c if #[allow(non_exhaustive_omitted_patterns)] match self.frontmatter_allowed {
FrontmatterAllowed::Yes => true,
_ => false,
}matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes)
540 && is_whitespace(c) =>
541 {
542 let mut last = first_char;
543 while is_whitespace(self.first()) {
544 let Some(c) = self.bump() else {
545 break;
546 };
547 last = c;
548 }
549 if last != '\n' && self.as_str().starts_with("---") {
553 self.bump();
554 self.frontmatter(true)
555 } else {
556 Whitespace
557 }
558 }
559 '-' if #[allow(non_exhaustive_omitted_patterns)] match self.frontmatter_allowed {
FrontmatterAllowed::Yes => true,
_ => false,
}matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes)
560 && self.as_str().starts_with("--") =>
561 {
562 self.frontmatter(false)
564 }
565 '/' => match self.first() {
567 '/' => self.line_comment(),
568 '*' => self.block_comment(),
569 _ => Slash,
570 },
571
572 c if is_whitespace(c) => self.whitespace(),
574
575 'r' => match (self.first(), self.second()) {
577 ('#', c1) if is_id_start(c1) => self.raw_ident(),
578 ('#', _) | ('"', _) => {
579 let res = self.raw_double_quoted_string(1);
580 let suffix_start = self.pos_within_token();
581 if res.is_ok() {
582 self.eat_literal_suffix();
583 }
584 let kind = RawStr { n_hashes: res.ok() };
585 Literal { kind, suffix_start }
586 }
587 _ => self.ident_or_unknown_prefix(),
588 },
589
590 'b' => self.c_or_byte_string(
592 |terminated| ByteStr { terminated },
593 |n_hashes| RawByteStr { n_hashes },
594 Some(|terminated| Byte { terminated }),
595 ),
596
597 'c' => self.c_or_byte_string(
599 |terminated| CStr { terminated },
600 |n_hashes| RawCStr { n_hashes },
601 None,
602 ),
603
604 c if is_id_start(c) => self.ident_or_unknown_prefix(),
607
608 c @ '0'..='9' => {
610 let literal_kind = self.number(c);
611 let suffix_start = self.pos_within_token();
612 self.eat_literal_suffix();
613 TokenKind::Literal { kind: literal_kind, suffix_start }
614 }
615
616 '#' if #[allow(non_exhaustive_omitted_patterns)] match self.first() {
'"' | '#' => true,
_ => false,
}matches!(self.first(), '"' | '#') => {
618 self.bump();
619 TokenKind::GuardedStrPrefix
620 }
621
622 ';' => Semi,
624 ',' => Comma,
625 '.' => Dot,
626 '(' => OpenParen,
627 ')' => CloseParen,
628 '{' => OpenBrace,
629 '}' => CloseBrace,
630 '[' => OpenBracket,
631 ']' => CloseBracket,
632 '@' => At,
633 '#' => Pound,
634 '~' => Tilde,
635 '?' => Question,
636 ':' => Colon,
637 '$' => Dollar,
638 '=' => Eq,
639 '!' => Bang,
640 '<' => Lt,
641 '>' => Gt,
642 '-' => Minus,
643 '&' => And,
644 '|' => Or,
645 '+' => Plus,
646 '*' => Star,
647 '^' => Caret,
648 '%' => Percent,
649
650 '\'' => self.lifetime_or_char(),
652
653 '"' => {
655 let terminated = self.double_quoted_string();
656 let suffix_start = self.pos_within_token();
657 if terminated {
658 self.eat_literal_suffix();
659 }
660 let kind = Str { terminated };
661 Literal { kind, suffix_start }
662 }
663 c if !c.is_ascii() && c.is_emoji_char() => self.invalid_ident(),
665 _ => Unknown,
666 };
667 if #[allow(non_exhaustive_omitted_patterns)] match self.frontmatter_allowed {
FrontmatterAllowed::Yes => true,
_ => false,
}matches!(self.frontmatter_allowed, FrontmatterAllowed::Yes)
668 && !#[allow(non_exhaustive_omitted_patterns)] match token_kind {
Whitespace => true,
_ => false,
}matches!(token_kind, Whitespace)
669 {
670 self.frontmatter_allowed = FrontmatterAllowed::No;
672 }
673 let res = Token::new(token_kind, self.pos_within_token());
674 self.reset_pos_within_token();
675 res
676 }
677
678 fn frontmatter(&mut self, has_invalid_preceding_whitespace: bool) -> TokenKind {
680 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());
681
682 let pos = self.pos_within_token();
683 self.eat_while(|c| c == '-');
684
685 let length_opening = self.pos_within_token() - pos + 1;
687
688 if true {
if !(length_opening >= 3) {
::core::panicking::panic("assertion failed: length_opening >= 3")
};
};debug_assert!(length_opening >= 3);
690
691 self.eat_while(|ch| ch != '\n' && is_horizontal_whitespace(ch));
693
694 if is_id_start(self.first()) {
697 self.bump();
698 self.eat_while(|c| is_id_continue(c) || c == '-' || c == '.');
699 }
700
701 self.eat_while(|ch| ch != '\n' && is_horizontal_whitespace(ch));
702 let invalid_infostring = self.first() != '\n';
703
704 let mut found = false;
705 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);
706 if let Some(closing) = self.as_str().find(&nl_fence_pattern) {
707 self.bump_bytes(closing + nl_fence_pattern.len());
709 self.eat_until(b'\n');
717 found = true;
718 }
719
720 if !found {
721 let mut rest = self.as_str();
725 let mut potential_closing = rest
728 .find("\n---")
729 .map(|x| x + 1)
733 .or_else(|| rest.find("\nuse "))
734 .or_else(|| rest.find("\n//!"))
735 .or_else(|| rest.find("\n#!["));
736
737 if potential_closing.is_none() {
738 let mut base_index = 0;
741 while let Some(closing) = rest.find("---") {
742 let preceding_chars_start = rest[..closing].rfind("\n").map_or(0, |i| i + 1);
743 if rest[preceding_chars_start..closing].chars().all(is_horizontal_whitespace) {
744 potential_closing = Some(closing + base_index);
746 break;
747 } else {
748 rest = &rest[closing + 3..];
749 base_index += closing + 3;
750 }
751 }
752 }
753
754 if let Some(potential_closing) = potential_closing {
755 self.bump_bytes(potential_closing);
757 self.eat_until(b'\n');
758 } else {
759 self.eat_while(|_| true);
761 }
762 }
763
764 Frontmatter { has_invalid_preceding_whitespace, invalid_infostring }
765 }
766
767 fn line_comment(&mut self) -> TokenKind {
768 if true {
if !(self.prev() == '/' && self.first() == '/') {
::core::panicking::panic("assertion failed: self.prev() == \'/\' && self.first() == \'/\'")
};
};debug_assert!(self.prev() == '/' && self.first() == '/');
769 self.bump();
770
771 let doc_style = match self.first() {
772 '!' => Some(DocStyle::Inner),
774 '/' if self.second() != '/' => Some(DocStyle::Outer),
776 _ => None,
777 };
778
779 self.eat_until(b'\n');
780 LineComment { doc_style }
781 }
782
783 fn block_comment(&mut self) -> TokenKind {
784 if true {
if !(self.prev() == '/' && self.first() == '*') {
::core::panicking::panic("assertion failed: self.prev() == \'/\' && self.first() == \'*\'")
};
};debug_assert!(self.prev() == '/' && self.first() == '*');
785 self.bump();
786
787 let doc_style = match self.first() {
788 '!' => Some(DocStyle::Inner),
790 '*' if !#[allow(non_exhaustive_omitted_patterns)] match self.second() {
'*' | '/' => true,
_ => false,
}matches!(self.second(), '*' | '/') => Some(DocStyle::Outer),
793 _ => None,
794 };
795
796 let mut depth = 1usize;
797 while let Some(c) = self.bump() {
798 match c {
799 '/' if self.first() == '*' => {
800 self.bump();
801 depth += 1;
802 }
803 '*' if self.first() == '/' => {
804 self.bump();
805 depth -= 1;
806 if depth == 0 {
807 break;
811 }
812 }
813 _ => (),
814 }
815 }
816
817 BlockComment { doc_style, terminated: depth == 0 }
818 }
819
820 fn whitespace(&mut self) -> TokenKind {
821 if true {
if !is_whitespace(self.prev()) {
::core::panicking::panic("assertion failed: is_whitespace(self.prev())")
};
};debug_assert!(is_whitespace(self.prev()));
822 self.eat_while(is_whitespace);
823 Whitespace
824 }
825
826 fn raw_ident(&mut self) -> TokenKind {
827 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()));
828 self.bump();
830 self.eat_identifier();
832 RawIdent
833 }
834
835 fn ident_or_unknown_prefix(&mut self) -> TokenKind {
836 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()));
837 self.eat_while(is_id_continue);
839 match self.first() {
842 '#' | '"' | '\'' => UnknownPrefix,
843 c if !c.is_ascii() && c.is_emoji_char() => self.invalid_ident(),
844 _ => Ident,
845 }
846 }
847
848 fn invalid_ident(&mut self) -> TokenKind {
849 self.eat_while(|c| {
851 const ZERO_WIDTH_JOINER: char = '\u{200d}';
852 is_id_continue(c) || (!c.is_ascii() && c.is_emoji_char()) || c == ZERO_WIDTH_JOINER
853 });
854 InvalidIdent
859 }
860
861 fn c_or_byte_string(
862 &mut self,
863 mk_kind: fn(bool) -> LiteralKind,
864 mk_kind_raw: fn(Option<u8>) -> LiteralKind,
865 single_quoted: Option<fn(bool) -> LiteralKind>,
866 ) -> TokenKind {
867 match (self.first(), self.second(), single_quoted) {
868 ('\'', _, Some(single_quoted)) => {
869 self.bump();
870 let terminated = self.single_quoted_string();
871 let suffix_start = self.pos_within_token();
872 if terminated {
873 self.eat_literal_suffix();
874 }
875 let kind = single_quoted(terminated);
876 Literal { kind, suffix_start }
877 }
878 ('"', _, _) => {
879 self.bump();
880 let terminated = self.double_quoted_string();
881 let suffix_start = self.pos_within_token();
882 if terminated {
883 self.eat_literal_suffix();
884 }
885 let kind = mk_kind(terminated);
886 Literal { kind, suffix_start }
887 }
888 ('r', '"', _) | ('r', '#', _) => {
889 self.bump();
890 let res = self.raw_double_quoted_string(2);
891 let suffix_start = self.pos_within_token();
892 if res.is_ok() {
893 self.eat_literal_suffix();
894 }
895 let kind = mk_kind_raw(res.ok());
896 Literal { kind, suffix_start }
897 }
898 _ => self.ident_or_unknown_prefix(),
899 }
900 }
901
902 fn number(&mut self, first_digit: char) -> LiteralKind {
903 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');
904 let mut base = Base::Decimal;
905 if first_digit == '0' {
906 match self.first() {
908 'b' => {
909 base = Base::Binary;
910 self.bump();
911 if !self.eat_decimal_digits() {
912 return Int { base, empty_int: true };
913 }
914 }
915 'o' => {
916 base = Base::Octal;
917 self.bump();
918 if !self.eat_decimal_digits() {
919 return Int { base, empty_int: true };
920 }
921 }
922 'x' => {
923 base = Base::Hexadecimal;
924 self.bump();
925 if !self.eat_hexadecimal_digits() {
926 return Int { base, empty_int: true };
927 }
928 }
929 '0'..='9' | '_' => {
931 self.eat_decimal_digits();
932 }
933
934 '.' | 'e' | 'E' => {}
936
937 _ => return Int { base, empty_int: false },
939 }
940 } else {
941 self.eat_decimal_digits();
943 }
944
945 match self.first() {
946 '.' if self.second() != '.' && !is_id_start(self.second()) => {
950 self.bump();
953 let mut empty_exponent = false;
954 if self.first().is_ascii_digit() {
955 self.eat_decimal_digits();
956 match self.first() {
957 'e' | 'E' => {
958 self.bump();
959 empty_exponent = !self.eat_float_exponent();
960 }
961 _ => (),
962 }
963 }
964 Float { base, empty_exponent }
965 }
966 'e' | 'E' => {
967 self.bump();
968 let empty_exponent = !self.eat_float_exponent();
969 Float { base, empty_exponent }
970 }
971 _ => Int { base, empty_int: false },
972 }
973 }
974
975 fn lifetime_or_char(&mut self) -> TokenKind {
976 if true {
if !(self.prev() == '\'') {
::core::panicking::panic("assertion failed: self.prev() == \'\\\'\'")
};
};debug_assert!(self.prev() == '\'');
977
978 let can_be_a_lifetime = if self.second() == '\'' {
979 false
981 } else {
982 is_id_start(self.first()) || self.first().is_ascii_digit()
986 };
987
988 if !can_be_a_lifetime {
989 let terminated = self.single_quoted_string();
990 let suffix_start = self.pos_within_token();
991 if terminated {
992 self.eat_literal_suffix();
993 }
994 let kind = Char { terminated };
995 return Literal { kind, suffix_start };
996 }
997
998 if self.first() == 'r' && self.second() == '#' && is_id_start(self.third()) {
999 self.bump();
1001 self.bump();
1002 self.bump();
1003 self.eat_while(is_id_continue);
1004 return RawLifetime;
1005 }
1006
1007 let starts_with_number = self.first().is_ascii_digit();
1010
1011 self.bump();
1015 self.eat_while(is_id_continue);
1016
1017 match self.first() {
1018 '\'' => {
1022 self.bump();
1023 let kind = Char { terminated: true };
1024 Literal { kind, suffix_start: self.pos_within_token() }
1025 }
1026 '#' if !starts_with_number => UnknownPrefixLifetime,
1027 _ => Lifetime { starts_with_number },
1028 }
1029 }
1030
1031 fn single_quoted_string(&mut self) -> bool {
1032 if true {
if !(self.prev() == '\'') {
::core::panicking::panic("assertion failed: self.prev() == \'\\\'\'")
};
};debug_assert!(self.prev() == '\'');
1033 if self.second() == '\'' && self.first() != '\\' {
1035 self.bump();
1036 self.bump();
1037 return true;
1038 }
1039
1040 loop {
1044 match self.first() {
1045 '\'' => {
1047 self.bump();
1048 return true;
1049 }
1050 '/' => break,
1053 '\n' if self.second() != '\'' => break,
1055 EOF_CHAR if self.is_eof() => break,
1057 '\\' => {
1059 self.bump();
1060 self.bump();
1061 }
1062 _ => {
1064 self.bump();
1065 }
1066 }
1067 }
1068 false
1070 }
1071
1072 fn double_quoted_string(&mut self) -> bool {
1075 if true {
if !(self.prev() == '"') {
::core::panicking::panic("assertion failed: self.prev() == \'\"\'")
};
};debug_assert!(self.prev() == '"');
1076 while let Some(c) = self.bump() {
1077 match c {
1078 '"' => {
1079 return true;
1080 }
1081 '\\' if self.first() == '\\' || self.first() == '"' => {
1082 self.bump();
1084 }
1085 _ => (),
1086 }
1087 }
1088 false
1090 }
1091
1092 pub fn guarded_double_quoted_string(&mut self) -> Option<GuardedStr> {
1101 if true {
if !(self.prev() != '#') {
::core::panicking::panic("assertion failed: self.prev() != \'#\'")
};
};debug_assert!(self.prev() != '#');
1102
1103 let mut n_start_hashes: u32 = 0;
1104 while self.first() == '#' {
1105 n_start_hashes += 1;
1106 self.bump();
1107 }
1108
1109 if self.first() != '"' {
1110 return None;
1111 }
1112 self.bump();
1113 if true {
if !(self.prev() == '"') {
::core::panicking::panic("assertion failed: self.prev() == \'\"\'")
};
};debug_assert!(self.prev() == '"');
1114
1115 let terminated = self.double_quoted_string();
1118 if !terminated {
1119 let token_len = self.pos_within_token();
1120 self.reset_pos_within_token();
1121
1122 return Some(GuardedStr { n_hashes: n_start_hashes, terminated: false, token_len });
1123 }
1124
1125 let mut n_end_hashes = 0;
1130 while self.first() == '#' && n_end_hashes < n_start_hashes {
1131 n_end_hashes += 1;
1132 self.bump();
1133 }
1134
1135 self.eat_literal_suffix();
1139
1140 let token_len = self.pos_within_token();
1141 self.reset_pos_within_token();
1142
1143 Some(GuardedStr { n_hashes: n_start_hashes, terminated: true, token_len })
1144 }
1145
1146 fn raw_double_quoted_string(&mut self, prefix_len: u32) -> Result<u8, RawStrError> {
1148 let n_hashes = self.raw_string_unvalidated(prefix_len)?;
1151 match u8::try_from(n_hashes) {
1153 Ok(num) => Ok(num),
1154 Err(_) => Err(RawStrError::TooManyDelimiters { found: n_hashes }),
1155 }
1156 }
1157
1158 fn raw_string_unvalidated(&mut self, prefix_len: u32) -> Result<u32, RawStrError> {
1159 if true {
if !(self.prev() == 'r') {
::core::panicking::panic("assertion failed: self.prev() == \'r\'")
};
};debug_assert!(self.prev() == 'r');
1160 let start_pos = self.pos_within_token();
1161 let mut possible_terminator_offset = None;
1162 let mut max_hashes = 0;
1163
1164 let mut eaten = 0;
1166 while self.first() == '#' {
1167 eaten += 1;
1168 self.bump();
1169 }
1170 let n_start_hashes = eaten;
1171
1172 match self.bump() {
1174 Some('"') => (),
1175 c => {
1176 let c = c.unwrap_or(EOF_CHAR);
1177 return Err(RawStrError::InvalidStarter { bad_char: c });
1178 }
1179 }
1180
1181 loop {
1184 self.eat_until(b'"');
1185
1186 if self.is_eof() {
1187 return Err(RawStrError::NoTerminator {
1188 expected: n_start_hashes,
1189 found: max_hashes,
1190 possible_terminator_offset,
1191 });
1192 }
1193
1194 self.bump();
1196
1197 let mut n_end_hashes = 0;
1203 while self.first() == '#' && n_end_hashes < n_start_hashes {
1204 n_end_hashes += 1;
1205 self.bump();
1206 }
1207
1208 if n_end_hashes == n_start_hashes {
1209 return Ok(n_start_hashes);
1210 } else if n_end_hashes > max_hashes {
1211 possible_terminator_offset =
1214 Some(self.pos_within_token() - start_pos - n_end_hashes + prefix_len);
1215 max_hashes = n_end_hashes;
1216 }
1217 }
1218 }
1219
1220 fn eat_decimal_digits(&mut self) -> bool {
1221 let mut has_digits = false;
1222 loop {
1223 match self.first() {
1224 '_' => {
1225 self.bump();
1226 }
1227 '0'..='9' => {
1228 has_digits = true;
1229 self.bump();
1230 }
1231 _ => break,
1232 }
1233 }
1234 has_digits
1235 }
1236
1237 fn eat_hexadecimal_digits(&mut self) -> bool {
1238 let mut has_digits = false;
1239 loop {
1240 match self.first() {
1241 '_' => {
1242 self.bump();
1243 }
1244 '0'..='9' | 'a'..='f' | 'A'..='F' => {
1245 has_digits = true;
1246 self.bump();
1247 }
1248 _ => break,
1249 }
1250 }
1251 has_digits
1252 }
1253
1254 fn eat_float_exponent(&mut self) -> bool {
1257 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');
1258 if self.first() == '-' || self.first() == '+' {
1259 self.bump();
1260 }
1261 self.eat_decimal_digits()
1262 }
1263
1264 fn eat_literal_suffix(&mut self) {
1266 self.eat_identifier();
1267 }
1268
1269 fn eat_identifier(&mut self) {
1272 if !is_id_start(self.first()) {
1273 return;
1274 }
1275 self.bump();
1276
1277 self.eat_while(is_id_continue);
1278 }
1279}