@devaloop/devalang 0.0.1-alpha.1 → 0.0.1-alpha.2
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.
- package/.devalang +4 -0
- package/Cargo.toml +3 -2
- package/README.md +30 -6
- package/docs/CHANGELOG.md +53 -0
- package/docs/COMMANDS.md +29 -6
- package/docs/CONFIG.md +28 -0
- package/docs/ROADMAP.md +1 -1
- package/docs/TODO.md +43 -15
- package/examples/index.deva +1 -1
- package/out-tsc/bin/devalang.exe +0 -0
- package/package.json +2 -2
- package/project-version.json +3 -3
- package/rust/cli/build.rs +58 -5
- package/rust/cli/check.rs +73 -17
- package/rust/cli/init.rs +77 -0
- package/rust/cli/mod.rs +2 -1
- package/rust/cli/template.rs +56 -0
- package/rust/core/lexer/at.rs +21 -0
- package/rust/core/lexer/brace.rs +41 -0
- package/rust/core/lexer/bracket.rs +41 -0
- package/rust/core/lexer/colon.rs +21 -0
- package/rust/core/lexer/comment.rs +30 -0
- package/rust/core/lexer/dot.rs +21 -0
- package/rust/core/lexer/driver.rs +286 -0
- package/rust/core/lexer/equal.rs +32 -0
- package/rust/core/lexer/identifier.rs +38 -0
- package/rust/core/lexer/indent.rs +47 -0
- package/rust/core/lexer/mod.rs +14 -333
- package/rust/core/lexer/newline.rs +23 -0
- package/rust/core/lexer/number.rs +31 -0
- package/rust/core/lexer/quote.rs +61 -0
- package/rust/core/parser/dot.rs +48 -18
- package/rust/core/preprocessor/module.rs +1 -1
- package/rust/core/types/cli.rs +53 -31
- package/rust/core/types/config.rs +15 -0
- package/rust/core/types/mod.rs +2 -1
- package/rust/main.rs +30 -19
- package/rust/utils/config.rs +13 -0
- package/rust/utils/file.rs +35 -0
- package/rust/utils/mod.rs +4 -1
- package/rust/utils/watcher.rs +25 -0
- package/templates/minimal/.devalang +4 -0
- package/templates/minimal/src/index.deva +2 -0
- package/templates/welcome/.devalang +4 -0
- package/templates/welcome/README.md +185 -0
- package/templates/welcome/samples/kick-808.wav +0 -0
- package/templates/welcome/src/index.deva +13 -0
- package/templates/welcome/src/variables.deva +5 -0
- package/rust/cli/new.rs +0 -1
package/rust/core/lexer/mod.rs
CHANGED
|
@@ -1,333 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
pub
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
while let Some(_) = chars.peek() {
|
|
16
|
-
if at_line_start {
|
|
17
|
-
current_indent = 0;
|
|
18
|
-
|
|
19
|
-
while let Some(&c) = chars.peek() {
|
|
20
|
-
if c == ' ' {
|
|
21
|
-
current_indent += 1;
|
|
22
|
-
chars.next();
|
|
23
|
-
column += 1;
|
|
24
|
-
} else {
|
|
25
|
-
break;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
let last_indent = *indent_stack.last().unwrap();
|
|
30
|
-
if current_indent > last_indent {
|
|
31
|
-
indent_stack.push(current_indent);
|
|
32
|
-
tokens.push(Token {
|
|
33
|
-
kind: TokenKind::Indent,
|
|
34
|
-
lexeme: String::new(),
|
|
35
|
-
line,
|
|
36
|
-
column,
|
|
37
|
-
indent: current_indent,
|
|
38
|
-
});
|
|
39
|
-
} else {
|
|
40
|
-
while current_indent < *indent_stack.last().unwrap() {
|
|
41
|
-
indent_stack.pop();
|
|
42
|
-
tokens.push(Token {
|
|
43
|
-
kind: TokenKind::Dedent,
|
|
44
|
-
lexeme: String::new(),
|
|
45
|
-
line,
|
|
46
|
-
column,
|
|
47
|
-
indent: current_indent,
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
at_line_start = false;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
let Some(ch) = chars.next() else {
|
|
56
|
-
break;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
if ch == '\n' {
|
|
60
|
-
tokens.push(Token {
|
|
61
|
-
kind: TokenKind::Newline,
|
|
62
|
-
lexeme: ch.to_string(),
|
|
63
|
-
line,
|
|
64
|
-
column,
|
|
65
|
-
indent: current_indent,
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
line += 1;
|
|
69
|
-
column = 1;
|
|
70
|
-
at_line_start = true;
|
|
71
|
-
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if ch == ' ' || ch == '\t' {
|
|
76
|
-
column += if ch == '\t' { 4 } else { 1 };
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if ch == '#' {
|
|
81
|
-
let mut comment = String::new();
|
|
82
|
-
while let Some(&c) = chars.peek() {
|
|
83
|
-
if c == '\n' {
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
comment.push(c);
|
|
87
|
-
chars.next();
|
|
88
|
-
column += 1;
|
|
89
|
-
}
|
|
90
|
-
tokens.push(Token {
|
|
91
|
-
kind: TokenKind::Comment(comment.trim().to_string()),
|
|
92
|
-
lexeme: ch.to_string(),
|
|
93
|
-
line,
|
|
94
|
-
column,
|
|
95
|
-
indent: current_indent,
|
|
96
|
-
});
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if ch == ':' {
|
|
101
|
-
tokens.push(Token {
|
|
102
|
-
kind: TokenKind::Colon,
|
|
103
|
-
lexeme: ch.to_string(),
|
|
104
|
-
line,
|
|
105
|
-
column,
|
|
106
|
-
indent: current_indent,
|
|
107
|
-
});
|
|
108
|
-
column += 1;
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if ch == '=' {
|
|
113
|
-
if let Some('=') = chars.peek() {
|
|
114
|
-
chars.next();
|
|
115
|
-
tokens.push(Token {
|
|
116
|
-
kind: TokenKind::DoubleEquals,
|
|
117
|
-
lexeme: ch.to_string(),
|
|
118
|
-
line,
|
|
119
|
-
column,
|
|
120
|
-
indent: current_indent,
|
|
121
|
-
});
|
|
122
|
-
column += 2;
|
|
123
|
-
} else {
|
|
124
|
-
tokens.push(Token {
|
|
125
|
-
kind: TokenKind::Equals,
|
|
126
|
-
lexeme: ch.to_string(),
|
|
127
|
-
line,
|
|
128
|
-
column,
|
|
129
|
-
indent: current_indent,
|
|
130
|
-
});
|
|
131
|
-
column += 1;
|
|
132
|
-
}
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if ch == '[' {
|
|
137
|
-
tokens.push(Token {
|
|
138
|
-
kind: TokenKind::LBracket,
|
|
139
|
-
lexeme: ch.to_string(),
|
|
140
|
-
line,
|
|
141
|
-
column,
|
|
142
|
-
indent: current_indent,
|
|
143
|
-
});
|
|
144
|
-
column += 1;
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if ch == ']' {
|
|
149
|
-
tokens.push(Token {
|
|
150
|
-
kind: TokenKind::RBracket,
|
|
151
|
-
lexeme: ch.to_string(),
|
|
152
|
-
line,
|
|
153
|
-
column,
|
|
154
|
-
indent: current_indent,
|
|
155
|
-
});
|
|
156
|
-
column += 1;
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if ch == '{' {
|
|
161
|
-
tokens.push(Token {
|
|
162
|
-
kind: TokenKind::LBrace,
|
|
163
|
-
lexeme: ch.to_string(),
|
|
164
|
-
line,
|
|
165
|
-
column,
|
|
166
|
-
indent: current_indent,
|
|
167
|
-
});
|
|
168
|
-
column += 1;
|
|
169
|
-
continue;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if ch == '}' {
|
|
173
|
-
tokens.push(Token {
|
|
174
|
-
kind: TokenKind::RBrace,
|
|
175
|
-
lexeme: ch.to_string(),
|
|
176
|
-
line,
|
|
177
|
-
column,
|
|
178
|
-
indent: current_indent,
|
|
179
|
-
});
|
|
180
|
-
column += 1;
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if ch == '"' {
|
|
185
|
-
let mut string_content = String::new();
|
|
186
|
-
column += 1; // skip the opening quote
|
|
187
|
-
|
|
188
|
-
while let Some(next_ch) = chars.next() {
|
|
189
|
-
column += 1;
|
|
190
|
-
if next_ch == '"' {
|
|
191
|
-
break; // closing quote reached
|
|
192
|
-
} else {
|
|
193
|
-
string_content.push(next_ch);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
tokens.push(Token {
|
|
198
|
-
kind: TokenKind::String,
|
|
199
|
-
lexeme: string_content,
|
|
200
|
-
line,
|
|
201
|
-
column,
|
|
202
|
-
indent: current_indent,
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
continue;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if ch == '\'' {
|
|
209
|
-
let mut string_content = String::new();
|
|
210
|
-
column += 1;
|
|
211
|
-
|
|
212
|
-
while let Some(next_ch) = chars.next() {
|
|
213
|
-
column += 1;
|
|
214
|
-
if next_ch == '\'' {
|
|
215
|
-
break;
|
|
216
|
-
} else {
|
|
217
|
-
string_content.push(next_ch);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
tokens.push(Token {
|
|
222
|
-
kind: TokenKind::String,
|
|
223
|
-
lexeme: string_content,
|
|
224
|
-
line,
|
|
225
|
-
column,
|
|
226
|
-
indent: current_indent,
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
continue;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if ch == '.' {
|
|
233
|
-
tokens.push(Token {
|
|
234
|
-
kind: TokenKind::Dot,
|
|
235
|
-
lexeme: ch.to_string(),
|
|
236
|
-
line,
|
|
237
|
-
column,
|
|
238
|
-
indent: current_indent,
|
|
239
|
-
});
|
|
240
|
-
column += 1;
|
|
241
|
-
continue;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if ch == '@' {
|
|
245
|
-
tokens.push(Token {
|
|
246
|
-
kind: TokenKind::At,
|
|
247
|
-
lexeme: ch.to_string(),
|
|
248
|
-
line,
|
|
249
|
-
column,
|
|
250
|
-
indent: current_indent,
|
|
251
|
-
});
|
|
252
|
-
column += 1;
|
|
253
|
-
continue;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if ch.is_ascii_digit() {
|
|
257
|
-
let mut number = ch.to_string();
|
|
258
|
-
while let Some(&c) = chars.peek() {
|
|
259
|
-
if c.is_ascii_digit() {
|
|
260
|
-
number.push(c);
|
|
261
|
-
chars.next();
|
|
262
|
-
column += 1;
|
|
263
|
-
} else {
|
|
264
|
-
break;
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// let value = number.parse::<f32>().unwrap();
|
|
269
|
-
tokens.push(Token {
|
|
270
|
-
kind: TokenKind::Number,
|
|
271
|
-
lexeme: number,
|
|
272
|
-
line,
|
|
273
|
-
column,
|
|
274
|
-
indent: current_indent,
|
|
275
|
-
});
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
if ch.is_ascii_alphabetic() {
|
|
280
|
-
let mut ident = ch.to_string();
|
|
281
|
-
while let Some(&c) = chars.peek() {
|
|
282
|
-
if c.is_ascii_alphanumeric() || c == '_' {
|
|
283
|
-
ident.push(c);
|
|
284
|
-
chars.next();
|
|
285
|
-
column += 1;
|
|
286
|
-
} else {
|
|
287
|
-
break;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
let kind = match ident.as_str() {
|
|
292
|
-
"bank" => TokenKind::Bank,
|
|
293
|
-
"bpm" => TokenKind::Tempo,
|
|
294
|
-
"loop" => TokenKind::Loop,
|
|
295
|
-
_ => TokenKind::Identifier,
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
tokens.push(Token {
|
|
299
|
-
kind,
|
|
300
|
-
lexeme: ident,
|
|
301
|
-
line,
|
|
302
|
-
column,
|
|
303
|
-
indent: current_indent,
|
|
304
|
-
});
|
|
305
|
-
continue;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// Skip unknown char
|
|
309
|
-
column += 1;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
while indent_stack.len() > 1 {
|
|
313
|
-
indent_stack.pop();
|
|
314
|
-
current_indent = *indent_stack.last().unwrap();
|
|
315
|
-
tokens.push(Token {
|
|
316
|
-
kind: TokenKind::Dedent,
|
|
317
|
-
lexeme: String::new(),
|
|
318
|
-
line,
|
|
319
|
-
column,
|
|
320
|
-
indent: current_indent,
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
tokens.push(Token {
|
|
325
|
-
kind: TokenKind::EOF,
|
|
326
|
-
lexeme: String::new(),
|
|
327
|
-
line: line + 1, // EOF is considered to be on the next line
|
|
328
|
-
column: 0, // EOF has no column
|
|
329
|
-
indent: 0, // EOF has no indent
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
tokens
|
|
333
|
-
}
|
|
1
|
+
pub mod indent;
|
|
2
|
+
pub mod identifier;
|
|
3
|
+
pub mod number;
|
|
4
|
+
pub mod at;
|
|
5
|
+
pub mod dot;
|
|
6
|
+
pub mod quote;
|
|
7
|
+
pub mod brace;
|
|
8
|
+
pub mod newline;
|
|
9
|
+
pub mod comment;
|
|
10
|
+
pub mod bracket;
|
|
11
|
+
pub mod colon;
|
|
12
|
+
pub mod equal;
|
|
13
|
+
|
|
14
|
+
pub mod driver;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
use crate::core::types::token::{Token, TokenKind};
|
|
2
|
+
|
|
3
|
+
pub fn handle_newline_lexer(
|
|
4
|
+
char: char,
|
|
5
|
+
chars: &mut std::iter::Peekable<std::str::Chars>,
|
|
6
|
+
tokens: &mut Vec<Token>,
|
|
7
|
+
line: &mut usize,
|
|
8
|
+
column: &mut usize,
|
|
9
|
+
at_line_start: &mut bool,
|
|
10
|
+
current_indent: &mut usize,
|
|
11
|
+
) {
|
|
12
|
+
tokens.push(Token {
|
|
13
|
+
kind: TokenKind::Newline,
|
|
14
|
+
lexeme: char.to_string(),
|
|
15
|
+
line: *line,
|
|
16
|
+
column: *column,
|
|
17
|
+
indent: *current_indent,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
*line += 1;
|
|
21
|
+
*column = 1;
|
|
22
|
+
*at_line_start = true;
|
|
23
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
use crate::core::types::token::{Token, TokenKind};
|
|
2
|
+
|
|
3
|
+
pub fn handle_number_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 number = char.to_string();
|
|
13
|
+
|
|
14
|
+
while let Some(&c) = chars.peek() {
|
|
15
|
+
if c.is_ascii_digit() {
|
|
16
|
+
number.push(c);
|
|
17
|
+
chars.next();
|
|
18
|
+
*column += 1;
|
|
19
|
+
} else {
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
tokens.push(Token {
|
|
25
|
+
kind: TokenKind::Number,
|
|
26
|
+
lexeme: number,
|
|
27
|
+
line: *line,
|
|
28
|
+
column: *column,
|
|
29
|
+
indent: *current_indent,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
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
|
+
}
|
package/rust/core/parser/dot.rs
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
use std::{ collections::HashMap, hash::Hash };
|
|
2
2
|
|
|
3
|
-
use crate::
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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,
|
|
7
10
|
};
|
|
8
11
|
|
|
9
12
|
pub fn parse_dot(
|
|
@@ -19,12 +22,43 @@ pub fn parse_dot(
|
|
|
19
22
|
|
|
20
23
|
parser.next();
|
|
21
24
|
|
|
22
|
-
let
|
|
23
|
-
if
|
|
24
|
-
return Err(format!("Expected Identifier after Dot, found {:?}",
|
|
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));
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
|
|
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();
|
|
28
62
|
|
|
29
63
|
let duration_token = parser.peek().ok_or("Expected duration after identifier")?.clone();
|
|
30
64
|
let mut duration = TokenDuration::Unknown;
|
|
@@ -50,10 +84,8 @@ pub fn parse_dot(
|
|
|
50
84
|
}
|
|
51
85
|
|
|
52
86
|
parser.next();
|
|
53
|
-
|
|
54
|
-
let dot_params: Vec<Token> = parser.collect_until(|t| {
|
|
55
|
-
t.kind == TokenKind::Newline
|
|
56
|
-
});
|
|
87
|
+
|
|
88
|
+
let dot_params: Vec<Token> = parser.collect_until(|t| { t.kind == TokenKind::Newline });
|
|
57
89
|
|
|
58
90
|
let mut params_value: VariableValue = VariableValue::Null;
|
|
59
91
|
|
|
@@ -79,24 +111,22 @@ pub fn parse_dot(
|
|
|
79
111
|
}
|
|
80
112
|
VariableValue::Map(map)
|
|
81
113
|
}
|
|
82
|
-
TokenKind::Identifier => {
|
|
83
|
-
VariableValue::Text(param.lexeme.clone())
|
|
84
|
-
}
|
|
114
|
+
TokenKind::Identifier => { VariableValue::Text(param.lexeme.clone()) }
|
|
85
115
|
TokenKind::Unknown => {
|
|
86
116
|
Err(format!("Unsupported token type in dot parameters: {:?}", param.kind))?;
|
|
87
117
|
VariableValue::Null
|
|
88
|
-
}
|
|
118
|
+
}
|
|
89
119
|
_ => {
|
|
90
120
|
Err(format!("Unsupported token type in dot parameters: {:?}", param.kind))?;
|
|
91
121
|
VariableValue::Unknown
|
|
92
|
-
}
|
|
122
|
+
}
|
|
93
123
|
};
|
|
94
124
|
params_value = token_value;
|
|
95
125
|
}
|
|
96
126
|
|
|
97
127
|
Ok(Statement {
|
|
98
128
|
kind: StatementKind::Trigger {
|
|
99
|
-
entity:
|
|
129
|
+
entity: identifier_token.lexeme.clone(),
|
|
100
130
|
duration: duration.clone(),
|
|
101
131
|
},
|
|
102
132
|
value: params_value,
|