devalang_core/core/parser/handler/
condition.rs

1use crate::core::{
2    lexer::token::TokenKind,
3    parser::{
4        driver::Parser,
5        statement::{Statement, StatementKind},
6    },
7    shared::value::Value,
8    store::global::GlobalStore,
9};
10use std::collections::HashMap;
11
12pub fn parse_condition_token(parser: &mut Parser, global_store: &mut GlobalStore) -> Statement {
13    parser.advance(); // consume 'if'
14    let Some(if_token) = parser.previous_clone() else {
15        return Statement::unknown();
16    };
17
18    let Some(condition) = parser.parse_condition_until_colon() else {
19        return Statement::error(if_token, "Expected condition after 'if'".to_string());
20    };
21
22    parser.advance_if(TokenKind::Colon);
23    let base_indent = if_token.indent;
24
25    let if_body = parser.parse_block_until_else_or_dedent(base_indent, global_store);
26
27    let mut root_map = HashMap::new();
28    root_map.insert("condition".to_string(), condition);
29    root_map.insert("body".to_string(), Value::Block(if_body));
30
31    let mut current = &mut root_map;
32
33    // Loop for else / else if
34    while let Some(tok) = parser.peek_clone() {
35        // Only continue if we see `else` at same indent level
36        if tok.lexeme != "else" || tok.indent != base_indent {
37            break;
38        }
39
40        parser.advance(); // consume 'else'
41
42        // Check if it's an 'else if'
43        let next_condition = if parser.peek_is("if") {
44            parser.advance(); // consume 'if'
45            let Some(cond) = parser.parse_condition_until_colon() else {
46                return Statement::error(
47                    tok.clone(),
48                    "Expected condition after 'else if'".to_string(),
49                );
50            };
51            parser.advance_if(TokenKind::Colon);
52            Some(cond)
53        } else {
54            parser.advance_if(TokenKind::Colon);
55            None
56        };
57
58        let body = parser.parse_block_until_else_or_dedent(base_indent, global_store);
59
60        let mut next_map = HashMap::new();
61        if let Some(cond) = next_condition {
62            next_map.insert("condition".to_string(), cond);
63        }
64        next_map.insert("body".to_string(), Value::Block(body));
65
66        current.insert("next".to_string(), Value::Map(next_map));
67        current = match current.get_mut("next") {
68            Some(Value::Map(map)) => map,
69            _ => break,
70        };
71    }
72
73    Statement {
74        kind: StatementKind::If,
75        value: Value::Map(root_map),
76        indent: if_token.indent,
77        line: if_token.line,
78        column: if_token.column,
79    }
80}