mimium_language_server/
semantic_token.rs

1use std::{collections::VecDeque, path::PathBuf};
2
3use mimium_lang::{
4    ast::{program::Program, statement::Statement},
5    interner::ExprNodeId,
6    pattern::TypedId,
7    utils::{error::ReportableError, metadata::Span},
8};
9use tower_lsp::lsp_types::{SemanticTokenType, SemanticTokens};
10
11/// Same as lstp_types::SemanticToken but lacks some fields like token_modifiers_bitset.
12#[derive(Debug)]
13pub struct ImCompleteSemanticToken {
14    pub start: usize,
15    pub length: usize,
16    pub token_type: usize,
17}
18
19pub const LEGEND_TYPE: &[SemanticTokenType] = &[
20    SemanticTokenType::FUNCTION,
21    SemanticTokenType::VARIABLE,
22    SemanticTokenType::STRING,
23    SemanticTokenType::COMMENT,
24    SemanticTokenType::NUMBER,
25    SemanticTokenType::KEYWORD,
26    SemanticTokenType::OPERATOR,
27    SemanticTokenType::PARAMETER,
28    SemanticTokenType::PROPERTY,
29    SemanticTokenType::MACRO,
30    SemanticTokenType::TYPE,
31    SemanticTokenType::TYPE_PARAMETER,
32];
33pub struct ParseResult {
34    pub ast: ExprNodeId,
35    pub semantic_tokens: Vec<ImCompleteSemanticToken>,
36    pub errors: Vec<Box<dyn ReportableError>>,
37}
38use mimium_lang::compiler::parser::Token;
39
40fn get_token_id(semt: &SemanticTokenType) -> usize {
41    LEGEND_TYPE.iter().position(|item| item == semt).unwrap()
42}
43fn token_to_semantic_token(token: &Token, span: &Span) -> Option<ImCompleteSemanticToken> {
44    let token_type = match token {
45        Token::Function
46        | Token::Let
47        | Token::LetRec
48        | Token::If
49        | Token::Else
50        | Token::SelfLit
51        | Token::Now
52        | Token::SampleRate => get_token_id(&SemanticTokenType::KEYWORD),
53        Token::Ident(_) => get_token_id(&SemanticTokenType::VARIABLE),
54        Token::Float(_) | Token::Int(_) => get_token_id(&SemanticTokenType::NUMBER),
55        Token::Str(_) => get_token_id(&SemanticTokenType::STRING),
56        Token::Comment(_) => get_token_id(&SemanticTokenType::COMMENT),
57        Token::Assign | Token::Dollar | Token::BackQuote | Token::Op(_) => {
58            get_token_id(&SemanticTokenType::OPERATOR)
59        }
60        Token::StringType | Token::IntegerType | Token::FloatType | Token::StructType => {
61            get_token_id(&SemanticTokenType::TYPE)
62        }
63        Token::MacroExpand(_) => get_token_id(&SemanticTokenType::MACRO),
64
65        _ => return None,
66    };
67    Some(ImCompleteSemanticToken {
68        start: span.start,
69        length: span.end - span.start,
70        token_type,
71    })
72}
73
74pub fn parse(src: &str, uri: &str) -> ParseResult {
75    let (tokens, mut errs) = mimium_lang::compiler::parser::lex(src, Some(PathBuf::from(uri)));
76    let semantic_token = if let Some(tks) = tokens {
77        tks.iter()
78            .filter_map(|(token, span)| token_to_semantic_token(token, &(span.start..span.end)))
79            .collect()
80    } else {
81        Vec::new()
82    };
83    let (ast, parse_errs) =
84        mimium_lang::compiler::parser::parse_to_expr(src, Some(PathBuf::from(uri)));
85    errs.extend(parse_errs);
86    ParseResult {
87        ast,
88        semantic_tokens: semantic_token,
89        errors: errs,
90    }
91}