#![ allow( clippy ::std_instead_of_alloc ) ]
#![ allow( clippy ::std_instead_of_core ) ]
use crate ::error :: { ParseError, SourceLocation };
use alloc ::borrow ::Cow;
use alloc ::string :: { String, ToString };
use core ::fmt;
#[ derive( Debug, Clone ) ]
pub struct Split< 'a >
{
pub string: Cow< 'a, str >,
pub bounds: ( usize, usize ),
pub start: usize,
pub end: usize,
pub typ: SplitType,
pub was_quoted: bool,
}
#[ derive( Debug, Clone, PartialEq ) ]
pub enum SplitType
{
Delimiter,
NonDelimiter,
}
#[ derive( Debug, Clone ) ]
pub struct ZeroCopyRichItem< 'a >
{
pub inner: Split< 'a >,
pub kind: ZeroCopyTokenKind< 'a >,
pub adjusted_source_location: SourceLocation,
}
impl< 'a > ZeroCopyRichItem< 'a >
{
#[ must_use ]
pub fn new
(
inner: Split< 'a >,
kind: ZeroCopyTokenKind< 'a >,
adjusted_source_location: SourceLocation,
)
->
Self
{
Self
{
inner,
kind,
adjusted_source_location,
}
}
#[ must_use ]
pub fn source_location( &self ) -> SourceLocation
{
self.adjusted_source_location.clone()
}
#[ must_use ]
pub fn to_owned( &self ) -> RichItem< 'a >
{
RichItem ::new( self.inner.clone(), self.kind.to_owned(), self.adjusted_source_location.clone() )
}
}
#[ derive( Debug, Clone ) ]
pub struct RichItem< 'a >
{
pub inner: Split< 'a >,
pub kind: UnilangTokenKind,
pub adjusted_source_location: SourceLocation,
}
impl< 'a > RichItem< 'a >
{
#[ must_use ]
pub fn new
(
inner: Split< 'a >,
kind: UnilangTokenKind,
adjusted_source_location: SourceLocation,
)
->
Self
{
Self
{
inner,
kind,
adjusted_source_location,
}
}
#[ must_use ]
pub fn source_location( &self ) -> SourceLocation
{
self.adjusted_source_location.clone()
}
}
#[ derive( Debug, PartialEq, Eq, Clone ) ]
pub enum ZeroCopyTokenKind< 'a >
{
Identifier( &'a str ),
Number( &'a str ),
Operator( &'static str ),
Delimiter( &'static str ),
Unrecognized( &'a str ),
}
#[ derive( Debug, PartialEq, Eq, Clone ) ]
pub enum UnilangTokenKind
{
Identifier( String ),
Number( String ),
Operator( &'static str ),
Delimiter( &'static str ),
Unrecognized( String ),
}
impl ZeroCopyTokenKind< '_ >
{
#[ must_use ]
pub fn to_owned( &self ) -> UnilangTokenKind
{
match self
{
ZeroCopyTokenKind ::Identifier( s ) => UnilangTokenKind ::Identifier( (*s).to_string() ),
ZeroCopyTokenKind ::Number( s ) => UnilangTokenKind ::Number( (*s).to_string() ),
ZeroCopyTokenKind ::Operator( s ) => UnilangTokenKind ::Operator( s ),
ZeroCopyTokenKind ::Delimiter( s ) => UnilangTokenKind ::Delimiter( s ),
ZeroCopyTokenKind ::Unrecognized( s ) => UnilangTokenKind ::Unrecognized( (*s).to_string() ),
}
}
}
impl fmt ::Display for ZeroCopyTokenKind< '_ >
{
fn fmt( &self, f: &mut fmt ::Formatter< '_ > ) -> fmt ::Result
{
match self
{
ZeroCopyTokenKind ::Identifier( s ) | ZeroCopyTokenKind ::Unrecognized( s ) | ZeroCopyTokenKind ::Number( s ) | ZeroCopyTokenKind ::Operator( s ) | ZeroCopyTokenKind ::Delimiter( s ) => write!( f, "{s}" ),
}
}
}
impl fmt ::Display for UnilangTokenKind
{
fn fmt( &self, f: &mut fmt ::Formatter< '_ > ) -> fmt ::Result
{
match self
{
UnilangTokenKind ::Identifier( s ) | UnilangTokenKind ::Unrecognized( s ) | UnilangTokenKind ::Number( s ) => write!( f, "{s}" ),
UnilangTokenKind ::Operator( s ) | UnilangTokenKind ::Delimiter( s ) => write!( f, "{s}" ),
}
}
}
fn is_valid_identifier( s: &str ) -> bool
{
!s.is_empty()
&& s.chars()
.next()
.is_some_and( | c | c.is_ascii_lowercase() || c == '_' )
&& !s.ends_with( '-' )
&& s
.chars()
.all( | c | c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '-' )
}
pub fn classify_split_zero_copy< 'a >( s: &'a Split< 'a > ) -> Result< ( ZeroCopyTokenKind< 'a >, SourceLocation ), ParseError >
{
let original_location = SourceLocation ::StrSpan
{
start: s.start,
end: s.end,
};
let result = match s.string
{
Cow ::Borrowed( " :: " ) => Ok( ( ZeroCopyTokenKind ::Operator( " :: " ), original_location ) ),
Cow ::Borrowed( "::" ) => Ok( ( ZeroCopyTokenKind ::Operator( "::" ), original_location ) ),
Cow ::Borrowed( "?" ) => Ok( ( ZeroCopyTokenKind ::Operator( "?" ), original_location ) ),
Cow ::Borrowed( " : " ) => Ok( ( ZeroCopyTokenKind ::Operator( " : " ), original_location ) ),
Cow ::Borrowed( "." ) => Ok( ( ZeroCopyTokenKind ::Delimiter( "." ), original_location ) ),
Cow ::Borrowed( " " ) => Ok( ( ZeroCopyTokenKind ::Delimiter( " " ), original_location ) ),
Cow ::Borrowed( "\t" ) => Ok( ( ZeroCopyTokenKind ::Delimiter( "\t" ), original_location ) ),
Cow ::Borrowed( "\r" ) => Ok( ( ZeroCopyTokenKind ::Delimiter( "\r" ), original_location ) ),
Cow ::Borrowed( "\n" ) => Ok( ( ZeroCopyTokenKind ::Delimiter( "\n" ), original_location ) ),
Cow ::Borrowed( "#" ) => Ok( ( ZeroCopyTokenKind ::Delimiter( "#" ), original_location ) ),
Cow ::Borrowed( "!" ) => Ok( ( ZeroCopyTokenKind ::Unrecognized( "!" ), original_location ) ),
_ =>
{
if s.typ == SplitType ::Delimiter
{
if s.was_quoted
{
Ok( ( ZeroCopyTokenKind ::Identifier( s.string.as_ref() ), original_location ) )
}
else if s.string.parse :: < i64 >().is_ok()
{
Ok( ( ZeroCopyTokenKind ::Number( s.string.as_ref() ), original_location ) )
}
else if is_valid_identifier( s.string.as_ref() )
{
Ok( ( ZeroCopyTokenKind ::Identifier( s.string.as_ref() ), original_location ) )
}
else
{
Ok( ( ZeroCopyTokenKind ::Unrecognized( s.string.as_ref() ), original_location ) )
}
}
else
{
Ok( ( ZeroCopyTokenKind ::Unrecognized( s.string.as_ref() ), original_location ) )
}
}
};
result
}
pub fn classify_split( s: &Split< '_ > ) -> Result< ( UnilangTokenKind, SourceLocation ), ParseError >
{
let ( zero_copy_token, location ) = classify_split_zero_copy( s )?;
Ok( ( zero_copy_token.to_owned(), location ) )
}