Add and lex LIFETIME tokens

cc #4846
This commit is contained in:
Niko Matsakis 2013-02-08 06:02:35 -08:00
parent bc1fb62c34
commit 14930fbffe
3 changed files with 90 additions and 22 deletions

View File

@ -29,6 +29,7 @@ macro_rules! interner_key (
(-3 as uint, 0u))) (-3 as uint, 0u)))
) )
#[deriving_eq]
pub struct ident { repr: uint } pub struct ident { repr: uint }
pub impl<S: Encoder> ident: Encodable<S> { pub impl<S: Encoder> ident: Encodable<S> {
@ -57,11 +58,6 @@ pub impl<D: Decoder> ident: Decodable<D> {
} }
} }
pub impl ident: cmp::Eq {
pure fn eq(&self, other: &ident) -> bool { (*self).repr == other.repr }
pure fn ne(&self, other: &ident) -> bool { !(*self).eq(other) }
}
pub impl ident: to_bytes::IterBytes { pub impl ident: to_bytes::IterBytes {
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
self.repr.iter_bytes(lsb0, f) self.repr.iter_bytes(lsb0, f)

View File

@ -501,18 +501,26 @@ fn scan_numeric_escape(rdr: @mut StringReader, n_hex_digits: uint) -> char {
return accum_int as char; return accum_int as char;
} }
fn ident_start(c: char) -> bool {
(c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| c == '_'
|| (c > 'z' && char::is_XID_start(c))
}
fn ident_continue(c: char) -> bool {
(c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9')
|| c == '_'
|| (c > 'z' && char::is_XID_continue(c))
}
fn next_token_inner(rdr: @mut StringReader) -> token::Token { fn next_token_inner(rdr: @mut StringReader) -> token::Token {
let mut accum_str = ~""; let mut accum_str = ~"";
let mut c = rdr.curr; let mut c = rdr.curr;
if (c >= 'a' && c <= 'z') if ident_start(c) {
|| (c >= 'A' && c <= 'Z') while ident_continue(c) {
|| c == '_'
|| (c > 'z' && char::is_XID_start(c)) {
while (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9')
|| c == '_'
|| (c > 'z' && char::is_XID_continue(c)) {
str::push_char(&mut accum_str, c); str::push_char(&mut accum_str, c);
bump(rdr); bump(rdr);
c = rdr.curr; c = rdr.curr;
@ -617,10 +625,26 @@ fn binop(rdr: @mut StringReader, op: token::binop) -> token::Token {
} }
} }
'\'' => { '\'' => {
// Either a character constant 'a' OR a lifetime name 'abc
bump(rdr); bump(rdr);
let mut c2 = rdr.curr; let mut c2 = rdr.curr;
bump(rdr); bump(rdr);
// If the character is an ident start not followed by another single
// quote, then this is a lifetime name:
if ident_start(c2) && rdr.curr != '\'' {
let mut lifetime_name = ~"";
lifetime_name.push_char(c2);
while ident_continue(rdr.curr) {
lifetime_name.push_char(rdr.curr);
bump(rdr);
}
return token::LIFETIME(rdr.interner.intern(@lifetime_name));
}
// Otherwise it is a character constant:
if c2 == '\\' { if c2 == '\\' {
// '\X' for some X must be a character constant:
let escaped = rdr.curr; let escaped = rdr.curr;
bump(rdr); bump(rdr);
match escaped { match escaped {
@ -730,17 +754,29 @@ pub mod test {
use util::interner; use util::interner;
use diagnostic; use diagnostic;
use util::testing::{check_equal, check_equal_ptr}; use util::testing::{check_equal, check_equal_ptr};
#[tetst] fn t1 () {
let teststr = struct Env {
@~"/* my source file */ interner: @token::ident_interner,
fn main() { io::println(~\"zebra\"); }\n"; string_reader: @mut StringReader
}
fn setup(teststr: ~str) -> Env {
let cm = CodeMap::new(); let cm = CodeMap::new();
let fm = cm.new_filemap(~"zebra.rs",teststr); let fm = cm.new_filemap(~"zebra.rs", @teststr);
let ident_interner = token::mk_ident_interner(); // interner::mk(); let ident_interner = token::mk_ident_interner(); // interner::mk();
let id = ident_interner.intern(@~"fn");
let span_handler = let span_handler =
diagnostic::mk_span_handler(diagnostic::mk_handler(None),@cm); diagnostic::mk_span_handler(diagnostic::mk_handler(None),@cm);
let string_reader = new_string_reader(span_handler,fm,ident_interner); Env {
interner: ident_interner,
string_reader: new_string_reader(span_handler,fm,ident_interner)
}
}
#[test] fn t1 () {
let Env {interner: ident_interner, string_reader} =
setup(~"/* my source file */ \
fn main() { io::println(~\"zebra\"); }\n");
let id = ident_interner.intern(@~"fn");
let tok1 = string_reader.next_token(); let tok1 = string_reader.next_token();
let tok2 = TokenAndSpan{ let tok2 = TokenAndSpan{
tok:token::IDENT(id, false), tok:token::IDENT(id, false),
@ -757,6 +793,35 @@ pub mod test {
// the lparen is already read: // the lparen is already read:
check_equal (string_reader.last_pos,BytePos(29)) check_equal (string_reader.last_pos,BytePos(29))
} }
#[test] fn character_a() {
let env = setup(~"'a'");
let TokenAndSpan {tok, sp: _} =
env.string_reader.next_token();
assert tok == token::LIT_INT('a' as i64, ast::ty_char);
}
#[test] fn character_space() {
let env = setup(~"' '");
let TokenAndSpan {tok, sp: _} =
env.string_reader.next_token();
assert tok == token::LIT_INT(' ' as i64, ast::ty_char);
}
#[test] fn character_escaped() {
let env = setup(~"'\n'");
let TokenAndSpan {tok, sp: _} =
env.string_reader.next_token();
assert tok == token::LIT_INT('\n' as i64, ast::ty_char);
}
#[test] fn lifetime_name() {
let env = setup(~"'abc");
let TokenAndSpan {tok, sp: _} =
env.string_reader.next_token();
let id = env.interner.intern(@~"abc");
assert tok == token::LIFETIME(id);
}
} }
// //

View File

@ -88,6 +88,7 @@ pub enum Token {
/* Name components */ /* Name components */
IDENT(ast::ident, bool), IDENT(ast::ident, bool),
UNDERSCORE, UNDERSCORE,
LIFETIME(ast::ident),
/* For interpolation */ /* For interpolation */
INTERPOLATED(nonterminal), INTERPOLATED(nonterminal),
@ -193,7 +194,7 @@ pub fn to_str(in: @ident_interner, t: Token) -> ~str {
/* Name components */ /* Name components */
IDENT(s, _) => *in.get(s), IDENT(s, _) => *in.get(s),
LIFETIME(s) => fmt!("'%s", *in.get(s)),
UNDERSCORE => ~"_", UNDERSCORE => ~"_",
/* Other */ /* Other */
@ -760,6 +761,12 @@ impl Token : cmp::Eq {
_ => false _ => false
} }
} }
LIFETIME(e0a) => {
match (*other) {
LIFETIME(e0b) => e0a == e0b,
_ => false
}
}
UNDERSCORE => { UNDERSCORE => {
match (*other) { match (*other) {
UNDERSCORE => true, UNDERSCORE => true,