devalang_core/core/parser/handler/
loop_.rs1use 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_loop_token(parser: &mut Parser, global_store: &mut GlobalStore) -> Statement {
13 parser.advance(); let Some(loop_token) = parser.previous_clone() else {
15 return Statement::unknown();
16 };
17
18 let Some(next_token) = parser.peek_clone() else {
24 return Statement::error_with_pos(
25 loop_token.indent,
26 loop_token.line,
27 loop_token.column,
28 "Expected iterator after loop/for".to_string(),
29 );
30 };
31
32 let mut foreach_ident: Option<String> = None;
34 if let TokenKind::Identifier = next_token.kind {
35 let name = next_token.lexeme.clone();
38 if let Some(t2) = parser.peek_nth(1) {
40 if t2.kind == TokenKind::Identifier && t2.lexeme == "in" {
41 foreach_ident = Some(name);
43 parser.advance();
45 parser.advance();
46 }
47 }
48 }
49
50 if let Some(var_name) = foreach_ident {
51 let array_val = if let Some(tok) = parser.peek_clone() {
53 match tok.kind {
54 TokenKind::LBracket => {
55 if let Some(v) = parser.parse_array_value() {
56 v
57 } else {
58 Value::Array(vec![])
59 }
60 }
61 TokenKind::Number => {
62 parser.advance();
63 let n = tok.lexeme.parse::<f32>().unwrap_or(0.0);
64 Value::Number(n)
65 }
66 TokenKind::String => {
67 parser.advance();
68 Value::String(tok.lexeme.clone())
69 }
70 TokenKind::Identifier => {
71 parser.advance();
72 Value::Identifier(tok.lexeme.clone())
73 }
74 _ => {
75 return Statement::error_with_pos(
76 loop_token.indent,
77 loop_token.line,
78 loop_token.column,
79 "Expected array, number, string or identifier after 'in'".to_string(),
80 );
81 }
82 }
83 } else {
84 return Statement::error_with_pos(
85 loop_token.indent,
86 loop_token.line,
87 loop_token.column,
88 "Expected array, number, string or identifier after 'in'".to_string(),
89 );
90 };
91
92 if !parser.match_token(TokenKind::Colon) {
94 return Statement::error_with_pos(
95 loop_token.indent,
96 loop_token.line,
97 loop_token.column,
98 "Expected ':' after foreach header".to_string(),
99 );
100 }
101
102 let tokens =
103 parser.collect_until(|t| t.kind == TokenKind::Dedent || t.kind == TokenKind::EOF);
104 let loop_body = parser.parse_block(tokens.clone(), global_store);
105 if let Some(token) = parser.peek() {
106 if token.kind == TokenKind::Dedent {
107 parser.advance();
108 }
109 }
110
111 let mut value_map = std::collections::HashMap::new();
112 value_map.insert("foreach".to_string(), Value::Identifier(var_name));
113 value_map.insert("array".to_string(), array_val);
114 value_map.insert("body".to_string(), Value::Block(loop_body.clone()));
115
116 return Statement {
117 kind: StatementKind::Loop,
118 value: Value::Map(value_map),
119 indent: loop_token.indent,
120 line: loop_token.line,
121 column: loop_token.column,
122 };
123 }
124
125 let Some(iterator_token) = parser.peek_clone() else {
127 return Statement::error_with_pos(
128 loop_token.indent,
129 loop_token.line,
130 loop_token.column,
131 "Expected number or identifier after 'loop'".to_string(),
132 );
133 };
134
135 let iterator_value = match iterator_token.kind {
136 TokenKind::Number => {
137 let val = iterator_token.lexeme.parse::<f32>().unwrap_or(1.0);
138 parser.advance();
139 Value::Number(val)
140 }
141 TokenKind::Identifier => {
142 let val = iterator_token.lexeme.clone();
143 parser.advance();
144 Value::Identifier(val)
145 }
146 TokenKind::String => {
147 let s = iterator_token.lexeme.clone();
149 parser.advance();
150 Value::String(s)
151 }
152 _ => {
153 return Statement::error_with_pos(
154 iterator_token.clone().indent,
155 iterator_token.clone().line,
156 iterator_token.clone().column,
157 "Expected a number, string or identifier as loop count".to_string(),
158 );
159 }
160 };
161
162 if !parser.match_token(TokenKind::Colon) {
163 let message = format!(
164 "Expected ':' after loop count, got {:?}",
165 parser.peek_kind()
166 );
167 return Statement::error_with_pos(
168 loop_token.clone().indent,
169 loop_token.clone().line,
170 loop_token.clone().column,
171 message,
172 );
173 }
174
175 let tokens = parser.collect_until(|t| t.kind == TokenKind::Dedent || t.kind == TokenKind::EOF);
176 let loop_body = parser.parse_block(tokens.clone(), global_store);
177 if let Some(token) = parser.peek() {
178 if token.kind == TokenKind::Dedent {
179 parser.advance();
180 }
181 }
182
183 let mut value_map = std::collections::HashMap::new();
184 value_map.insert("iterator".to_string(), iterator_value);
185 value_map.insert("body".to_string(), Value::Block(loop_body.clone()));
186
187 Statement {
188 kind: StatementKind::Loop,
189 value: Value::Map(value_map),
190 indent: loop_token.indent,
191 line: loop_token.line,
192 column: loop_token.column,
193 }
194}