Skip to content

Commit 9a01471

Browse files
committed
syntax: copy unstable char::escape_{default,unicode} code into libsyntax
This avoids using unsafe behavior.
1 parent 19c8d70 commit 9a01471

File tree

2 files changed

+113
-3
lines changed

2 files changed

+113
-3
lines changed

src/libsyntax/parse/lexer/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use diagnostic::SpanHandler;
1515
use ext::tt::transcribe::tt_next_token;
1616
use parse::token::str_to_ident;
1717
use parse::token;
18-
use str::char_at;
18+
use str::{char_at, escape_default};
1919

2020
use std::borrow::Cow;
2121
use std::char;
@@ -205,7 +205,7 @@ impl<'a> StringReader<'a> {
205205
fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> ! {
206206
let mut m = m.to_string();
207207
m.push_str(": ");
208-
for c in c.escape_default() { m.push(c) }
208+
for c in escape_default(c) { m.push(c) }
209209
self.fatal_span_(from_pos, to_pos, &m[..]);
210210
}
211211

@@ -214,7 +214,7 @@ impl<'a> StringReader<'a> {
214214
fn err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) {
215215
let mut m = m.to_string();
216216
m.push_str(": ");
217-
for c in c.escape_default() { m.push(c) }
217+
for c in escape_default(c) { m.push(c) }
218218
self.err_span_(from_pos, to_pos, &m[..]);
219219
}
220220

src/libsyntax/str.rs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,116 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use std::mem::transmute;
12+
1113
pub fn char_at(s: &str, byte: usize) -> char {
1214
s[byte..].chars().next().unwrap()
1315
}
16+
17+
// FIXME: This was copied from core/char.rs because it is currenty unstable.
18+
pub fn escape_unicode(ch: char) -> EscapeUnicode {
19+
EscapeUnicode { c: ch, state: EscapeUnicodeState::Backslash }
20+
}
21+
22+
// FIXME: This was copied from core/char.rs because it is currenty unstable.
23+
pub fn escape_default(ch: char) -> EscapeDefault {
24+
let init_state = match ch {
25+
'\t' => EscapeDefaultState::Backslash('t'),
26+
'\r' => EscapeDefaultState::Backslash('r'),
27+
'\n' => EscapeDefaultState::Backslash('n'),
28+
'\\' => EscapeDefaultState::Backslash('\\'),
29+
'\'' => EscapeDefaultState::Backslash('\''),
30+
'"' => EscapeDefaultState::Backslash('"'),
31+
'\x20' ... '\x7e' => EscapeDefaultState::Char(ch),
32+
_ => EscapeDefaultState::Unicode(escape_unicode(ch))
33+
};
34+
EscapeDefault { state: init_state }
35+
}
36+
37+
// FIXME: This was copied from core/char.rs because it is currenty unstable.
38+
pub struct EscapeUnicode {
39+
c: char,
40+
state: EscapeUnicodeState
41+
}
42+
43+
enum EscapeUnicodeState {
44+
Backslash,
45+
Type,
46+
LeftBrace,
47+
Value(usize),
48+
RightBrace,
49+
Done,
50+
}
51+
52+
impl Iterator for EscapeUnicode {
53+
type Item = char;
54+
55+
fn next(&mut self) -> Option<char> {
56+
match self.state {
57+
EscapeUnicodeState::Backslash => {
58+
self.state = EscapeUnicodeState::Type;
59+
Some('\\')
60+
}
61+
EscapeUnicodeState::Type => {
62+
self.state = EscapeUnicodeState::LeftBrace;
63+
Some('u')
64+
}
65+
EscapeUnicodeState::LeftBrace => {
66+
let mut n = 0;
67+
while (self.c as u32) >> (4 * (n + 1)) != 0 {
68+
n += 1;
69+
}
70+
self.state = EscapeUnicodeState::Value(n);
71+
Some('{')
72+
}
73+
EscapeUnicodeState::Value(offset) => {
74+
let v = match ((self.c as i32) >> (offset * 4)) & 0xf {
75+
i @ 0 ... 9 => '0' as i32 + i,
76+
i => 'a' as i32 + (i - 10)
77+
};
78+
if offset == 0 {
79+
self.state = EscapeUnicodeState::RightBrace;
80+
} else {
81+
self.state = EscapeUnicodeState::Value(offset - 1);
82+
}
83+
Some(unsafe { transmute(v) })
84+
}
85+
EscapeUnicodeState::RightBrace => {
86+
self.state = EscapeUnicodeState::Done;
87+
Some('}')
88+
}
89+
EscapeUnicodeState::Done => None,
90+
}
91+
}
92+
}
93+
94+
// FIXME: This was copied from core/char.rs because it is currenty unstable.
95+
pub struct EscapeDefault {
96+
state: EscapeDefaultState
97+
}
98+
99+
enum EscapeDefaultState {
100+
Backslash(char),
101+
Char(char),
102+
Done,
103+
Unicode(EscapeUnicode),
104+
}
105+
106+
impl Iterator for EscapeDefault {
107+
type Item = char;
108+
109+
fn next(&mut self) -> Option<char> {
110+
match self.state {
111+
EscapeDefaultState::Backslash(c) => {
112+
self.state = EscapeDefaultState::Char(c);
113+
Some('\\')
114+
}
115+
EscapeDefaultState::Char(c) => {
116+
self.state = EscapeDefaultState::Done;
117+
Some(c)
118+
}
119+
EscapeDefaultState::Done => None,
120+
EscapeDefaultState::Unicode(ref mut iter) => iter.next()
121+
}
122+
}
123+
}

0 commit comments

Comments
 (0)