summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
m---------dhall-lang0
-rw-r--r--dhall_generated_parser/src/dhall.pest.visibility1
-rw-r--r--dhall_syntax/src/parser.rs28
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()
}
}