1use crate::ast::{Number, Value};
2use pest::iterators::Pair;
3use pest::Parser;
4use pest_derive::Parser;
5use std::collections::HashMap;
6use thiserror::Error;
7
8#[derive(Parser)]
9#[grammar = "uson.pest"]
10pub struct UsonParser;
11
12#[derive(Error, Debug)]
13pub enum ParseError {
14 #[error("Parse error: {0}")]
15 PestError(#[from] pest::error::Error<Rule>),
16
17 #[error("Invalid number format: {0}")]
18 NumberError(String),
19
20 #[error("Invalid escape sequence: {0}")]
21 EscapeError(String),
22}
23
24pub type ParseResult<T> = Result<T, ParseError>;
25
26pub fn parse(input: &str) -> ParseResult<Vec<Value>> {
27 let mut pairs = UsonParser::parse(Rule::uson_text, input)?;
28 let uson_text = pairs.next().unwrap();
29
30 let mut values = Vec::new();
31 for pair in uson_text.into_inner() {
32 if pair.as_rule() == Rule::EOI {
33 break;
34 }
35 if pair.as_rule() == Rule::expr {
36 let value_pair = pair.into_inner().next().unwrap();
37 values.push(parse_value(value_pair)?);
38 }
39 }
40
41 Ok(values)
42}
43
44fn parse_value(pair: Pair<Rule>) -> ParseResult<Value> {
45 match pair.as_rule() {
46 Rule::null_val => Ok(Value::Null),
47 Rule::true_val => Ok(Value::Bool(true)),
48 Rule::false_val => Ok(Value::Bool(false)),
49 Rule::number => parse_number(pair),
50 Rule::string => parse_string(pair),
51 Rule::array => parse_array(pair),
52 Rule::object => parse_object(pair),
53 Rule::assign => parse_assign(pair),
54 Rule::typed => parse_typed(pair),
55 Rule::value => {
56 let inner = pair.into_inner().next().unwrap();
57 parse_value(inner)
58 }
59 _ => unreachable!("Unexpected rule: {:?}", pair.as_rule()),
60 }
61}
62
63fn parse_number(pair: Pair<Rule>) -> ParseResult<Value> {
64 let num_str = pair.as_str();
65
66 if num_str.contains('.') || num_str.contains('e') || num_str.contains('E') {
67 let f = num_str.parse::<f64>()
68 .map_err(|e| ParseError::NumberError(e.to_string()))?;
69 Ok(Value::Number(Number::Float(f)))
70 } else {
71 let i = num_str.parse::<i64>()
72 .map_err(|e| ParseError::NumberError(e.to_string()))?;
73 Ok(Value::Number(Number::Integer(i)))
74 }
75}
76
77fn parse_string(pair: Pair<Rule>) -> ParseResult<Value> {
78 let inner = pair.into_inner().next().unwrap();
79 let s = match inner.as_rule() {
80 Rule::double_quoted_string => {
81 let s = inner.as_str();
82 unescape_string(&s[1..s.len()-1])?
83 }
84 Rule::single_quoted_string => {
85 let s = inner.as_str();
86 unescape_string(&s[1..s.len()-1])?
87 }
88 Rule::unquoted_string => {
89 let s = inner.as_str();
90 // Check if it's a number
91 if s.chars().all(|c| c.is_ascii_digit() || c == '.') {
92 if s.contains('.') {
93 if let Ok(f) = s.parse::<f64>() {
94 return Ok(Value::Number(Number::Float(f)));
95 }
96 } else if let Ok(i) = s.parse::<i64>() {
97 return Ok(Value::Number(Number::Integer(i)));
98 }
99 }
100 s.to_string()
101 }
102 _ => unreachable!(),
103 };
104
105 Ok(Value::String(s))
106}
107
108fn unescape_string(s: &str) -> ParseResult<String> {
109 let mut result = String::new();
110 let mut chars = s.chars();
111
112 while let Some(ch) = chars.next() {
113 if ch == '\\' {
114 match chars.next() {
115 Some('n') => result.push('\n'),
116 Some('r') => result.push('\r'),
117 Some('t') => result.push('\t'),
118 Some('b') => result.push('\u{0008}'),
119 Some('f') => result.push('\u{000C}'),
120 Some('\\') => result.push('\\'),
121 Some('/') => result.push('/'),
122 Some('#') => result.push('#'),
123 Some('"') => result.push('"'),
124 Some('\'') => result.push('\''),
125 Some('u') => {
126 let hex: String = chars.by_ref().take(4).collect();
127 let code = u32::from_str_radix(&hex, 16)
128 .map_err(|_| ParseError::EscapeError(format!("Invalid unicode escape: \\u{}", hex)))?;
129 let ch = char::from_u32(code)
130 .ok_or_else(|| ParseError::EscapeError(format!("Invalid unicode codepoint: {}", code)))?;
131 result.push(ch);
132 }
133 Some(c) => result.push(c),
134 None => return Err(ParseError::EscapeError("Incomplete escape sequence".to_string())),
135 }
136 } else {
137 result.push(ch);
138 }
139 }
140
141 Ok(result)
142}
143
144fn parse_array(pair: Pair<Rule>) -> ParseResult<Value> {
145 let mut values = Vec::new();
146
147 for inner in pair.into_inner() {
148 if inner.as_rule() == Rule::value {
149 values.push(parse_value(inner)?);
150 }
151 }
152
153 Ok(Value::Array(values))
154}
155
156fn parse_object(pair: Pair<Rule>) -> ParseResult<Value> {
157 let mut map = HashMap::new();
158
159 for inner in pair.into_inner() {
160 if inner.as_rule() == Rule::member {
161 let mut member_parts = inner.into_inner();
162 let key_pair = member_parts.next().unwrap();
163 let key = if let Value::String(s) = parse_string(key_pair)? {
164 s
165 } else {
166 unreachable!()
167 };
168 let value_pair = member_parts.next().unwrap();
169 let value = parse_value(value_pair)?;
170 map.insert(key, value);
171 }
172 }
173
174 Ok(Value::Object(map))
175}
176
177fn parse_assign(pair: Pair<Rule>) -> ParseResult<Value> {
178 let mut inner = pair.into_inner();
179 let key_pair = inner.next().unwrap();
180 let key = if let Value::String(s) = parse_string(key_pair)? {
181 s
182 } else {
183 unreachable!()
184 };
185 let value_pair = inner.next().unwrap();
186 let value = parse_value(value_pair)?;
187
188 let mut map = HashMap::new();
189 map.insert(key, value);
190 Ok(Value::Object(map))
191}
192
193fn parse_typed(pair: Pair<Rule>) -> ParseResult<Value> {
194 let mut inner = pair.into_inner();
195 let type_name = inner.next().unwrap().as_str().to_string();
196 let value_pair = inner.next().unwrap();
197 let value = parse_value(value_pair)?;
198
199 Ok(Value::Typed {
200 type_name,
201 value: Box::new(value),
202 })
203}
204
205pub fn apply_builtin_types(value: Value) -> Value {
206 match value {
207 Value::Typed { type_name, value } => {
208 let inner = apply_builtin_types(*value);
209 match type_name.as_str() {
210 "str" => match &inner {
211 Value::String(s) => Value::String(s.clone()),
212 Value::Number(Number::Integer(i)) => Value::String(i.to_string()),
213 Value::Number(Number::Float(f)) => Value::String(f.to_string()),
214 Value::Bool(b) => Value::String(b.to_string()),
215 Value::Null => Value::String("null".to_string()),
216 Value::Array(arr) => {
217 let strs: Vec<String> = arr.iter().map(|v| match v {
218 Value::String(s) => s.clone(),
219 Value::Number(Number::Integer(i)) => i.to_string(),
220 Value::Number(Number::Float(f)) => f.to_string(),
221 _ => "".to_string(),
222 }).collect();
223 Value::String(strs.join(","))
224 }
225 _ => inner,
226 },
227 "int" => match &inner {
228 Value::String(s) => s.parse::<i64>()
229 .map(|i| Value::Number(Number::Integer(i)))
230 .unwrap_or(inner),
231 Value::Number(_) => inner,
232 _ => inner,
233 },
234 "float" => match &inner {
235 Value::String(s) => s.parse::<f64>()
236 .map(|f| Value::Number(Number::Float(f)))
237 .unwrap_or(inner),
238 Value::Number(Number::Integer(i)) => Value::Number(Number::Float(*i as f64)),
239 Value::Number(_) => inner,
240 _ => inner,
241 },
242 "bool" => match &inner {
243 Value::String(s) => match s.as_str() {
244 "true" => Value::Bool(true),
245 "false" => Value::Bool(false),
246 _ => inner,
247 },
248 Value::Bool(_) => inner,
249 _ => inner,
250 },
251 "null" => Value::Null,
252 "arr" => match &inner {
253 Value::String(s) => {
254 let parts: Vec<Value> = s.split(',')
255 .filter_map(|p| p.trim().parse::<i64>().ok())
256 .map(|i| Value::Number(Number::Integer(i)))
257 .collect();
258 Value::Array(parts)
259 }
260 Value::Array(_) => inner,
261 _ => inner,
262 },
263 "obj" => match &inner {
264 Value::String(s) => {
265 // Try to parse as JSON
266 if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(s) {
267 json_to_value(parsed)
268 } else {
269 inner
270 }
271 }
272 _ => inner,
273 },
274 _ => inner, // Unknown type, return value as-is
275 }
276 }
277 Value::Array(arr) => Value::Array(arr.into_iter().map(apply_builtin_types).collect()),
278 Value::Object(obj) => Value::Object(
279 obj.into_iter()
280 .map(|(k, v)| (k, apply_builtin_types(v)))
281 .collect()
282 ),
283 other => other,
284 }
285}
286
287fn json_to_value(json: serde_json::Value) -> Value {
288 match json {
289 serde_json::Value::Null => Value::Null,
290 serde_json::Value::Bool(b) => Value::Bool(b),
291 serde_json::Value::Number(n) => {
292 if let Some(i) = n.as_i64() {
293 Value::Number(Number::Integer(i))
294 } else if let Some(f) = n.as_f64() {
295 Value::Number(Number::Float(f))
296 } else {
297 Value::Null
298 }
299 }
300 serde_json::Value::String(s) => Value::String(s),
301 serde_json::Value::Array(arr) => {
302 Value::Array(arr.into_iter().map(json_to_value).collect())
303 }
304 serde_json::Value::Object(obj) => {
305 Value::Object(obj.into_iter().map(|(k, v)| (k, json_to_value(v))).collect())
306 }
307 }
308}
309