blues-lsp 0.1.3

LSP language server for the Bluespec SystemVerilog language
Documentation
use std::fmt::Display;

use crate::{
    syntax::lexer::token::{Kw, NumLit, Sym, TokenKind},
    util::data::bitset::BitSet,
};

/// "Token type"
/// Aka.: a TokenKind, but with with data unnecessary for parsing stripped.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Tt {
    /// Keywords
    Kw(Kw),
    /// Identifiers
    Ident,
    /// System identifiers ('$foo')
    SysIdent,
    /// Symbols
    Sym(Sym),
    /// Numeric literals
    Num(NumLit),
    /// String literals
    Str,
    /// End-of-File sentinel, parser internal
    Eof,
}

impl Tt {
    pub fn from_kind(kind: &TokenKind) -> Option<Tt> {
        match kind {
            TokenKind::Kw(kw) => Some(Tt::Kw(*kw)),
            TokenKind::Ident(_) => Some(Tt::Ident),
            TokenKind::SysIdent(_) => Some(Tt::SysIdent),
            TokenKind::Sym(sym) => Some(Tt::Sym(*sym)),
            TokenKind::Num(num_lit) => Some(Tt::Num(*num_lit)),
            TokenKind::Str(_) => Some(Tt::Str),
            TokenKind::Comment => None,
            TokenKind::Error => None,
        }
    }
}

impl Display for Tt {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Tt::Kw(kw) => write!(f, "keyword '{kw}'"),
            Tt::Ident => write!(f, "identifier"),
            Tt::SysIdent => write!(f, "system identifier"),
            Tt::Sym(sym) => write!(f, "symbol '{sym}'"),
            Tt::Num(_) => write!(f, "number"),
            Tt::Str => write!(f, "string"),
            Tt::Eof => write!(f, "end-of-file"),
        }
    }
}

impl From<Kw> for Tt {
    fn from(value: Kw) -> Self {
        Tt::Kw(value)
    }
}

impl From<Sym> for Tt {
    fn from(value: Sym) -> Self {
        Tt::Sym(value)
    }
}

impl From<NumLit> for Tt {
    fn from(value: NumLit) -> Self {
        Tt::Num(value)
    }
}

#[derive(Debug, Clone, Copy)]
pub struct TtSet {
    set: BitSet<3>,
}

impl Default for TtSet {
    fn default() -> Self {
        Self::new()
    }
}

impl TtSet {
    pub const fn new() -> Self {
        Self { set: BitSet::new() }
    }

    pub const fn inherit(mut self, other: TtSet) -> Self {
        self.set.union(other.set);
        self
    }

    pub const fn ty_idx(ty: Tt) -> usize {
        match ty {
            Tt::Ident => 0,
            Tt::SysIdent => 1,
            Tt::Str => 2,
            Tt::Eof => 3,
            Tt::Num(NumLit::Int) => 4,
            Tt::Num(NumLit::Real) => 5,
            Tt::Num(NumLit::Repeated) => 6,
            Tt::Num(NumLit::Mixed) => 7,
            Tt::Kw(kw) => 8 + kw as usize,
            Tt::Sym(sym) => 8 + Kw::__Last as usize + sym as usize,
        }
    }

    pub const fn add(&mut self, ty: Tt) {
        self.set.add(Self::ty_idx(ty));
    }

    pub const fn contains(&self, ty: Tt) -> bool {
        self.set.contains(Self::ty_idx(ty))
    }

    pub const fn tys(mut self, tys: &[Tt]) -> Self {
        let mut i = 0;
        while i < tys.len() {
            self.add(tys[i]);
            i += 1;
        }
        self
    }

    pub const fn kws(mut self, kws: &[Kw]) -> Self {
        let mut i = 0;
        while i < kws.len() {
            self.add(Tt::Kw(kws[i]));
            i += 1;
        }
        self
    }

    pub const fn syms(mut self, syms: &[Sym]) -> Self {
        let mut i = 0;
        while i < syms.len() {
            self.add(Tt::Sym(syms[i]));
            i += 1;
        }
        self
    }
}