devalang_core/core/parser/handler/identifier/
on.rs

1use devalang_types::Value;
2
3use crate::core::{
4    lexer::token::TokenKind,
5    parser::{
6        driver::parser::Parser,
7        statement::{Statement, StatementKind},
8    },
9    store::global::GlobalStore,
10};
11
12pub fn parse_on_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
13    // consume 'on'
14    let on_tok = match parser.peek_clone() {
15        Some(tok) => tok,
16        None => return Statement::unknown(),
17    };
18    parser.advance();
19
20    // Expect event name identifier
21    let event_tok = match parser.peek_clone() {
22        Some(tok) if tok.kind == TokenKind::Identifier => tok,
23        Some(other) => {
24            return crate::core::parser::statement::error_from_token(
25                other,
26                "Expected event name after 'on'".to_string(),
27            );
28        }
29        None => {
30            return crate::core::parser::statement::error_from_token(
31                on_tok,
32                "Expected event name after 'on'".to_string(),
33            );
34        }
35    };
36    let event_name = event_tok.lexeme.clone();
37    parser.advance();
38
39    // Optional parenthesized args on same line
40    let mut args: Option<Vec<Value>> = None;
41    if parser.peek_kind() == Some(TokenKind::LParen) {
42        parser.advance(); // '('
43        let mut collected: Vec<Value> = Vec::new();
44        // Collect tokens until ')', supporting numbers and identifiers separated by comma
45        while let Some(tok) = parser.peek_clone() {
46            match tok.kind {
47                TokenKind::RParen => {
48                    parser.advance();
49                    break;
50                }
51                TokenKind::Number => {
52                    parser.advance();
53                    collected.push(Value::Number(tok.lexeme.parse().unwrap_or(0.0)));
54                }
55                TokenKind::Identifier => {
56                    parser.advance();
57                    collected.push(Value::Identifier(tok.lexeme));
58                }
59                TokenKind::Comma => {
60                    parser.advance();
61                }
62                TokenKind::Whitespace | TokenKind::Newline => {
63                    parser.advance();
64                }
65                _ => {
66                    break;
67                }
68            }
69        }
70        if !collected.is_empty() {
71            args = Some(collected);
72        }
73    }
74
75    // Expect ':' then block
76    if parser.peek_kind() != Some(TokenKind::Colon) {
77        return crate::core::parser::statement::error_from_token(
78            event_tok,
79            "Expected ':' after event name".to_string(),
80        );
81    }
82    parser.advance(); // consume ':'
83
84    let base_indent = on_tok.indent;
85    let block_tokens = parser.collect_block_tokens(base_indent);
86    // Parse body within current store context
87    let body = parser.parse_block(block_tokens, _global_store);
88
89    let stmt = Statement {
90        kind: StatementKind::On {
91            event: event_name,
92            args,
93            body,
94        },
95        value: Value::Null,
96        indent: on_tok.indent,
97        line: on_tok.line,
98        column: on_tok.column,
99    };
100
101    // Register in global store for later emission
102    if let StatementKind::On { event, .. } = &stmt.kind {
103        _global_store.register_event_handler(event, stmt.clone());
104    }
105
106    stmt
107}