devalang_wasm/language/syntax/parser/driver/
helpers.rs1use crate::language::syntax::ast::Value;
2use anyhow::Result;
4use std::collections::HashMap;
5
6pub fn parse_function_args(args_str: &str) -> Result<Vec<Value>> {
9 let mut args = Vec::new();
10 let mut current_arg = String::new();
11 let mut depth = 0; let mut in_string = false;
13
14 for ch in args_str.chars() {
15 match ch {
16 '"' => {
17 in_string = !in_string;
18 current_arg.push(ch);
19 }
20 '[' | '{' if !in_string => {
21 depth += 1;
22 current_arg.push(ch);
23 }
24 ']' | '}' if !in_string => {
25 depth -= 1;
26 current_arg.push(ch);
27 }
28 ',' if depth == 0 && !in_string => {
29 if !current_arg.trim().is_empty() {
31 args.push(parse_single_arg(current_arg.trim())?);
32 current_arg.clear();
33 }
34 }
35 _ => {
36 current_arg.push(ch);
37 }
38 }
39 }
40
41 if !current_arg.trim().is_empty() {
43 args.push(parse_single_arg(current_arg.trim())?);
44 }
45
46 Ok(args)
47}
48
49pub fn parse_single_arg(arg: &str) -> Result<Value> {
51 let arg = arg.trim();
52
53 if arg.starts_with('"') && arg.ends_with('"') {
55 return Ok(Value::String(arg[1..arg.len() - 1].to_string()));
56 }
57
58 if arg.starts_with('[') && arg.ends_with(']') {
60 let inner = &arg[1..arg.len() - 1];
61 let items = parse_function_args(inner)?;
62 return Ok(Value::Array(items));
63 }
64
65 if arg.starts_with('{') && arg.ends_with('}') {
67 let inner = &arg[1..arg.len() - 1];
68 let mut map = HashMap::new();
69
70 for pair in inner.split(',') {
72 if let Some(colon_idx) = pair.find(':') {
73 let key = pair[..colon_idx].trim().trim_matches('"');
74 let value = parse_single_arg(pair[colon_idx + 1..].trim())?;
75 map.insert(key.to_string(), value);
76 }
77 }
78
79 return Ok(Value::Map(map));
80 }
81
82 if let Ok(num) = arg.parse::<f32>() {
84 return Ok(Value::Number(num));
85 }
86
87 match arg.to_lowercase().as_str() {
89 "true" => return Ok(Value::Boolean(true)),
90 "false" => return Ok(Value::Boolean(false)),
91 _ => {}
92 }
93
94 Ok(Value::Identifier(arg.to_string()))
96}
97
98pub fn parse_synth_definition(input: &str) -> Result<Value> {
101 let input = input.trim_start_matches("synth ").trim();
103
104 let (waveform, params_str) = if let Some(brace_idx) = input.find('{') {
106 let waveform = input[..brace_idx].trim();
107 let params = &input[brace_idx..];
108 (waveform, params)
109 } else {
110 return Ok(Value::Map({
112 let mut map = HashMap::new();
113 map.insert("type".to_string(), Value::String("synth".to_string()));
114 map.insert("waveform".to_string(), Value::String(input.to_string()));
115 map
116 }));
117 };
118
119 let params_str = params_str.trim_matches(|c| c == '{' || c == '}').trim();
121 let mut params_map = HashMap::new();
122
123 params_map.insert("type".to_string(), Value::String("synth".to_string()));
125 params_map.insert("waveform".to_string(), Value::String(waveform.to_string()));
126
127 if !params_str.is_empty() {
129 let mut cleaned_lines = Vec::new();
131 for line in params_str.lines() {
132 if let Some(comment_pos) = line.find("//") {
133 let clean_line = &line[..comment_pos];
134 if !clean_line.trim().is_empty() {
135 cleaned_lines.push(clean_line);
136 }
137 } else if !line.trim().is_empty() {
138 cleaned_lines.push(line);
139 }
140 }
141
142 let cleaned = cleaned_lines.join("\n");
144 let normalized = cleaned.replace('\n', ",").replace('\r', "");
145
146 for pair in normalized.split(',') {
147 let pair = pair.trim();
148 if pair.is_empty() {
149 continue;
150 }
151
152 let parts: Vec<&str> = pair.split(':').collect();
153 if parts.len() >= 2 {
154 let key = parts[0].trim().to_string();
155 let value_part = parts[1..].join(":");
157 let value_str = value_part.trim().trim_matches(',');
158
159 if value_str.starts_with('[') {
161 if let Ok(array_val) = parse_array_value(value_str) {
162 params_map.insert(key, array_val);
163 continue;
164 }
165 }
166
167 if let Ok(num) = value_str.parse::<f32>() {
169 params_map.insert(key, Value::Number(num));
170 } else {
171 params_map.insert(key, Value::String(value_str.to_string()));
173 }
174 }
175 }
176 }
177
178 Ok(Value::Map(params_map))
179}
180
181pub fn parse_array_value(input: &str) -> Result<Value> {
183 let input = input.trim().trim_matches(|c| c == '[' || c == ']').trim();
184 if input.is_empty() {
185 return Ok(Value::Array(Vec::new()));
186 }
187
188 if input.contains("..") {
190 let parts: Vec<&str> = input.split("..").collect();
191 if parts.len() == 2 {
192 let start_str = parts[0].trim();
193 let end_str = parts[1].trim();
194
195 if let (Ok(start), Ok(end)) = (start_str.parse::<f32>(), end_str.parse::<f32>()) {
197 return Ok(Value::Range {
198 start: Box::new(Value::Number(start)),
199 end: Box::new(Value::Number(end)),
200 });
201 }
202 }
203 }
204
205 let mut items = Vec::new();
206 let mut depth = 0;
207 let mut current = String::new();
208
209 for ch in input.chars() {
210 match ch {
211 '{' => {
212 depth += 1;
213 current.push(ch);
214 }
215 '}' => {
216 depth -= 1;
217 current.push(ch);
218
219 if depth == 0 && !current.trim().is_empty() {
220 if let Ok(obj) = parse_map_value(¤t) {
222 items.push(obj);
223 }
224 current.clear();
225 }
226 }
227 ',' if depth == 0 => {
228 continue;
230 }
231 _ => {
232 current.push(ch);
233 }
234 }
235 }
236
237 Ok(Value::Array(items))
238}
239
240pub fn parse_map_value(input: &str) -> Result<Value> {
242 let input = input.trim().trim_matches(|c| c == '{' || c == '}').trim();
243 let mut map = HashMap::new();
244
245 for pair in input.split(',') {
246 let pair = pair.trim();
247 if pair.is_empty() {
248 continue;
249 }
250
251 let parts: Vec<&str> = pair.split(':').collect();
252 if parts.len() >= 2 {
253 let key = parts[0].trim().to_string();
254 let value_part = parts[1..].join(":");
256
257 let value_clean = if let Some(comment_pos) = value_part.find("//") {
259 &value_part[..comment_pos]
260 } else {
261 &value_part
262 };
263
264 let value_str = value_clean.trim().trim_matches('"').trim_matches('\'');
265
266 if let Ok(num) = value_str.parse::<f32>() {
268 map.insert(key, Value::Number(num));
269 } else {
270 map.insert(key, Value::String(value_str.to_string()));
271 }
272 }
273 }
274
275 Ok(Value::Map(map))
276}
277
278pub fn parse_condition(condition_str: &str) -> Result<Value> {
281 let operators = vec![">=", "<=", "==", "!=", ">", "<"];
283 for op in operators {
284 if let Some(idx) = condition_str.find(op) {
285 let left = condition_str[..idx].trim();
286 let right = condition_str[idx + op.len()..].trim();
287
288 let mut map = HashMap::new();
290 map.insert("operator".to_string(), Value::String(op.to_string()));
291 map.insert(
292 "left".to_string(),
293 if let Ok(num) = left.parse::<f32>() {
294 Value::Number(num)
295 } else {
296 Value::Identifier(left.to_string())
297 },
298 );
299 map.insert(
300 "right".to_string(),
301 if let Ok(num) = right.parse::<f32>() {
302 Value::Number(num)
303 } else {
304 Value::Identifier(right.to_string())
305 },
306 );
307
308 return Ok(Value::Map(map));
309 }
310 }
311
312 Ok(Value::Identifier(condition_str.to_string()))
314}