use std::borrow::Cow;
#[derive(Debug, Clone)]
pub struct TokenStream {
inner: String,
}
impl TokenStream {
pub fn new() -> Self {
Self {
inner: String::new(),
}
}
pub fn append(&mut self, ident: Ident) {
self.push_space();
self.inner.push_str(ident.as_str())
}
pub fn combine(&mut self, other: &TokenStream) {
self.push_space();
self.inner.push_str(&other.inner)
}
pub fn as_str(&self) -> &str {
&self.inner
}
pub fn into_string(self) -> String {
self.inner
}
pub fn parse<T: std::str::FromStr>(self) -> Result<T, T::Err> {
self.into_string().parse()
}
pub(crate) fn push_space(&mut self) {
match self.last_char() {
None | Some(' ') => {}
_ => self.inner.push(' '),
}
}
pub fn push(&mut self, c: char) {
self.inner.push(c)
}
pub fn push_str(&mut self, str: &str) {
self.inner.push_str(str)
}
fn last_char(&self) -> Option<char> {
self.inner.chars().last()
}
}
impl Default for TokenStream {
fn default() -> Self {
Self::new()
}
}
impl std::iter::FromIterator<TokenStream> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenStream>>(iter: I) -> Self {
iter.into_iter()
.fold(None, |accum: Option<TokenStream>, n| {
let mut ts = accum.unwrap_or_else(TokenStream::new);
ts.combine(&n);
Some(ts)
})
.unwrap_or_else(TokenStream::new)
}
}
#[derive(Clone, Debug)]
pub struct Ident {
inner: Cow<'static, str>,
}
impl Ident {
pub fn new<T: Into<Cow<'static, str>>>(str: T) -> Self {
Self { inner: str.into() }
}
pub fn as_str(&self) -> &str {
&*self.inner
}
}
impl std::fmt::Display for Ident {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl PartialEq<&str> for Ident {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
#[derive(Copy, Clone)]
pub enum Delimiter {
Bracket,
Brace,
Parenthesis,
}
impl Delimiter {
pub fn open(self) -> char {
match self {
Delimiter::Bracket => '[',
Delimiter::Brace => '{',
Delimiter::Parenthesis => '(',
}
}
pub fn close(self) -> char {
match self {
Delimiter::Bracket => ']',
Delimiter::Brace => '}',
Delimiter::Parenthesis => ')',
}
}
}
pub struct Literal {
inner: String,
}
macro_rules! unsuffixed {
($ty:ty => $name:ident) => {
pub fn $name(n: $ty) -> Self {
Self {
inner: n.to_string(),
}
}
};
}
impl Literal {
unsuffixed!(usize => usize_unsuffixed);
unsuffixed!(u32 => u32_unsuffixed);
unsuffixed!(u16 => u16_unsuffixed);
unsuffixed!(u8 => u8_unsuffixed);
pub fn byte_string(s: &[u8]) -> Self {
Self {
inner: format!(
"b\"{}\"",
std::str::from_utf8(s).expect("Could not turn bytes into byte literal")
),
}
}
pub fn as_str(&self) -> &str {
&self.inner
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn accept_owned_and_borrowed() {
assert_eq!(
Ident::new("hello").as_str(),
Ident::new(String::from("hello")).as_str()
);
}
}
impl std::fmt::Display for TokenStream {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}