ableos_userland/programs/aidl/src/lexer.rs

117 lines
2.2 KiB
Rust

use std::{
fmt::Display,
ops::{Add, Range},
};
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,
#[token(".")]
Dot,
#[regex(r#"[a-zA-Z_][a-zA-Z\d_]*"#, |lex| Ident::lexer(lex.slice()).next().and_then(Result::ok))]
Ident(Ident),
#[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("Alias")]
Alias,
#[token("Use")]
Use,
#[regex(r"[A-z]+", |lex| lex.slice().parse().ok())]
Other(String),
}
#[derive(Debug, Clone)]
pub struct Span(pub Range<usize>);
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)
}
}
#[derive(Debug, Clone)]
pub struct Spanned<T>(pub T, pub Span);
impl<T> Spanned<T> {
pub fn new<const N: usize>(thing: T, spans: [Span; N]) -> Self {
Self(thing, spans.into_iter().fold(Span::ZERO, Span::concat))
}
pub fn map<R>(self, f: impl Fn(T) -> R) -> Spanned<R> {
Spanned(f(self.0), self.1)
}
}
impl<T: Display> Display for Spanned<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} @ {}", self.0, self.1)
}
}