matugen_parser/engine/
resolve.rs1use chumsky::span::SimpleSpan;
2
3use super::Engine;
4
5use crate::{
6 color::parse::parse_css_color,
7 {
8 Error, ParseErrorKind, Value,
9 engine::{FORMATS, format_color},
10 },
11};
12
13impl Engine {
14 pub fn resolve_generic_color<'a>(
15 &self,
16 color: &Value,
17 format: &'a str,
18 format_value: bool,
19 span: SimpleSpan,
20 name: &str,
21 ) -> Result<Value, Error> {
22 let color = match parse_css_color(&color.to_string()) {
23 Ok(v) => v,
24 Err(_) => {
25 return Err(Error::ResolveError {
26 span,
27 name: name.to_string(),
28 });
29 }
30 };
31 if format_value {
32 let res = match format_color(color, format) {
33 Some(v) => v,
34 None => {
35 return Err(Error::ParseError {
36 kind: ParseErrorKind::Keyword(crate::KeywordError::InvalidFormat {
37 formats: FORMATS,
38 }),
39 span,
40 name: name.to_string(),
41 });
42 }
43 };
44
45 Ok(Value::Ident(res.to_string()))
46 } else {
47 Ok(Value::Color(color))
48 }
49 }
50
51 pub fn resolve_path<'a, I>(
52 &self,
53 path: I,
54 format_value: bool,
55 span: SimpleSpan,
56 name: &str,
57 ) -> Result<Value, Error>
58 where
59 I: IntoIterator<Item = &'a str> + Clone,
60 {
61 let mut iter = path.clone().into_iter().peekable();
62 let first = iter.next().ok_or(Error::ResolveError {
63 span,
64 name: name.to_string(),
65 })?;
66
67 let mut current = self
68 .runtime
69 .borrow()
70 .resolve_path(std::iter::once(first))
71 .or_else(|| self.context.data().get(first).cloned())
72 .ok_or(Error::ResolveError {
73 span,
74 name: name.to_string(),
75 })?;
76
77 while let Some(next_key) = iter.next() {
78 let next_key = if next_key.starts_with("_") {
79 next_key.strip_prefix("_").unwrap()
80 } else {
81 next_key
82 };
83
84 match current {
85 Value::Map(ref map) => {
86 if map.contains_key("color") {
87 let color = map.get("color").unwrap();
88 current =
89 self.resolve_generic_color(color, next_key, format_value, span, name)?;
90 } else {
91 current = map
92 .get(next_key)
93 .ok_or(Error::ResolveError {
94 span,
95 name: name.to_string(),
96 })?
97 .clone();
98 }
99 }
100 Value::LazyColor { color, .. } => {
101 current = if format_value {
102 Value::Ident(
103 format_color(color, next_key)
104 .ok_or(Error::ResolveError {
105 span,
106 name: name.to_string(),
107 })?
108 .to_string(),
109 )
110 } else {
111 Value::Color(color)
112 }
113 }
114 Value::Color(color) => {
115 current = if format_value {
116 Value::Ident(
117 format_color(color, next_key)
118 .ok_or(Error::ResolveError {
119 span,
120 name: name.to_string(),
121 })?
122 .to_string(),
123 )
124 } else {
125 Value::Color(color)
126 }
127 }
128 _ => {
129 return Err(Error::ResolveError {
130 span,
131 name: name.to_string(),
132 });
133 }
134 }
135 }
136
137 Ok(current)
138 }
139
140 pub fn get_format<'a>(&self, keywords: &[&'a str]) -> &'a str {
141 keywords
142 .last()
143 .expect("Could not get format from {keywords}")
144 }
145}