Add a b'x' byte literal of type u8.

This commit is contained in:
Simon Sapin
2014-06-06 16:04:04 +01:00
parent 2fd618e77a
commit bccdba0296
16 changed files with 169 additions and 5 deletions

View File

@@ -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;

View File

@@ -33,7 +33,7 @@ use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod};
use ast::{Ident, NormalFn, Inherited, Item, Item_, ItemStatic};
use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl};
use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, Lit, Lit_};
use ast::{LitBool, LitFloat, LitFloatUnsuffixed, LitInt, LitChar};
use ast::{LitBool, LitFloat, LitFloatUnsuffixed, LitInt, LitChar, LitByte};
use ast::{LitIntUnsuffixed, LitNil, LitStr, LitUint, Local, LocalLet};
use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, Matcher, MatchNonterminal};
use ast::{MatchSeq, MatchTok, Method, MutTy, BiMul, Mutability};
@@ -1512,6 +1512,7 @@ impl<'a> Parser<'a> {
// matches token_lit = LIT_INT | ...
pub fn lit_from_token(&mut self, tok: &token::Token) -> Lit_ {
match *tok {
token::LIT_BYTE(i) => LitByte(i),
token::LIT_CHAR(i) => LitChar(i),
token::LIT_INT(i, it) => LitInt(i, it),
token::LIT_UINT(u, ut) => LitUint(u, ut),

View File

@@ -78,6 +78,7 @@ pub enum Token {
DOLLAR,
/* Literals */
LIT_BYTE(u8),
LIT_CHAR(char),
LIT_INT(i64, ast::IntTy),
LIT_UINT(u64, ast::UintTy),
@@ -193,6 +194,14 @@ pub fn to_str(t: &Token) -> String {
DOLLAR => "$".to_string(),
/* Literals */
LIT_BYTE(b) => {
let mut res = String::from_str("b'");
(b as char).escape_default(|c| {
res.push_char(c);
});
res.push_char('\'');
res
}
LIT_CHAR(c) => {
let mut res = String::from_str("'");
c.escape_default(|c| {
@@ -273,6 +282,7 @@ pub fn can_begin_expr(t: &Token) -> bool {
IDENT(_, _) => true,
UNDERSCORE => true,
TILDE => true,
LIT_BYTE(_) => true,
LIT_CHAR(_) => true,
LIT_INT(_, _) => true,
LIT_UINT(_, _) => true,
@@ -311,6 +321,7 @@ pub fn close_delimiter_for(t: &Token) -> Option<Token> {
pub fn is_lit(t: &Token) -> bool {
match *t {
LIT_BYTE(_) => true,
LIT_CHAR(_) => true,
LIT_INT(_, _) => true,
LIT_UINT(_, _) => true,