use super::{decode_pair, Value}; use std::{collections::HashMap, convert::TryInto, str::FromStr}; grammar; pub Value: Value = { "null" => Value::Null, "true" => Value::Bool(true), "false" => Value::Bool(false), Num => Value::Number(<>), Str => Value::String(<>), "[" "]" => Value::Array(Vec::new()), "[" ",")*> "]" => { let mut v = v; v.push(e); Value::Array(v) }, "{" "}" => Value::Object(HashMap::new()), "{" ":" ",")*> ":" )> "}" => { let mut v = v; v.push(e); Value::Object(v.into_iter().collect()) }, }; pub Num: f64 = r"-?(0|[1-9][0-9]*)(\.[0-9]*)?([eE][-+]?[0-9]+)?" => f64::from_str(<>).unwrap(); pub Str: String = r#""([^\\"]|\\.)*""# => { let mut out = String::new(); let mut iter = <>.chars(); iter.next(); iter.next_back(); while let Some(c) = iter.next() { let c = match c { c @ '\x20'..='\x21' | c @ '\x23'..='\x5B' | c @ '\x5D'..='\u{10FFFF}' => c, '\\' => match iter.next().unwrap() { '\"' => '\x22', '\\' => '\x5C', '/' => '\x2F', 'b' => '\x08', 'f' => '\x0C', 'n' => '\x0A', 'r' => '\x0D', 't' => '\x09', 'u' => { let v = iter.by_ref().take(4).collect::(); assert_eq!(v.len(), 4); let v = u16::from_str_radix(&v, 16).unwrap(); let codepoint = if (0xD800..=0xDFFF).contains(&v) { let skipped = iter.by_ref().take(2).collect::(); assert_eq!(skipped, "\\u"); let o = iter.by_ref().take(4).collect::(); assert_eq!(o.len(), 4); let o = u16::from_str_radix(&o, 16).unwrap(); decode_pair(v, o) } else { u32::from(v) }; codepoint.try_into().unwrap() } c => panic!("bad escape sequence {}", c), } c => panic!("invalid character {}", c), }; out.push(c); } out };