devalang_core/core/parser/handler/identifier/
automate.rs1use crate::core::{
2 lexer::token::{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_automate_token(
13 parser: &mut Parser,
14 current_token: Token,
15 _global_store: &mut GlobalStore,
16) -> Statement {
17 parser.advance(); let Some(target_token) = parser.peek_clone() else {
21 return crate::core::parser::statement::error_from_token(
22 current_token,
23 "Expected target after 'automate'".to_string(),
24 );
25 };
26
27 if target_token.kind != TokenKind::Identifier && target_token.kind != TokenKind::String {
28 return crate::core::parser::statement::error_from_token(
29 target_token,
30 "Expected valid target after 'automate'".to_string(),
31 );
32 }
33 parser.advance(); let Some(colon_token) = parser.peek_clone() else {
37 return crate::core::parser::statement::error_from_token(
38 target_token,
39 "Expected ':' after automate target".to_string(),
40 );
41 };
42 if colon_token.kind != TokenKind::Colon {
43 return crate::core::parser::statement::error_from_token(
44 colon_token,
45 "Expected ':' after automate target".to_string(),
46 );
47 }
48 parser.advance(); let base_indent = current_token.indent;
51
52 let mut index = parser.token_index;
54 let mut tokens_inside = Vec::new();
55 while index < parser.tokens.len() {
56 let tok = parser.tokens[index].clone();
57 if tok.indent <= base_indent && tok.kind != TokenKind::Newline {
58 break;
59 }
60 tokens_inside.push(tok);
61 index += 1;
62 }
63 parser.token_index = index;
64
65 let mut local = Parser {
67 resolve_modules: parser.resolve_modules,
68 tokens: tokens_inside,
69 token_index: 0,
70 current_module: parser.current_module.clone(),
71 previous: None,
72 };
73
74 let mut params: HashMap<String, Value> = HashMap::new();
75
76 while let Some(tok) = local.peek_clone() {
77 match tok.kind {
78 TokenKind::Identifier if tok.lexeme == "param" => {
79 local.advance(); let Some(name_tok) = local.peek_clone() else {
82 return crate::core::parser::statement::error_from_token(
83 tok,
84 "Expected parameter name after 'param'".to_string(),
85 );
86 };
87 if name_tok.kind != TokenKind::Identifier && name_tok.kind != TokenKind::String {
88 return crate::core::parser::statement::error_from_token(
89 name_tok,
90 "Expected valid parameter name".to_string(),
91 );
92 }
93 local.advance(); if !local.match_token(TokenKind::LBrace) {
97 return crate::core::parser::statement::error_from_token(
98 name_tok,
99 "Expected '{' to start parameter block".to_string(),
100 );
101 }
102
103 let mut envelope: HashMap<String, Value> = HashMap::new();
105 while let Some(inner) = local.peek_clone() {
106 if inner.kind == TokenKind::RBrace {
107 local.advance();
108 break;
109 }
110 if matches!(
112 inner.kind,
113 TokenKind::Newline
114 | TokenKind::Indent
115 | TokenKind::Dedent
116 | TokenKind::Comma
117 ) {
118 local.advance();
119 continue;
120 }
121
122 let percent_token = inner.clone();
125 local.advance();
126
127 let percent_key = percent_token.lexeme.clone();
128
129 while let Some(t) = local.peek_kind() {
132 if matches!(
133 t,
134 TokenKind::Indent | TokenKind::Dedent | TokenKind::Newline
135 ) {
136 local.advance();
137 continue;
138 }
139 break;
140 }
141 if !local.match_token(TokenKind::Equals) {
142 return crate::core::parser::statement::error_from_token(
143 percent_token,
144 "Expected '=' in param entry".to_string(),
145 );
146 }
147
148 while let Some(t) = local.peek_kind() {
151 if matches!(
152 t,
153 TokenKind::Indent | TokenKind::Dedent | TokenKind::Newline
154 ) {
155 local.advance();
156 continue;
157 }
158 break;
159 }
160
161 let value = if let Some(vtok) = local.peek_clone() {
162 match vtok.kind {
163 TokenKind::Arrow => {
165 let mut num_str = String::from("-");
167 local.advance(); if let Some(ntok) = local.peek_clone() {
169 if ntok.kind == TokenKind::Number {
170 num_str.push_str(&ntok.lexeme);
171 local.advance(); if let Some(dot) = local.peek_clone() {
173 if dot.kind == TokenKind::Dot {
174 local.advance();
175 if let Some(frac) = local.peek_clone() {
176 if frac.kind == TokenKind::Number {
177 num_str.push('.');
178 num_str.push_str(&frac.lexeme);
179 local.advance();
180 }
181 }
182 }
183 }
184 Value::Number(num_str.parse::<f32>().unwrap_or(0.0))
185 } else {
186 Value::Unknown
187 }
188 } else {
189 Value::Unknown
190 }
191 }
192 TokenKind::Number => {
193 let mut number_str = vtok.lexeme.clone();
195 local.advance();
196 if let Some(dot) = local.peek_clone() {
197 if dot.kind == TokenKind::Dot {
198 local.advance();
199 if let Some(frac) = local.peek_clone() {
200 if frac.kind == TokenKind::Number {
201 number_str.push('.');
202 number_str.push_str(&frac.lexeme);
203 local.advance();
204 }
205 }
206 }
207 }
208 Value::Number(number_str.parse::<f32>().unwrap_or(0.0))
209 }
210 TokenKind::Identifier => {
211 local.advance();
212 Value::Identifier(vtok.lexeme.clone())
213 }
214 TokenKind::String => {
215 local.advance();
216 Value::String(vtok.lexeme.clone())
217 }
218 _ => {
219 local.advance();
220 Value::Unknown
221 }
222 }
223 } else {
224 Value::Null
225 };
226
227 envelope.insert(percent_key, value);
228 }
229
230 params.insert(name_tok.lexeme.clone(), Value::Map(envelope));
231 }
232 _ => {
233 local.advance();
234 }
235 }
236 }
237
238 let mut value_map = HashMap::new();
239 value_map.insert(
240 "target".to_string(),
241 Value::String(target_token.lexeme.clone()),
242 );
243 value_map.insert("params".to_string(), Value::Map(params));
244
245 Statement {
246 kind: StatementKind::Automate {
247 target: target_token.lexeme.clone(),
248 },
249 value: Value::Map(value_map),
250 indent: current_token.indent,
251 line: current_token.line,
252 column: current_token.column,
253 }
254}