devalang_core/core/parser/driver/
parse_array.rs

1use crate::core::lexer::token::TokenKind;
2use devalang_types::Value;
3
4pub fn parse_array_value(
5    parser: &mut crate::core::parser::driver::parser::Parser,
6) -> Option<Value> {
7    let logger = devalang_utils::logger::Logger::new();
8    use devalang_utils::logger::LogLevel;
9    if !parser.match_token(TokenKind::LBracket) {
10        return None;
11    }
12
13    let mut arr: Vec<Value> = Vec::new();
14
15    while !parser.check_token(TokenKind::RBracket) && !parser.is_eof() {
16        // Skip formatting tokens
17        while parser.check_token(TokenKind::Newline)
18            || parser.check_token(TokenKind::Whitespace)
19            || parser.check_token(TokenKind::Indent)
20            || parser.check_token(TokenKind::Dedent)
21            || parser.check_token(TokenKind::Comma)
22        {
23            parser.advance();
24        }
25
26        if parser.check_token(TokenKind::RBracket) {
27            break;
28        }
29
30        if let Some(token) = parser.peek_clone() {
31            let value = match token.kind {
32                TokenKind::String => {
33                    parser.advance();
34                    Value::String(token.lexeme.clone())
35                }
36                TokenKind::Number => {
37                    // Support decimals and fraction literals (e.g., 1/4 -> Duration::Beat("1/4"))
38                    let mut number_str = token.lexeme.clone();
39                    parser.advance();
40                    if let Some(dot) = parser.peek_clone() {
41                        if dot.kind == TokenKind::Dot {
42                            if let Some(next) = parser.peek_nth(1).cloned() {
43                                if next.kind == TokenKind::Number {
44                                    parser.advance(); // consume dot
45                                    parser.advance(); // consume next number
46                                    number_str.push('.');
47                                    number_str.push_str(&next.lexeme);
48                                }
49                            }
50                        }
51                    }
52
53                    // Fraction form: number '/' number or identifier
54                    if let Some(slash_tok) = parser.peek_clone() {
55                        if slash_tok.kind == TokenKind::Slash {
56                            // consume '/'
57                            parser.advance();
58                            if let Some(den_tok) = parser.peek_clone() {
59                                match den_tok.kind {
60                                    TokenKind::Number | TokenKind::Identifier => {
61                                        let frac = format!("{}/{}", number_str, den_tok.lexeme);
62                                        parser.advance();
63                                        Value::Duration(devalang_types::Duration::Beat(frac))
64                                    }
65                                    _ => Value::Number(number_str.parse::<f32>().unwrap_or(0.0)),
66                                }
67                            } else {
68                                Value::Number(number_str.parse::<f32>().unwrap_or(0.0))
69                            }
70                        } else {
71                            Value::Number(number_str.parse::<f32>().unwrap_or(0.0))
72                        }
73                    } else {
74                        Value::Number(number_str.parse::<f32>().unwrap_or(0.0))
75                    }
76                }
77                TokenKind::Identifier => {
78                    parser.advance();
79                    Value::Identifier(token.lexeme.clone())
80                }
81                TokenKind::LBrace => {
82                    // Allow inline maps inside arrays
83                    if let Some(v) = crate::core::parser::driver::parse_map::parse_map_value(parser)
84                    {
85                        v
86                    } else {
87                        Value::Null
88                    }
89                }
90                TokenKind::LBracket => {
91                    // Nested arrays
92                    if let Some(v) = parse_array_value(parser) {
93                        v
94                    } else {
95                        Value::Null
96                    }
97                }
98                _ => {
99                    parser.advance();
100                    Value::Null
101                }
102            };
103
104            // Only push non-null (retain alignment with permissive parsing)
105            if value != Value::Null {
106                arr.push(value);
107            }
108
109            // Optional trailing comma handled by the skipper at loop start
110        } else {
111            break;
112        }
113    }
114
115    if !parser.match_token(TokenKind::RBracket) {
116        logger.log_message(LogLevel::Error, "Expected ']' at end of array");
117    }
118
119    Some(Value::Array(arr))
120}