μson (uson) is a shorthand for JSON
at main 11 kB view raw
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