devalang_core/core/parser/
driver.rs1use devalang_types::Value;
2
3use crate::core::{
4 lexer::token::{Token, TokenKind},
5 parser::{
6 handler::{
7 arrow_call::parse_arrow_call,
8 at::parse_at_token,
9 bank::parse_bank_token,
10 condition::parse_condition_token,
11 dot::parse_dot_token,
12 identifier::{
13 emit::parse_emit_token, function::parse_function_token, on::parse_on_token,
14 parse_identifier_token,
15 },
16 loop_::parse_loop_token,
17 pattern::parse_pattern_token,
18 tempo::parse_tempo_token,
19 },
20 statement::Statement,
21 },
22 store::global::GlobalStore,
23};
24
25#[derive(Debug, Clone, PartialEq)]
26pub struct Parser {
27 pub resolve_modules: bool,
28 pub tokens: Vec<Token>,
29 pub token_index: usize,
30 pub current_module: String,
31 pub previous: Option<Token>,
32}
33
34impl Default for Parser {
35 fn default() -> Self {
36 Self::new()
37 }
38}
39
40impl Parser {
41 pub fn new() -> Self {
42 Parser {
43 resolve_modules: false,
44 tokens: Vec::new(),
45 token_index: 0,
46 current_module: String::new(),
47 previous: None,
48 }
49 }
50
51 pub fn set_current_module(&mut self, module_path: String) {
52 self.current_module = module_path;
53 }
54
55 pub fn advance(&mut self) -> Option<&Token> {
56 if self.is_eof() {
57 return None;
58 }
59
60 self.previous = self.tokens.get(self.token_index).cloned();
61 self.token_index += 1;
62
63 self.tokens.get(self.token_index - 1)
64 }
65
66 pub fn peek_is(&self, expected: &str) -> bool {
67 self.peek().is_some_and(|t| t.lexeme == expected)
68 }
69
70 pub fn peek_nth(&self, n: usize) -> Option<&Token> {
71 if self.token_index + n < self.tokens.len() {
72 self.tokens.get(self.token_index + n)
73 } else {
74 None
75 }
76 }
77
78 pub fn peek_nth_kind(&self, n: usize) -> Option<TokenKind> {
79 self.peek_nth(n).map(|t| t.kind.clone())
80 }
81
82 pub fn advance_if(&mut self, kind: TokenKind) -> bool {
83 self.match_token(kind)
84 }
85
86 pub fn match_token(&mut self, kind: TokenKind) -> bool {
87 if let Some(tok) = self.peek() {
88 if tok.kind == kind {
89 self.advance();
90 return true;
91 }
92 }
93 false
94 }
95
96 pub fn previous_clone(&self) -> Option<Token> {
97 self.previous.clone()
98 }
99
100 pub fn parse_block(
101 &self,
102 tokens: Vec<Token>,
103 global_store: &mut GlobalStore,
104 ) -> Vec<Statement> {
105 let mut inner_parser = Parser {
106 resolve_modules: self.resolve_modules,
107 tokens,
108 token_index: 0,
109 current_module: self.current_module.clone(),
110 previous: None,
111 };
112
113 inner_parser.parse_tokens(inner_parser.tokens.clone(), global_store)
114 }
115
116 pub fn parse_tokens(
117 &mut self,
118 tokens: Vec<Token>,
119 global_store: &mut GlobalStore,
120 ) -> Vec<Statement> {
121 self.tokens = tokens
124 .into_iter()
125 .filter(|t| t.kind != TokenKind::Whitespace)
126 .collect();
127 self.token_index = 0;
128
129 let mut statements = Vec::new();
130
131 while !self.is_eof() {
132 let token = match self.peek() {
133 Some(t) => t.clone(),
134 None => {
135 break;
136 }
137 };
138
139 if token.kind == TokenKind::Newline {
140 self.advance();
141 continue;
142 }
143
144 let statement = match &token.kind {
145 TokenKind::At => parse_at_token(self, global_store),
146 TokenKind::Identifier => {
147 if let Some(next) = self.peek_nth(1).cloned() {
148 if next.kind == TokenKind::Arrow {
149 parse_arrow_call(self, global_store)
150 } else {
151 parse_identifier_token(self, global_store)
152 }
153 } else {
154 parse_identifier_token(self, global_store)
155 }
156 }
157 TokenKind::Dot => parse_dot_token(self, global_store),
158 TokenKind::Tempo => parse_tempo_token(self, global_store),
159 TokenKind::Bank => parse_bank_token(self, global_store),
160 TokenKind::Pattern => parse_pattern_token(self, global_store),
161 TokenKind::Loop => parse_loop_token(self, global_store),
162 TokenKind::If => parse_condition_token(self, global_store),
163 TokenKind::Function => parse_function_token(self, global_store),
164 TokenKind::On => parse_on_token(self, global_store),
165 TokenKind::Emit => parse_emit_token(self, token.clone(), global_store),
166
167 | TokenKind::Else | TokenKind::Comment
169 | TokenKind::Equals
170 | TokenKind::Colon
171 | TokenKind::Number
172 | TokenKind::String
173 | TokenKind::LBrace
174 | TokenKind::RBrace
175 | TokenKind::Comma
176 | TokenKind::Dedent
177 | TokenKind::Indent => {
178 self.advance();
179 continue;
180 }
181
182 TokenKind::EOF => {
183 break;
184 }
185
186 _ => {
187 self.advance();
188 Statement::unknown_with_pos(token.indent, token.line, token.column)
189 }
190 };
191
192 statements.push(statement);
193 }
194
195 statements
196 }
197
198 pub fn check_token(&self, kind: TokenKind) -> bool {
199 self.peek().is_some_and(|t| t.kind == kind)
200 }
201
202 pub fn peek_kind(&self) -> Option<TokenKind> {
203 self.peek().map(|t| t.kind.clone())
204 }
205
206 pub fn parse_map_value(&mut self) -> Option<Value> {
207 let logger = devalang_utils::logger::Logger::new();
208 use devalang_utils::logger::LogLevel;
209 if !self.match_token(TokenKind::LBrace) {
210 return None;
211 }
212
213 let mut map = std::collections::HashMap::new();
214
215 while !self.check_token(TokenKind::RBrace) && !self.is_eof() {
216 while self.check_token(TokenKind::Newline)
218 || self.check_token(TokenKind::Whitespace)
219 || self.check_token(TokenKind::Indent)
220 || self.check_token(TokenKind::Dedent)
221 || self.check_token(TokenKind::Comma)
222 {
223 self.advance();
224 }
225
226 if self.check_token(TokenKind::RBrace) {
228 break;
229 }
230
231 let key = if let Some(token) = self.advance() {
232 match token.kind {
233 TokenKind::Whitespace
234 | TokenKind::Indent
235 | TokenKind::Dedent
236 | TokenKind::Newline => {
237 continue;
238 }
239 _ => token.lexeme.clone(),
240 }
241 } else {
242 break;
243 };
244
245 while self.check_token(TokenKind::Newline) || self.check_token(TokenKind::Whitespace) {
247 self.advance();
248 }
249
250 if !self.match_token(TokenKind::Colon) {
251 logger.log_message(
252 LogLevel::Error,
253 &format!("Expected ':' after map key '{}'", key),
254 );
255 break;
256 }
257
258 while self.check_token(TokenKind::Newline)
260 || self.check_token(TokenKind::Whitespace)
261 || self.check_token(TokenKind::Indent)
262 || self.check_token(TokenKind::Dedent)
263 || self.check_token(TokenKind::Comma)
264 {
265 self.advance();
266 }
267
268 let value = if let Some(token) = self.peek_clone() {
269 match token.kind {
270 TokenKind::String => {
271 self.advance();
272 Value::String(token.lexeme.clone())
273 }
274 TokenKind::Number => {
275 let mut number_str = token.lexeme.clone();
276 self.advance(); if let Some(dot_token) = self.peek_clone() {
279 if dot_token.kind == TokenKind::Dot {
280 self.advance(); if let Some(decimal_token) = self.peek_clone() {
283 if decimal_token.kind == TokenKind::Number {
284 self.advance(); number_str.push('.');
286 number_str.push_str(&decimal_token.lexeme);
287 } else {
288 logger.log_message(
289 LogLevel::Error,
290 &format!(
291 "Expected number after dot, got {:?}",
292 decimal_token
293 ),
294 );
295 return Some(Value::Null);
296 }
297 } else {
298 logger.log_message(
299 LogLevel::Error,
300 "Expected number after dot, but reached EOF",
301 );
302 return Some(Value::Null);
303 }
304 }
305 }
306
307 Value::Number(number_str.parse::<f32>().unwrap_or(0.0))
308 }
309
310 TokenKind::Identifier => {
311 let current_line = token.line;
313 let mut parts: Vec<String> = vec![token.lexeme.clone()];
314 self.advance();
315 loop {
316 let Some(next) = self.peek_clone() else { break };
317 if next.line != current_line {
318 break;
319 }
320 if next.kind == TokenKind::Dot {
321 self.advance(); if let Some(id2) = self.peek_clone() {
324 if id2.line == current_line
325 && (id2.kind == TokenKind::Identifier
326 || id2.kind == TokenKind::Number)
327 {
328 parts.push(id2.lexeme.clone());
329 self.advance(); continue;
331 }
332 }
333 break;
334 } else {
335 break;
336 }
337 }
338 Value::Identifier(parts.join("."))
339 }
340 _ => {
341 logger.log_message(
342 LogLevel::Error,
343 &format!("Unexpected token in map value: {:?}", token),
344 );
345 Value::Null
346 }
347 }
348 } else {
349 Value::Null
350 };
351
352 map.insert(key, value);
353
354 while self.check_token(TokenKind::Comma)
356 || self.check_token(TokenKind::Whitespace)
357 || self.check_token(TokenKind::Newline)
358 {
359 self.advance();
360 }
361 }
362
363 if !self.match_token(TokenKind::RBrace) {
364 logger.log_message(LogLevel::Error, "Expected '}' at end of map");
365 }
366
367 Some(Value::Map(map))
368 }
369
370 pub fn parse_array_value(&mut self) -> Option<Value> {
372 let logger = devalang_utils::logger::Logger::new();
373 use devalang_utils::logger::LogLevel;
374 if !self.match_token(TokenKind::LBracket) {
375 return None;
376 }
377
378 let mut arr: Vec<Value> = Vec::new();
379
380 while !self.check_token(TokenKind::RBracket) && !self.is_eof() {
381 while self.check_token(TokenKind::Newline)
383 || self.check_token(TokenKind::Whitespace)
384 || self.check_token(TokenKind::Indent)
385 || self.check_token(TokenKind::Dedent)
386 || self.check_token(TokenKind::Comma)
387 {
388 self.advance();
389 }
390
391 if self.check_token(TokenKind::RBracket) {
392 break;
393 }
394
395 if let Some(token) = self.peek_clone() {
396 let value = match token.kind {
397 TokenKind::String => {
398 self.advance();
399 Value::String(token.lexeme.clone())
400 }
401 TokenKind::Number => {
402 let mut number_str = token.lexeme.clone();
404 self.advance();
405 if let Some(dot) = self.peek_clone() {
406 if dot.kind == TokenKind::Dot {
407 if let Some(next) = self.peek_nth(1).cloned() {
408 if next.kind == TokenKind::Number {
409 self.advance(); self.advance(); number_str.push('.');
412 number_str.push_str(&next.lexeme);
413 }
414 }
415 }
416 }
417 Value::Number(number_str.parse::<f32>().unwrap_or(0.0))
418 }
419 TokenKind::Identifier => {
420 self.advance();
421 Value::Identifier(token.lexeme.clone())
422 }
423 TokenKind::LBrace => {
424 if let Some(v) = self.parse_map_value() {
426 v
427 } else {
428 Value::Null
429 }
430 }
431 TokenKind::LBracket => {
432 if let Some(v) = self.parse_array_value() {
434 v
435 } else {
436 Value::Null
437 }
438 }
439 _ => {
440 self.advance();
441 Value::Null
442 }
443 };
444
445 if value != Value::Null {
447 arr.push(value);
448 }
449
450 } else {
452 break;
453 }
454 }
455
456 if !self.match_token(TokenKind::RBracket) {
457 logger.log_message(LogLevel::Error, "Expected ']' at end of array");
458 }
459
460 Some(Value::Array(arr))
461 }
462
463 pub fn peek(&self) -> Option<&Token> {
464 self.tokens.get(self.token_index)
465 }
466
467 pub fn peek_clone(&self) -> Option<Token> {
468 self.tokens.get(self.token_index).cloned()
469 }
470
471 pub fn expect(&mut self, kind: TokenKind) -> Result<&Token, String> {
472 let tok = self.advance().ok_or("Unexpected end of input")?;
473 if tok.kind == kind {
474 Ok(tok)
475 } else {
476 Err(format!("Expected {:?}, got {:?}", kind, tok.kind))
477 }
478 }
479
480 pub fn collect_block_tokens(&mut self, base_indent: usize) -> Vec<Token> {
481 let mut tokens = Vec::new();
482
483 while let Some(tok) = self.peek() {
484 if tok.indent <= base_indent && tok.kind != TokenKind::Newline {
485 break;
486 }
487 if let Some(t) = self.advance() {
488 tokens.push(t.clone());
489 } else {
490 break;
492 }
493 }
494
495 tokens
496 }
497
498 pub fn collect_until<F>(&mut self, condition: F) -> Vec<Token>
499 where
500 F: Fn(&Token) -> bool,
501 {
502 let mut collected = Vec::new();
503 while let Some(token) = self.peek() {
504 if condition(token) {
505 break;
506 }
507 if token.kind == TokenKind::EOF {
508 break;
509 }
510 if let Some(t) = self.advance() {
511 collected.push(t.clone());
512 } else {
513 break;
514 }
515 }
516
517 collected
518 }
519
520 pub fn is_eof(&self) -> bool {
521 self.token_index >= self.tokens.len()
522 }
523
524 pub fn parse_block_until_next_else(
525 &mut self,
526 base_indent: usize,
527 global_store: &mut GlobalStore,
528 ) -> Vec<Statement> {
529 let mut block_tokens = Vec::new();
530
531 while let Some(tok) = self.peek() {
532 if tok.lexeme == "else" && tok.indent == base_indent {
534 break;
535 }
536 if let Some(t) = self.advance() {
537 block_tokens.push(t.clone());
538 } else {
539 break;
540 }
541 }
542
543 self.parse_block(block_tokens, global_store)
544 }
545
546 pub fn parse_condition_until_colon(&mut self) -> Option<Value> {
547 let tokens = self.collect_until(|t| t.kind == TokenKind::Colon);
548 if tokens.is_empty() {
549 return None;
550 }
551
552 let condition = tokens
553 .iter()
554 .map(|t| t.lexeme.clone())
555 .collect::<Vec<_>>()
556 .join(" ");
557
558 Some(Value::String(condition))
559 }
560
561 pub fn parse_block_until_else_or_dedent(
562 &mut self,
563 base_indent: usize,
564 global_store: &mut GlobalStore,
565 ) -> Vec<Statement> {
566 let mut tokens = Vec::new();
567
568 while let Some(tok) = self.peek() {
569 if tok.lexeme == "else" && tok.indent == base_indent {
570 break;
571 }
572 if tok.indent < base_indent && tok.kind != TokenKind::Newline {
573 break;
574 }
575 if let Some(t) = self.advance() {
576 tokens.push(t.clone());
577 } else {
578 break;
579 }
580 }
581
582 self.parse_block(tokens, global_store)
583 }
584}