@devaloop/devalang 0.0.1-alpha.2 → 0.0.1-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/.devalang +1 -1
  2. package/Cargo.toml +46 -46
  3. package/README.md +48 -30
  4. package/docs/CHANGELOG.md +28 -6
  5. package/docs/COMMANDS.md +31 -0
  6. package/docs/CONFIG.md +6 -4
  7. package/docs/ROADMAP.md +5 -1
  8. package/docs/TODO.md +10 -35
  9. package/examples/exported.deva +1 -1
  10. package/examples/index.deva +8 -1
  11. package/examples/samples/hat-808.wav +0 -0
  12. package/out-tsc/bin/devalang.exe +0 -0
  13. package/package.json +41 -42
  14. package/project-version.json +5 -5
  15. package/rust/audio/engine.rs +130 -0
  16. package/rust/audio/interpreter.rs +143 -0
  17. package/rust/audio/loader.rs +46 -0
  18. package/rust/audio/mod.rs +5 -1
  19. package/rust/audio/player.rs +54 -0
  20. package/rust/audio/render.rs +57 -0
  21. package/rust/cli/build.rs +73 -45
  22. package/rust/cli/check.rs +47 -111
  23. package/rust/cli/init.rs +1 -1
  24. package/rust/cli/mod.rs +203 -2
  25. package/rust/cli/play.rs +191 -0
  26. package/rust/{utils/config.rs → config/loader.rs} +3 -2
  27. package/rust/config/mod.rs +16 -0
  28. package/rust/core/builder/mod.rs +69 -27
  29. package/rust/core/debugger/lexer.rs +27 -0
  30. package/rust/core/debugger/mod.rs +12 -49
  31. package/rust/core/debugger/preprocessor.rs +27 -0
  32. package/rust/core/error/mod.rs +60 -0
  33. package/rust/core/lexer/{at.rs → handler/at.rs} +1 -1
  34. package/rust/core/lexer/{brace.rs → handler/brace.rs} +1 -1
  35. package/rust/core/lexer/{colon.rs → handler/colon.rs} +1 -1
  36. package/rust/core/lexer/{comment.rs → handler/comment.rs} +3 -3
  37. package/rust/core/lexer/{dot.rs → handler/dot.rs} +1 -1
  38. package/rust/core/lexer/{equal.rs → handler/equal.rs} +1 -1
  39. package/rust/core/lexer/{identifier.rs → handler/identifier.rs} +1 -1
  40. package/rust/core/lexer/{indent.rs → handler/indent.rs} +10 -5
  41. package/rust/core/lexer/handler/mod.rs +238 -0
  42. package/rust/core/lexer/{newline.rs → handler/newline.rs} +6 -10
  43. package/rust/core/lexer/{number.rs → handler/number.rs} +1 -1
  44. package/rust/core/lexer/handler/string.rs +66 -0
  45. package/rust/core/lexer/mod.rs +25 -14
  46. package/rust/core/lexer/token.rs +55 -0
  47. package/rust/core/mod.rs +5 -2
  48. package/rust/core/parser/handler/at.rs +166 -0
  49. package/rust/core/parser/handler/bank.rs +38 -0
  50. package/rust/core/parser/handler/dot.rs +112 -0
  51. package/rust/core/parser/handler/identifier.rs +134 -0
  52. package/rust/core/parser/handler/loop_.rs +55 -0
  53. package/rust/core/parser/handler/mod.rs +6 -0
  54. package/rust/core/parser/handler/tempo.rs +47 -0
  55. package/rust/core/parser/mod.rs +204 -166
  56. package/rust/core/parser/statement.rs +91 -0
  57. package/rust/core/preprocessor/loader.rs +116 -0
  58. package/rust/core/preprocessor/mod.rs +2 -24
  59. package/rust/core/preprocessor/module.rs +37 -56
  60. package/rust/core/preprocessor/processor.rs +41 -0
  61. package/rust/core/preprocessor/resolver/bank.rs +38 -51
  62. package/rust/core/preprocessor/resolver/loop_.rs +126 -65
  63. package/rust/core/preprocessor/resolver/mod.rs +119 -80
  64. package/rust/core/preprocessor/resolver/tempo.rs +40 -61
  65. package/rust/core/preprocessor/resolver/trigger.rs +93 -155
  66. package/rust/core/shared/duration.rs +8 -0
  67. package/rust/core/shared/mod.rs +2 -0
  68. package/rust/core/shared/value.rs +18 -0
  69. package/rust/core/store/export.rs +28 -0
  70. package/rust/core/store/global.rs +39 -0
  71. package/rust/core/store/import.rs +28 -0
  72. package/rust/core/store/mod.rs +4 -0
  73. package/rust/core/store/variable.rs +28 -0
  74. package/rust/core/utils/mod.rs +2 -0
  75. package/rust/core/utils/validation.rs +35 -0
  76. package/rust/lib.rs +0 -1
  77. package/rust/main.rs +22 -18
  78. package/rust/utils/logger.rs +69 -34
  79. package/rust/utils/mod.rs +3 -5
  80. package/rust/utils/watcher.rs +10 -2
  81. package/templates/minimal/.devalang +1 -1
  82. package/templates/welcome/.devalang +1 -1
  83. package/rust/core/lexer/bracket.rs +0 -41
  84. package/rust/core/lexer/driver.rs +0 -286
  85. package/rust/core/lexer/quote.rs +0 -61
  86. package/rust/core/parser/at.rs +0 -142
  87. package/rust/core/parser/bank.rs +0 -42
  88. package/rust/core/parser/dot.rs +0 -137
  89. package/rust/core/parser/identifer.rs +0 -91
  90. package/rust/core/parser/loop_.rs +0 -62
  91. package/rust/core/parser/tempo.rs +0 -42
  92. package/rust/core/parser/variable.rs +0 -129
  93. package/rust/core/preprocessor/dependencies.rs +0 -54
  94. package/rust/core/preprocessor/resolver/at.rs +0 -24
  95. package/rust/core/types/cli.rs +0 -182
  96. package/rust/core/types/config.rs +0 -15
  97. package/rust/core/types/mod.rs +0 -8
  98. package/rust/core/types/module.rs +0 -41
  99. package/rust/core/types/parser.rs +0 -73
  100. package/rust/core/types/statement.rs +0 -105
  101. package/rust/core/types/store.rs +0 -116
  102. package/rust/core/types/token.rs +0 -83
  103. package/rust/core/types/variable.rs +0 -32
  104. package/rust/runner/executer.rs +0 -44
  105. package/rust/runner/mod.rs +0 -1
  106. /package/rust/{utils → core/utils}/path.rs +0 -0
  107. /package/rust/utils/{loader.rs → spinner.rs} +0 -0
@@ -1,286 +0,0 @@
1
-
2
-
3
- use crate::core::{
4
- lexer::{
5
- at::handle_at_lexer,
6
- brace::{ handle_lbrace_lexer, handle_rbrace_lexer },
7
- colon::handle_colon_lexer,
8
- comment::handle_comment_lexer,
9
- equal::handle_equal_lexer,
10
- newline::handle_newline_lexer,
11
- bracket::{ handle_lbracket_lexer, handle_rbracket_lexer },
12
- dot::handle_dot_lexer,
13
- identifier::handle_identifier_lexer,
14
- indent::handle_indent_lexer,
15
- number::handle_number_lexer,
16
- quote::{ handle_double_quote_lexer, handle_single_quote_lexer },
17
- },
18
- types::token::{ Token, TokenKind },
19
- };
20
-
21
- pub fn lex(input: String) -> Vec<Token> {
22
- let mut tokens = Vec::new();
23
-
24
- let mut line = 1;
25
- let mut column = 1;
26
-
27
- let mut indent_stack: Vec<usize> = vec![0];
28
- let mut current_indent = 0;
29
- let mut at_line_start = true;
30
-
31
- let mut chars = input.chars().peekable();
32
-
33
- while let Some(_) = chars.peek() {
34
- if at_line_start {
35
- let (new_tokens, new_indent_stack, new_line, new_column) = handle_indent_lexer(
36
- &mut chars,
37
- &mut current_indent,
38
- &mut indent_stack,
39
- &mut tokens,
40
- &mut line,
41
- &mut column
42
- );
43
-
44
- // Update the main tokens vector and indent stack
45
- tokens = new_tokens;
46
- indent_stack = new_indent_stack;
47
- line = new_line;
48
- column = new_column;
49
-
50
- // Reset at_line_start flag
51
- at_line_start = false;
52
- }
53
-
54
- // Read the next character
55
- let Some(ch) = chars.next() else {
56
- break;
57
- };
58
-
59
- // Newline handling
60
- if ch == '\n' {
61
- handle_newline_lexer(
62
- ch,
63
- &mut chars,
64
- &mut tokens,
65
- &mut line,
66
- &mut column,
67
- &mut at_line_start,
68
- &mut current_indent
69
- );
70
-
71
- continue;
72
- }
73
-
74
- if ch == ' ' || ch == '\t' {
75
- column += if ch == '\t' { 4 } else { 1 };
76
- continue;
77
- }
78
-
79
- if ch == '#' {
80
- handle_comment_lexer(
81
- ch,
82
- &mut chars,
83
- &mut current_indent,
84
- &mut indent_stack,
85
- &mut tokens,
86
- &mut line,
87
- &mut column
88
- );
89
-
90
- continue;
91
- }
92
-
93
- if ch == ':' {
94
- handle_colon_lexer(
95
- ch,
96
- &mut chars,
97
- &mut current_indent,
98
- &mut indent_stack,
99
- &mut tokens,
100
- &mut line,
101
- &mut column
102
- );
103
-
104
- continue;
105
- }
106
-
107
- if ch == '=' {
108
- handle_equal_lexer(
109
- ch,
110
- &mut chars,
111
- &mut current_indent,
112
- &mut indent_stack,
113
- &mut tokens,
114
- &mut line,
115
- &mut column
116
- );
117
-
118
- continue;
119
- }
120
-
121
- if ch == '[' {
122
- handle_lbracket_lexer(
123
- ch,
124
- &mut chars,
125
- &mut current_indent,
126
- &mut indent_stack,
127
- &mut tokens,
128
- &mut line,
129
- &mut column
130
- );
131
-
132
- continue;
133
- }
134
-
135
- if ch == ']' {
136
- handle_rbracket_lexer(
137
- ch,
138
- &mut chars,
139
- &mut current_indent,
140
- &mut indent_stack,
141
- &mut tokens,
142
- &mut line,
143
- &mut column
144
- );
145
-
146
- continue;
147
- }
148
-
149
- if ch == '{' {
150
- handle_lbrace_lexer(
151
- ch,
152
- &mut chars,
153
- &mut current_indent,
154
- &mut indent_stack,
155
- &mut tokens,
156
- &mut line,
157
- &mut column
158
- );
159
-
160
- continue;
161
- }
162
-
163
- if ch == '}' {
164
- handle_rbrace_lexer(
165
- ch,
166
- &mut chars,
167
- &mut current_indent,
168
- &mut indent_stack,
169
- &mut tokens,
170
- &mut line,
171
- &mut column
172
- );
173
-
174
- continue;
175
- }
176
-
177
- if ch == '"' {
178
- handle_double_quote_lexer(
179
- ch,
180
- &mut chars,
181
- &mut current_indent,
182
- &mut indent_stack,
183
- &mut tokens,
184
- &mut line,
185
- &mut column
186
- );
187
-
188
- continue;
189
- }
190
-
191
- if ch == '\'' {
192
- handle_single_quote_lexer(
193
- ch,
194
- &mut chars,
195
- &mut current_indent,
196
- &mut indent_stack,
197
- &mut tokens,
198
- &mut line,
199
- &mut column
200
- );
201
-
202
- continue;
203
- }
204
-
205
- if ch == '.' {
206
- handle_dot_lexer(
207
- ch,
208
- &mut chars,
209
- &mut current_indent,
210
- &mut indent_stack,
211
- &mut tokens,
212
- &mut line,
213
- &mut column
214
- );
215
-
216
- continue;
217
- }
218
-
219
- if ch == '@' {
220
- handle_at_lexer(
221
- ch,
222
- &mut chars,
223
- &mut current_indent,
224
- &mut indent_stack,
225
- &mut tokens,
226
- &mut line,
227
- &mut column
228
- );
229
-
230
- continue;
231
- }
232
-
233
- if ch.is_ascii_digit() {
234
- handle_number_lexer(
235
- ch,
236
- &mut chars,
237
- &mut current_indent,
238
- &mut indent_stack,
239
- &mut tokens,
240
- &mut line,
241
- &mut column
242
- );
243
-
244
- continue;
245
- }
246
-
247
- if ch.is_ascii_alphabetic() {
248
- handle_identifier_lexer(
249
- ch,
250
- &mut chars,
251
- &mut current_indent,
252
- &mut indent_stack,
253
- &mut tokens,
254
- &mut line,
255
- &mut column
256
- );
257
-
258
- continue;
259
- }
260
-
261
- // Skip unknown char
262
- column += 1;
263
- }
264
-
265
- while indent_stack.len() > 1 {
266
- indent_stack.pop();
267
- current_indent = *indent_stack.last().unwrap();
268
- tokens.push(Token {
269
- kind: TokenKind::Dedent,
270
- lexeme: String::new(),
271
- line,
272
- column,
273
- indent: current_indent,
274
- });
275
- }
276
-
277
- tokens.push(Token {
278
- kind: TokenKind::EOF,
279
- lexeme: String::new(),
280
- line: line + 1, // EOF is considered to be on the next line
281
- column: 0, // EOF has no column
282
- indent: 0, // EOF has no indent
283
- });
284
-
285
- tokens
286
- }
@@ -1,61 +0,0 @@
1
- use crate::core::types::token::{Token, TokenKind};
2
-
3
- pub fn handle_single_quote_lexer(
4
- char: char,
5
- chars: &mut std::iter::Peekable<std::str::Chars>,
6
- current_indent: &mut usize,
7
- indent_stack: &mut Vec<usize>,
8
- tokens: &mut Vec<Token>,
9
- line: &mut usize,
10
- column: &mut usize
11
- ) {
12
- let mut string_content = String::new();
13
- *column += 1;
14
-
15
- while let Some(next_ch) = chars.next() {
16
- *column += 1;
17
- if next_ch == '\'' {
18
- break;
19
- } else {
20
- string_content.push(next_ch);
21
- }
22
- }
23
-
24
- tokens.push(Token {
25
- kind: TokenKind::String,
26
- lexeme: string_content,
27
- line: *line,
28
- column: *column,
29
- indent: *current_indent,
30
- });
31
- }
32
-
33
- pub fn handle_double_quote_lexer(
34
- char: char,
35
- chars: &mut std::iter::Peekable<std::str::Chars>,
36
- current_indent: &mut usize,
37
- indent_stack: &mut Vec<usize>,
38
- tokens: &mut Vec<Token>,
39
- line: &mut usize,
40
- column: &mut usize
41
- ) {
42
- let mut string_content = String::new();
43
- *column += 1; // skip the opening quote
44
-
45
- while let Some(next_ch) = chars.next() {
46
- *column += 1;
47
- if next_ch == '"' {
48
- break; // closing quote reached
49
- } else {
50
- string_content.push(next_ch);
51
- }
52
- }
53
-
54
- tokens.push(Token {
55
- kind: TokenKind::String,
56
- lexeme: string_content,
57
- line: *line,
58
- column: *column,
59
- indent: *current_indent,
60
- });
61
- }
@@ -1,142 +0,0 @@
1
- use crate::core::types::{
2
- parser::Parser,
3
- statement::{ Statement, StatementKind },
4
- token::TokenKind,
5
- variable::VariableValue,
6
- };
7
-
8
- pub fn parse_at(parser: &mut Parser) -> Result<Statement, String> {
9
- let token = parser.peek().ok_or("Unexpected EOF")?.clone();
10
-
11
- if token.kind != TokenKind::At {
12
- return Err(format!("Expected '@', found {:?}", token.kind));
13
- }
14
-
15
- parser.next();
16
-
17
- let identifier_token = parser.peek().ok_or("Expected identifier after '@'")?.clone();
18
- if identifier_token.kind != TokenKind::Identifier {
19
- return Err(format!("Expected Identifier, found {:?}", identifier_token.kind));
20
- }
21
-
22
- match identifier_token.lexeme.as_str() {
23
- "export" => {
24
- parser.next();
25
-
26
- if let Some(next_token) = parser.peek() {
27
- if next_token.kind == TokenKind::LBrace {
28
- parser.next(); // Consomme le LBrace
29
- }
30
- }
31
-
32
- let exportable_tokens = parser.collect_until(|t| { t.kind == TokenKind::RBrace });
33
-
34
- exportable_tokens.iter().for_each(|t| {
35
- let variable_value = parser.variable_table
36
- .get(&t.lexeme)
37
- .cloned()
38
- .unwrap_or_else(|| VariableValue::Text(t.lexeme.clone()));
39
-
40
- parser.export_table.exports.insert(t.lexeme.clone(), variable_value);
41
- });
42
-
43
- return Ok(Statement {
44
- kind: StatementKind::Export,
45
- value: VariableValue::Array(exportable_tokens),
46
- indent: token.indent,
47
- line: token.line,
48
- column: token.column,
49
- });
50
- }
51
- "import" => {
52
- parser.next();
53
-
54
- if let Some(next_token) = parser.peek() {
55
- if next_token.kind == TokenKind::LBrace {
56
- parser.next();
57
- }
58
- }
59
-
60
- let importable_tokens = parser.collect_until(|t| { t.kind == TokenKind::RBrace });
61
-
62
- parser.next();
63
-
64
- if let Some(from_token) = parser.peek() {
65
- if from_token.kind == TokenKind::Identifier && from_token.lexeme == "from" {
66
- parser.next();
67
- } else {
68
- return Err(format!("Expected 'from', found {:?}", from_token.kind));
69
- }
70
- } else {
71
- return Err("Expected 'from' after import declaration".into());
72
- }
73
-
74
- let source_token = parser.peek().ok_or("Expected source after 'from'")?.clone();
75
- if source_token.kind != TokenKind::String {
76
- return Err(format!("Expected String, found {:?}", source_token.kind));
77
- }
78
-
79
- let statement = Statement {
80
- kind: StatementKind::Import {
81
- names: importable_tokens
82
- .iter()
83
- .map(|t| t.lexeme.clone())
84
- .collect(),
85
- source: source_token.lexeme.clone(),
86
- },
87
- value: VariableValue::Array(importable_tokens),
88
- indent: token.indent,
89
- line: token.line,
90
- column: token.column,
91
- };
92
-
93
- return Ok(statement);
94
- }
95
- "load" => {
96
- parser.next();
97
-
98
- let source_token = parser.peek().ok_or("Expected source after load")?.clone();
99
- if source_token.kind != TokenKind::String {
100
- return Err(format!("Expected String, found {:?}", source_token.kind));
101
- }
102
-
103
- parser.next();
104
-
105
- let as_token = parser.peek().ok_or("Expected 'as' after load")?.clone();
106
- if as_token.kind != TokenKind::Identifier || as_token.lexeme != "as" {
107
- return Err(format!("Expected 'as', found {:?}", as_token.kind));
108
- }
109
-
110
- parser.next();
111
-
112
- let alias_token = parser.peek().ok_or("Expected alias after load")?.clone();
113
- if alias_token.kind != TokenKind::Identifier {
114
- return Err(format!("Expected Identifier, found {:?}", alias_token.kind));
115
- }
116
-
117
- parser.next();
118
-
119
- let statement = Statement {
120
- kind: StatementKind::Load {
121
- source: source_token.lexeme.clone(),
122
- alias: alias_token.lexeme.clone(),
123
- },
124
- value: VariableValue::Text(alias_token.lexeme.clone()),
125
- indent: token.indent,
126
- line: token.line,
127
- column: token.column,
128
- };
129
-
130
- return Ok(statement);
131
- }
132
-
133
- _ => {
134
- return Err(
135
- format!(
136
- "Expected 'export', 'import' or 'load', found '{}'",
137
- identifier_token.lexeme
138
- )
139
- );
140
- }
141
- }
142
- }
@@ -1,42 +0,0 @@
1
- use crate::core::types::{
2
- parser::Parser,
3
- statement::{ Statement, StatementKind },
4
- store::GlobalStore,
5
- token::TokenKind,
6
- variable::VariableValue,
7
- };
8
-
9
- pub fn parse_bank(
10
- parser: &mut Parser,
11
- global_store: &mut GlobalStore
12
- ) -> Result<Statement, String> {
13
- let token = parser.peek().ok_or("Unexpected EOF")?.clone();
14
-
15
- let mut bank_name = String::new();
16
-
17
- if parser.next().map(|t| t.kind.clone()) != Some(TokenKind::Bank) {
18
- return Err("Expected 'bank' keyword".to_string());
19
- }
20
-
21
- if let Some(token) = parser.next() {
22
- if token.kind == TokenKind::Identifier {
23
- bank_name = token.lexeme.clone();
24
- } else if token.kind == TokenKind::String {
25
- bank_name = token.lexeme.trim_matches('"').to_string();
26
- } else if token.kind == TokenKind::Number {
27
- bank_name = token.lexeme.clone();
28
- } else {
29
- return Err(format!("Expected bank name, found {:?}", token.kind));
30
- }
31
- } else {
32
- return Err("Expected bank name after 'bank' keyword".to_string());
33
- }
34
-
35
- Ok(Statement {
36
- kind: StatementKind::Bank,
37
- value: VariableValue::Text(bank_name.clone()),
38
- indent: token.indent,
39
- line: token.line,
40
- column: token.column,
41
- })
42
- }
@@ -1,137 +0,0 @@
1
- use std::{ collections::HashMap, hash::Hash };
2
-
3
- use crate::{
4
- core::types::{
5
- statement::{ Statement, StatementKind },
6
- token::{ Token, TokenDuration, TokenKind, TokenParamValue },
7
- variable::{ Variable, VariableValue },
8
- },
9
- utils::logger::log_message,
10
- };
11
-
12
- pub fn parse_dot(
13
- parser: &mut crate::core::parser::Parser,
14
- global_store: &mut crate::core::types::store::GlobalStore
15
- ) -> Result<crate::core::types::statement::Statement, String> {
16
- let token = parser.peek().ok_or("Unexpected EOF")?.clone();
17
- let mut trigger_value: String = String::from("Unknown Trigger");
18
-
19
- if token.kind != crate::core::types::token::TokenKind::Dot {
20
- return Err(format!("Expected Dot, found {:?}", token.kind));
21
- }
22
-
23
- parser.next();
24
-
25
- let identifier_token = parser.peek().ok_or("Expected identifier after dot")?.clone();
26
- if identifier_token.kind != crate::core::types::token::TokenKind::Identifier {
27
- return Err(format!("Expected Identifier after Dot, found {:?}", identifier_token.kind));
28
- }
29
-
30
- match identifier_token.lexeme.as_str() {
31
- // TODO Execute each trigger logic
32
-
33
- "kick" => {
34
- trigger_value = String::from("Kick");
35
- }
36
- "snare" => {
37
- trigger_value = String::from("Snare");
38
- }
39
- "hihat" => {
40
- trigger_value = String::from("HiHat");
41
- }
42
- "tom" => {
43
- trigger_value = String::from("Tom");
44
- }
45
- "clap" => {
46
- trigger_value = String::from("Clap");
47
- }
48
- "crash" => {
49
- trigger_value = String::from("Crash");
50
- }
51
- "ride" => {
52
- trigger_value = String::from("Ride");
53
- }
54
-
55
- _ => {
56
- log_message("Custom triggers are experimental", "WARNING");
57
- trigger_value = identifier_token.lexeme.clone();
58
- }
59
- }
60
-
61
- parser.next();
62
-
63
- let duration_token = parser.peek().ok_or("Expected duration after identifier")?.clone();
64
- let mut duration = TokenDuration::Unknown;
65
-
66
- match duration_token.lexeme.as_str() {
67
- "auto" => {
68
- duration = TokenDuration::Auto;
69
- }
70
- "infinite" => {
71
- duration = TokenDuration::Infinite;
72
- }
73
- _ => {
74
- if let Ok(num) = duration_token.lexeme.parse::<f32>() {
75
- duration = TokenDuration::Number(num);
76
- } else if let Ok(boolean) = duration_token.lexeme.parse::<bool>() {
77
- duration = TokenDuration::Unknown;
78
- } else if duration_token.kind == TokenKind::Identifier {
79
- duration = TokenDuration::Identifier(duration_token.lexeme.clone());
80
- } else {
81
- return Err(format!("Invalid duration format: {}", duration_token.lexeme));
82
- }
83
- }
84
- }
85
-
86
- parser.next();
87
-
88
- let dot_params: Vec<Token> = parser.collect_until(|t| { t.kind == TokenKind::Newline });
89
-
90
- let mut params_value: VariableValue = VariableValue::Null;
91
-
92
- for param in dot_params {
93
- let token_value = match param.kind {
94
- TokenKind::String => VariableValue::Text(param.lexeme),
95
- TokenKind::Number => VariableValue::Number(param.lexeme.parse().unwrap_or(0.0)),
96
- TokenKind::Boolean => VariableValue::Boolean(param.lexeme.parse().unwrap_or(false)),
97
- TokenKind::Map => {
98
- let mut map: HashMap<String, TokenParamValue> = HashMap::new();
99
- let entries: Vec<&str> = param.lexeme.split(',').collect();
100
- for entry in entries {
101
- let parts: Vec<&str> = entry.split(':').collect();
102
- if parts.len() == 2 {
103
- let key = parts[0].trim().to_string();
104
- let value = match parts[1].trim() {
105
- "true" => TokenParamValue::Boolean(true),
106
- "false" => TokenParamValue::Boolean(false),
107
- _ => TokenParamValue::String(parts[1].trim().to_string()),
108
- };
109
- map.insert(key, value);
110
- }
111
- }
112
- VariableValue::Map(map)
113
- }
114
- TokenKind::Identifier => { VariableValue::Text(param.lexeme.clone()) }
115
- TokenKind::Unknown => {
116
- Err(format!("Unsupported token type in dot parameters: {:?}", param.kind))?;
117
- VariableValue::Null
118
- }
119
- _ => {
120
- Err(format!("Unsupported token type in dot parameters: {:?}", param.kind))?;
121
- VariableValue::Unknown
122
- }
123
- };
124
- params_value = token_value;
125
- }
126
-
127
- Ok(Statement {
128
- kind: StatementKind::Trigger {
129
- entity: identifier_token.lexeme.clone(),
130
- duration: duration.clone(),
131
- },
132
- value: params_value,
133
- indent: token.indent,
134
- line: token.line,
135
- column: token.column,
136
- })
137
- }