devalang_core/core/parser/handler/
condition.rs

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