blues-lsp 0.1.0

LSP language server for the Bluespec SystemVerilog language
Documentation
// VPP utility functions
// Mostly referenced from bsc VPP implementation.

/// Returns `true` if `c` is any whitespace
// https://github.com/B-Lang-org/bsc/blob/a798d8a94d54197d2b4755afdbb460cdc559c151/src/comp/SystemVerilogScanner.lhs#L399
pub fn bsv_whitespace(c: char) -> bool {
    c.is_ascii_whitespace()
}

/// Returns `true` if `c` is horizontal whitespace
// https://github.com/B-Lang-org/bsc/blob/a798d8a94d54197d2b4755afdbb460cdc559c151/src/comp/SystemVerilogScanner.lhs#L403
pub fn bsv_horizontal_whitespace(c: char) -> bool {
    matches!(c, ' ' | '\t')
}

/// Returns `true` if `c` can be used as the first character in a macro name
// https://github.com/B-Lang-org/bsc/blob/a798d8a94d54197d2b4755afdbb460cdc559c151/src/comp/SystemVerilogScanner.lhs#L409
pub fn bsv_ident_start(c: char) -> bool {
    match c {
        '_' => true,
        // Note The bsc analog function is implemented using Haskell's `Data.Char.isLetter`,
        // that checks against "Letter" Unicode category group.
        // `char::is_alphabetic` alone is not suitable, as it checks against "Alphabetic" property,
        // which includes the "Letter" group and the "Letter_Number" category.
        // This double lookup isn't ideal, but is fine for ascii values.
        //
        // This took a momment to figure out (and it might still be wrong).
        // So, to the 0 people hitting an error when prefixing their identifiers with
        // unicode code points for roman numerals and what not, I guess you're welcome?
        c if c.is_alphabetic() && !c.is_numeric() => true,
        _ => false,
    }
}

/// Returns `true` if `c` can be used after the first character in a macro name
// https://github.com/B-Lang-org/bsc/blob/a798d8a94d54197d2b4755afdbb460cdc559c151/src/comp/SystemVerilogScanner.lhs#L415
pub fn bsv_ident(c: char) -> bool {
    match c {
        '$' => true,
        c if c.is_ascii_digit() => true,
        c => bsv_ident_start(c),
    }
}

// https://github.com/B-Lang-org/bsc/blob/a798d8a94d54197d2b4755afdbb460cdc559c151/src/comp/SystemVerilogScanner.lhs#L422
pub fn bsv_symbol(c: char) -> bool {
    match c {
        #[rustfmt::skip]
        '!' | '*' | '/' | '=' | '|' | '(' | '[' | '{' | '`' |
        '%' | '+' | '<' | '?' | '~' | ')' | ']' | '}' | ':' |
        '&' | '-' | '>' | '^' | '.' | ',' | ';' | '#' | '\'' => true,
        _ => false,
    }
}

pub fn bsv_decimal_underscore(c: char) -> bool {
    match c {
        '_' => true,
        c if c.is_ascii_digit() => true,
        _ => false,
    }
}

pub fn bsv_hexadecimal_underscore(c: char) -> bool {
    match c {
        '_' => true,
        c if c.is_ascii_hexdigit() => true,
        _ => false,
    }
}

pub fn bsv_octal_underscore(c: char) -> bool {
    matches!(c, '_' | '0'..='7')
}

pub fn bsv_binary_underscore(c: char) -> bool {
    matches!(c, '_' | '0' | '1')
}

/// bsc does not check for id characters when parsing macro param names,
/// technically allowing param names to contain almost any character in unicode.
/// Returns `true` if `c` can be used in a param name under these circumstances,
/// excluding actual ident characters.
pub fn vpp_malformed_param(c: char) -> bool {
    match c {
        c if bsv_ident(c) => false,
        c if bsv_whitespace(c) => false,
        ',' | ')' | '\\' => false,
        _ => true,
    }
}