devalang_core/core/parser/handler/
condition.rs

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