diff options
m--------- | dhall-lang | 0 | ||||
-rw-r--r-- | dhall_generated_parser/src/dhall.pest.visibility | 1 | ||||
-rw-r--r-- | dhall_syntax/src/parser.rs | 28 |
3 files changed, 25 insertions, 4 deletions
diff --git a/dhall-lang b/dhall-lang -Subproject 0396b67639a6deaff480844e71b576db998717d +Subproject dbf4ebcfabf499e87c27e75bec108d91929ccc3 diff --git a/dhall_generated_parser/src/dhall.pest.visibility b/dhall_generated_parser/src/dhall.pest.visibility index 0c48656..2b7c477 100644 --- a/dhall_generated_parser/src/dhall.pest.visibility +++ b/dhall_generated_parser/src/dhall.pest.visibility @@ -21,6 +21,7 @@ label # any_label double_quote_chunk double_quote_escaped +# unicode_escape double_quote_char double_quote_literal single_quote_continue diff --git a/dhall_syntax/src/parser.rs b/dhall_syntax/src/parser.rs index db1699b..2450c76 100644 --- a/dhall_syntax/src/parser.rs +++ b/dhall_syntax/src/parser.rs @@ -402,11 +402,31 @@ make_parser! { "n" => "\n".to_owned(), "r" => "\r".to_owned(), "t" => "\t".to_owned(), + // "uXXXX" or "u{XXXXX}" _ => { - // "uXXXX" - use std::convert::TryFrom; - let c = u16::from_str_radix(&s[1..5], 16).unwrap(); - let c = char::try_from(u32::from(c)).unwrap(); + use std::convert::{TryFrom, TryInto}; + + let s = &s[1..]; + let s = if &s[0..1] == "{" { + &s[1..s.len()-1] + } else { + &s[0..s.len()] + }; + + if s.len() > 8 { + Err(format!("Escape sequences can't have more than 8 chars: \"{}\"", s))? + } + + // pad with zeroes + let s: String = std::iter::repeat('0') + .take(8 - s.len()) + .chain(s.chars()) + .collect(); + + // `s` has length 8, so `bytes` has length 4 + let bytes: &[u8] = &hex::decode(s).unwrap(); + let c = u32::from_be_bytes(bytes.try_into().unwrap()); + let c = char::try_from(c).unwrap(); std::iter::once(c).collect() } } |