use std::ops::{Range, Add}; use logos::Logos; #[derive(Logos, Debug, PartialEq)] #[logos(skip r"[ \t\n\f]+")] pub enum Token { #[token("{")] LeftBrace, #[token("}")] RightBrace, #[token("(")] LeftParen, #[token(")")] RightParen, #[token(";")] Semicolon, #[token(":")] Colon, #[token("<")] LeftArrow, #[token(">")] RightArrow, #[token(",")] Comma, #[token("=")] Equals, //#[regex(r#"[A-z]+"#, |lex| lex.slice().parse().ok())] //Literal(String), #[regex(r#"[A-z]+"#, |lex| Ident::lexer(lex.slice()).next().and_then(Result::ok))] Ident(Ident), #[regex("use [a-zA-Z/]+;", |lex| lex.slice().parse().ok())] Component(String), #[regex("U[0-9]+", |lex| lex.slice().parse().ok())] UnsignedType(String), #[regex("I[0-9]+", |lex| lex.slice().parse().ok())] SignedType(String), #[regex(r"//.*", |lex| lex.slice().parse().ok())] Comment(String), } #[derive(Logos, Debug, PartialEq, Eq)] pub enum Ident { #[token("Interface")] Interface, #[token("Function")] Function, #[token("Constant")] Constant, #[token("Structure")] Structure, #[token("Type")] Type, #[token("Use")] Use, #[regex(r"[A-z]+", |lex| lex.slice().parse().ok())] Other(String) } #[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::{min, max}; Self(min(self.lower(), other.lower())..max(self.upper(), other.upper())) } } impl Add for Span { type Output = Self; fn add(self, rhs: Self) -> Self::Output { self.concat(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) } }