diff options
| author | Simon Sapin <simon.sapin@exyr.org> | 2014-06-06 16:04:04 +0100 |
|---|---|---|
| committer | Simon Sapin <simon.sapin@exyr.org> | 2014-06-17 23:41:03 +0200 |
| commit | bccdba02960b3cd428addbc2c856065ebb81eb04 (patch) | |
| tree | 09c67823ea70b74b18af5ba2470b337968d758aa /src/libsyntax/parse/lexer | |
| parent | 2fd618e77accd37426819952ad443e50bb3c9015 (diff) | |
| download | rust-bccdba02960b3cd428addbc2c856065ebb81eb04.tar.gz rust-bccdba02960b3cd428addbc2c856065ebb81eb04.zip | |
Add a b'x' byte literal of type u8.
Diffstat (limited to 'src/libsyntax/parse/lexer')
| -rw-r--r-- | src/libsyntax/parse/lexer/mod.rs | 68 |
1 files changed, 65 insertions, 3 deletions
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index f7eac0b323f..7e4cb195cea 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -650,10 +650,13 @@ impl<'a> StringReader<'a> { /// token, and updates the interner fn next_token_inner(&mut self) -> token::Token { let c = self.curr; - if ident_start(c) && !self.nextch_is('"') && !self.nextch_is('#') { + if ident_start(c) && match (c.unwrap(), self.nextch()) { // Note: r as in r" or r#" is part of a raw string literal, - // not an identifier, and is handled further down. - + // b as in b' is part of a byte literal. + // They are not identifiers, and are handled further down. + ('r', Some('"')) | ('r', Some('#')) | ('b', Some('\'')) => false, + _ => true + } { let start = self.last_pos; while ident_continue(self.curr) { self.bump(); @@ -854,6 +857,65 @@ impl<'a> StringReader<'a> { self.bump(); // advance curr past token return token::LIT_CHAR(c2); } + 'b' => { + self.bump(); + assert!(self.curr_is('\''), "Should have been a token::IDENT"); + self.bump(); + let start = self.last_pos; + + // the eof will be picked up by the final `'` check below + let mut c2 = self.curr.unwrap_or('\x00'); + self.bump(); + + match c2 { + '\\' => { + // '\X' for some X must be a character constant: + let escaped = self.curr; + let escaped_pos = self.last_pos; + self.bump(); + match escaped { + None => {} + Some(e) => { + c2 = match e { + 'n' => '\n', + 'r' => '\r', + 't' => '\t', + '\\' => '\\', + '\'' => '\'', + '"' => '"', + '0' => '\x00', + 'x' => self.scan_numeric_escape(2u, '\''), + c2 => { + self.err_span_char(escaped_pos, self.last_pos, + "unknown byte escape", c2); + c2 + } + } + } + } + } + '\t' | '\n' | '\r' | '\'' => { + self.err_span_char( start, self.last_pos, + "byte constant must be escaped", c2); + } + _ if c2 > '\x7F' => { + self.err_span_char( start, self.last_pos, + "byte constant must be ASCII. \ + Use a \\xHH escape for a non-ASCII byte", c2); + } + _ => {} + } + if !self.curr_is('\'') { + self.fatal_span_verbose( + // Byte offsetting here is okay because the + // character before position `start` are an + // ascii single quote and ascii 'b'. + start - BytePos(2), self.last_pos, + "unterminated byte constant".to_string()); + } + self.bump(); // advance curr past token + return token::LIT_BYTE(c2 as u8); + } '"' => { let mut accum_str = String::new(); let start_bpos = self.last_pos; |
