devalang_wasm/language/syntax/tokens/
mod.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
4pub enum Keyword {
5    At,
6    Tempo,
7    Bank,
8    Pattern,
9    Loop,
10    Function,
11    As,
12    On,
13    Emit,
14    Synth,
15    Use,
16    Let,
17    Automate,
18    Trigger,
19    Sleep,
20    Call,
21    Spawn,
22    Group,
23    Include,
24    Export,
25    Import,
26    Routing,
27    Bind,
28    Fx,
29    Node,
30    Sidechain,
31    If,
32    Else,
33    ElseIf,
34    Print,
35}
36
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
38#[serde(tag = "kind", rename_all = "snake_case")]
39pub enum TokenKind {
40    Keyword(Keyword),
41    Identifier,
42    Number,
43    String,
44    Boolean,
45    Duration,
46    Arrow,
47    Colon,
48    Comma,
49    Equals,
50    Dot,
51    Slash,
52    Plus,
53    Asterisk,
54    Minus,
55    DoubleEquals,
56    NotEquals,
57    GreaterEqual,
58    LessEqual,
59    Greater,
60    Less,
61    LBrace,
62    RBrace,
63    LBracket,
64    RBracket,
65    LParen,
66    RParen,
67    Newline,
68    Indent,
69    Dedent,
70    Comment,
71    Eof,
72    Unknown,
73    Error(String),
74}
75
76impl TokenKind {
77    pub fn is_keyword(&self, keyword: Keyword) -> bool {
78        matches!(self, TokenKind::Keyword(k) if *k == keyword)
79    }
80}
81
82#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
83pub struct Token {
84    pub kind: TokenKind,
85    pub lexeme: String,
86    pub indent: usize,
87    pub line: usize,
88    pub column: usize,
89}
90
91impl Token {
92    pub fn new(
93        kind: TokenKind,
94        lexeme: impl Into<String>,
95        indent: usize,
96        line: usize,
97        column: usize,
98    ) -> Self {
99        Self {
100            kind,
101            lexeme: lexeme.into(),
102            indent,
103            line,
104            column,
105        }
106    }
107
108    pub fn is_error(&self) -> bool {
109        matches!(self.kind, TokenKind::Error(_))
110    }
111}
112
113pub fn keyword_from_ident(ident: &str) -> Option<Keyword> {
114    match ident.to_lowercase().as_str() {
115        "at" => Some(Keyword::At),
116        "bpm" | "tempo" => Some(Keyword::Tempo),
117        "bank" => Some(Keyword::Bank),
118        "pattern" => Some(Keyword::Pattern),
119        "loop" => Some(Keyword::Loop),
120        "fn" | "function" => Some(Keyword::Function),
121        "as" => Some(Keyword::As),
122        "on" => Some(Keyword::On),
123        "emit" => Some(Keyword::Emit),
124        "synth" => Some(Keyword::Synth),
125        "use" => Some(Keyword::Use),
126        "let" => Some(Keyword::Let),
127        "automate" => Some(Keyword::Automate),
128        "trigger" => Some(Keyword::Trigger),
129        "sleep" | "rest" | "wait" => Some(Keyword::Sleep),
130        "call" => Some(Keyword::Call),
131        "spawn" => Some(Keyword::Spawn),
132        "group" => Some(Keyword::Group),
133        "include" => Some(Keyword::Include),
134        "export" => Some(Keyword::Export),
135        "import" => Some(Keyword::Import),
136        "routing" => Some(Keyword::Routing),
137        "bind" => Some(Keyword::Bind),
138        "fx" | "pipeline" => Some(Keyword::Fx),
139        "node" => Some(Keyword::Node),
140        "sidechain" => Some(Keyword::Sidechain),
141        "if" => Some(Keyword::If),
142        "else" => Some(Keyword::Else),
143        "elseif" | "else_if" | "elif" => Some(Keyword::ElseIf),
144        "print" => Some(Keyword::Print),
145        _ => None,
146    }
147}