devalang_wasm/language/syntax/parser/driver/
effects.rs1use crate::language::syntax::ast::Value;
2use anyhow::{Result, anyhow};
3use std::collections::HashMap;
4
5pub fn parse_chained_effects(effects_str: &str) -> Result<Value> {
7 let effects = effects_str
8 .split("->")
9 .map(str::trim)
10 .filter(|s| !s.is_empty())
11 .try_fold(HashMap::new(), |mut map, effect| {
12 parse_single_effect(effect).map(|(name, params)| {
13 map.insert(name, params);
14 map
15 })
16 })?;
17
18 Ok(Value::Map(effects))
19}
20
21fn parse_single_effect(effect_str: &str) -> Result<(String, Value)> {
23 let effect_str = effect_str.trim();
24 if effect_str.is_empty() {
25 return Err(anyhow!("Empty effect definition"));
26 }
27
28 if let Some((name, params_str)) = effect_str.split_once('(') {
30 let name = name.trim().to_string();
31 let params_str = params_str.trim_end_matches(')');
32
33 if params_str == "true" {
35 return Ok((name, Value::Boolean(true)));
36 } else if params_str == "false" {
37 return Ok((name, Value::Boolean(false)));
38 }
39
40 if let Ok(num) = params_str.parse::<f32>() {
42 return Ok((name, Value::Number(num)));
43 }
44
45 if params_str.contains('{') && params_str.contains('}') {
47 let map_str = params_str.trim_matches(|c| c == '{' || c == '}');
48 let mut params_map = HashMap::new();
49
50 for pair in map_str.split(',') {
51 if let Some((key, value)) = pair.split_once(':') {
52 let key = key.trim().to_string();
53 let value = value.trim();
54
55 let value = if value == "true" {
56 Value::Boolean(true)
57 } else if value == "false" {
58 Value::Boolean(false)
59 } else if let Ok(num) = value.parse::<f32>() {
60 Value::Number(num)
61 } else {
62 Value::String(value.trim_matches('"').to_string())
63 };
64
65 params_map.insert(key, value);
66 }
67 }
68
69 Ok((name, Value::Map(params_map)))
70 } else {
71 Ok((
73 name,
74 Value::String(params_str.trim_matches('"').to_string()),
75 ))
76 }
77 } else {
78 Ok((effect_str.to_string(), Value::Null))
80 }
81}
82
83#[cfg(test)]
84#[path = "test_effects.rs"]
85mod tests;