diff options
| author | bors <bors@rust-lang.org> | 2017-09-12 01:25:23 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-09-12 01:25:23 +0000 |
| commit | 11f64d8f881a8bd994210efc1d3ff1982abf9df3 (patch) | |
| tree | 2750d4d4f6fc74996727fec47fe1e79c2d58fde8 /src/libsyntax/parse/lexer | |
| parent | 07d950f38f1719e2a54d9a515178b0e11dbaf108 (diff) | |
| parent | d4e0e5228111cd47294342a60b5f8af44c65e206 (diff) | |
| download | rust-11f64d8f881a8bd994210efc1d3ff1982abf9df3.tar.gz rust-11f64d8f881a8bd994210efc1d3ff1982abf9df3.zip | |
Auto merge of #43716 - MaloJaffre:_-in-literals, r=petrochenkov
Accept underscores in unicode escapes Fixes #43692. I don't know if this need an RFC, but at least the impl is here!
Diffstat (limited to 'src/libsyntax/parse/lexer')
| -rw-r--r-- | src/libsyntax/parse/lexer/mod.rs | 87 |
1 files changed, 47 insertions, 40 deletions
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index f26a0460905..ce3f16d2ba1 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -963,60 +963,67 @@ impl<'a> StringReader<'a> { true } - /// Scan over a \u{...} escape + /// Scan over a `\u{...}` escape /// - /// At this point, we have already seen the \ and the u, the { is the current character. We - /// will read at least one digit, and up to 6, and pass over the }. + /// At this point, we have already seen the `\` and the `u`, the `{` is the current character. + /// We will read a hex number (with `_` separators), with 1 to 6 actual digits, + /// and pass over the `}`. fn scan_unicode_escape(&mut self, delim: char) -> bool { self.bump(); // past the { let start_bpos = self.pos; - let mut count = 0; - let mut accum_int = 0; let mut valid = true; - while !self.ch_is('}') && count <= 6 { - let c = match self.ch { - Some(c) => c, - None => { - panic!(self.fatal_span_(start_bpos, - self.pos, - "unterminated unicode escape (found EOF)")); - } - }; - accum_int *= 16; - accum_int += c.to_digit(16).unwrap_or_else(|| { - if c == delim { - panic!(self.fatal_span_(self.pos, - self.next_pos, - "unterminated unicode escape (needed a `}`)")); - } else { - self.err_span_char(self.pos, - self.next_pos, - "invalid character in unicode escape", - c); - } - valid = false; - 0 - }); - self.bump(); - count += 1; + if let Some('_') = self.ch { + // disallow leading `_` + self.err_span_(self.pos, + self.next_pos, + "invalid start of unicode escape"); + valid = false; } + let count = self.scan_digits(16, 16); + if count > 6 { self.err_span_(start_bpos, self.pos, - "overlong unicode escape (can have at most 6 hex digits)"); + "overlong unicode escape (must have at most 6 hex digits)"); valid = false; } - - if valid && (char::from_u32(accum_int).is_none() || count == 0) { - self.err_span_(start_bpos, - self.pos, - "invalid unicode character escape"); - valid = false; + loop { + match self.ch { + Some('}') => { + if valid && count == 0 { + self.err_span_(start_bpos, + self.pos, + "empty unicode escape (must have at least 1 hex digit)"); + valid = false; + } + self.bump(); // past the ending `}` + break; + }, + Some(c) => { + if c == delim { + self.err_span_(self.pos, + self.pos, + "unterminated unicode escape (needed a `}`)"); + valid = false; + break; + } else if valid { + self.err_span_char(start_bpos, + self.pos, + "invalid character in unicode escape", + c); + valid = false; + } + }, + None => { + panic!(self.fatal_span_(start_bpos, + self.pos, + "unterminated unicode escape (found EOF)")); + } + } + self.bump(); } - - self.bump(); // past the ending } valid } |
