Skip to content

Commit

Permalink
Add and lex LIFETIME tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Feb 8, 2013
1 parent bc1fb62 commit 14930fb
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 22 deletions.
6 changes: 1 addition & 5 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ macro_rules! interner_key (
(-3 as uint, 0u)))
)

#[deriving_eq]
pub struct ident { repr: uint }

pub impl<S: Encoder> ident: Encodable<S> {
Expand Down Expand Up @@ -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 {
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
self.repr.iter_bytes(lsb0, f)
Expand Down
97 changes: 81 additions & 16 deletions src/libsyntax/parse/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,18 +501,26 @@ fn scan_numeric_escape(rdr: @mut StringReader, n_hex_digits: uint) -> 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 {
let mut accum_str = ~"";
let mut c = rdr.curr;
if (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| 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)) {
if ident_start(c) {
while ident_continue(c) {
str::push_char(&mut accum_str, c);
bump(rdr);
c = rdr.curr;
Expand Down Expand Up @@ -617,10 +625,26 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
}
}
'\'' => {
// Either a character constant 'a' OR a lifetime name 'abc
bump(rdr);
let mut c2 = rdr.curr;
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 == '\\' {
// '\X' for some X must be a character constant:
let escaped = rdr.curr;
bump(rdr);
match escaped {
Expand Down Expand Up @@ -730,17 +754,29 @@ pub mod test {
use util::interner;
use diagnostic;
use util::testing::{check_equal, check_equal_ptr};
#[tetst] fn t1 () {
let teststr =
@~"/* my source file */
fn main() { io::println(~\"zebra\"); }\n";

struct Env {
interner: @token::ident_interner,
string_reader: @mut StringReader
}

fn setup(teststr: ~str) -> Env {
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 id = ident_interner.intern(@~"fn");
let span_handler =
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 tok2 = TokenAndSpan{
tok:token::IDENT(id, false),
Expand All @@ -757,6 +793,35 @@ fn main() { io::println(~\"zebra\"); }\n";
// the lparen is already read:
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);
}
}

//
Expand Down
9 changes: 8 additions & 1 deletion src/libsyntax/parse/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ pub enum Token {
/* Name components */
IDENT(ast::ident, bool),
UNDERSCORE,
LIFETIME(ast::ident),

/* For interpolation */
INTERPOLATED(nonterminal),
Expand Down Expand Up @@ -193,7 +194,7 @@ pub fn to_str(in: @ident_interner, t: Token) -> ~str {

/* Name components */
IDENT(s, _) => *in.get(s),

LIFETIME(s) => fmt!("'%s", *in.get(s)),
UNDERSCORE => ~"_",

/* Other */
Expand Down Expand Up @@ -760,6 +761,12 @@ impl Token : cmp::Eq {
_ => false
}
}
LIFETIME(e0a) => {
match (*other) {
LIFETIME(e0b) => e0a == e0b,
_ => false
}
}
UNDERSCORE => {
match (*other) {
UNDERSCORE => true,
Expand Down

1 comment on commit 14930fb

@graydon
Copy link

@graydon graydon commented on 14930fb Feb 8, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r+

Please sign in to comment.