use std::{ fmt::Display, ops::{Add, AddAssign, Range}, }; use logos::Logos; #[derive(Logos, Debug, PartialEq, derive_more::Display, Clone)] #[logos(skip r"[ \t\n\f]+")] pub enum Token { #[token("{")] #[display(fmt = "{{")] LeftCurly, #[token("}")] #[display(fmt = "}}")] RightCurly, #[token("(")] #[display(fmt = "(")] LeftParen, #[token(")")] #[display(fmt = ")")] RightParen, #[token(";")] #[display(fmt = ";")] Semicolon, #[token(":")] #[display(fmt = ":")] Colon, #[token("<")] #[display(fmt = "<")] LeftArrow, #[token(">")] #[display(fmt = ">")] RightArrow, #[token(",")] #[display(fmt = ",")] Comma, #[token("=")] #[display(fmt = "=")] Equals, #[token(".")] #[display(fmt = ".")] Dot, // why #[regex("\"(?s:[^\"\\\\]|\\\\.)*\"", |lex| lex.slice().strip_prefix('"')?.strip_suffix('"').map(ToOwned::to_owned))] #[display(fmt = "\"{_0}\"")] StringLiteral(String), #[regex(r"'.'", |lex| lex.slice().strip_prefix('\'')?.strip_suffix('\'')?.parse().ok())] #[display(fmt = "{_0}")] CharLiteral(char), #[regex(r#"(-)?\d+"#, |lex| lex.slice().parse().ok())] #[display(fmt = "{_0}")] NumberLiteral(i64), #[regex( "(ptr|u8|i8|u16|i16|u32|i32|u64|i64|f32|f64)", |lex| NumberSuffix::lexer(lex.slice()).next().and_then(Result::ok) )] #[display(fmt = "{_0}")] NumberSuffix(NumberSuffix), #[regex(r#"[a-zA-Z_][a-zA-Z\d_]*"#, |lex| Ident::lexer(lex.slice()).next().and_then(Result::ok))] #[display(fmt = "{_0}")] Ident(Ident), #[regex(r"//.*", |lex| lex.slice().parse().ok())] #[display(fmt = "//{_0}")] Comment(String), } #[derive(Logos, Debug, Clone, PartialEq, Eq, derive_more::Display)] pub enum Ident { #[token("Module")] #[display(fmt = "Module")] Module, #[token("Interface")] #[display(fmt = "Interface")] Interface, #[token("Function")] #[display(fmt = "Function")] Function, #[token("Constant")] #[display(fmt = "Constant")] Constant, #[token("Structure")] #[display(fmt = "Structure")] Structure, #[token("Alias")] #[display(fmt = "Alias")] Alias, #[token("Enumeration")] #[display(fmt = "Enumeration")] Enumeration, #[token("Use")] #[display(fmt = "Use")] Use, #[token("Make")] #[display(fmt = "Make")] Make, #[token("Takes")] #[display(fmt = "Takes")] Takes, #[token("Returns")] #[display(fmt = "Returns")] Returns, #[token("_")] #[display(fmt = "_")] Underscore, #[regex(r"[a-zA-Z_][a-zA-Z\d_]*", |lex| lex.slice().parse().ok())] #[display(fmt = "{_0}")] Other(String), } #[derive(Logos, Debug, Clone, Copy, PartialEq, Eq, derive_more::Display)] pub enum NumberSuffix { #[token("ptr")] #[display(fmt = "ptr")] Ptr, #[token("u8")] #[display(fmt = "u8")] U8, #[token("i8")] #[display(fmt = "i8")] I8, #[token("u16")] #[display(fmt = "u16")] U16, #[token("i16")] #[display(fmt = "i16")] I16, #[token("u32")] #[display(fmt = "u32")] U32, #[token("i32")] #[display(fmt = "i32")] I32, #[token("u64")] #[display(fmt = "u64")] U64, #[token("i64")] #[display(fmt = "i64")] I64, #[token("f32")] #[display(fmt = "f32")] F32, #[token("f64")] #[display(fmt = "f64")] F64, } impl NumberSuffix { pub const ALL_SUFFIXES: [&str; 11] = [ "ptr", "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f32", "f64" ]; } #[derive(Debug, Clone)] pub struct Span(pub Range); impl Span { pub const ZERO: Self = Self(0..0); pub fn lower(&self) -> usize { self.0.start } pub fn upper(&self) -> usize { self.0.end } pub fn concat(self, other: Span) -> Self { use std::cmp::{max, min}; Self(min(self.lower(), other.lower())..max(self.upper(), other.upper())) } } impl Display for Span { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}..{}", self.lower(), self.upper()) } } impl Add for Span { type Output = Self; fn add(self, rhs: Self) -> Self::Output { self.concat(rhs) } } impl AddAssign for Span { fn add_assign(&mut self, rhs: Self) { *self = self.clone() + rhs; } } #[derive(Debug, Clone)] pub struct Spanned(pub T, pub Span); impl Spanned { pub fn new(thing: T, spans: [Span; N]) -> Self { Self(thing, spans.into_iter().fold(Span::ZERO, Span::concat)) } pub fn map(self, f: impl Fn(T) -> R) -> Spanned { Spanned(f(self.0), self.1) } } impl Display for Spanned { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{} @ {}", self.0, self.1) } }