1
Fork 0

Use an enum for keywords and intern them to improve parser performance

Currently, keywords are stored in hashsets that are recreated for every
Parser instance, which is quite expensive since macro expansion creates
lots of them. Additionally, the parser functions that look for a keyword
currently accept a string and have a runtime check to validate that they
actually received a keyword.

By creating an enum for the keywords and inserting them into the
ident interner, we can avoid the creation of the hashsets and get static
checks for the keywords.

For libstd, this cuts the parse+expansion part from ~2.6s to ~1.6s.
This commit is contained in:
Björn Steinbrink 2013-05-25 17:45:45 +02:00
parent b238a08725
commit 6c62d77830
5 changed files with 281 additions and 246 deletions

View file

@ -16,6 +16,7 @@ use ext::base::ExtCtxt;
use ext::base; use ext::base;
use parse::lexer::{new_tt_reader, reader}; use parse::lexer::{new_tt_reader, reader};
use parse::parser::Parser; use parse::parser::Parser;
use parse::token::keywords;
pub fn expand_trace_macros(cx: @ExtCtxt, pub fn expand_trace_macros(cx: @ExtCtxt,
sp: span, sp: span,
@ -36,9 +37,9 @@ pub fn expand_trace_macros(cx: @ExtCtxt,
rdr.dup() rdr.dup()
); );
if rust_parser.is_keyword("true") { if rust_parser.is_keyword(keywords::True) {
cx.set_trace_macros(true); cx.set_trace_macros(true);
} else if rust_parser.is_keyword("false") { } else if rust_parser.is_keyword(keywords::False) {
cx.set_trace_macros(false); cx.set_trace_macros(false);
} else { } else {
cx.span_fatal(sp, "trace_macros! only accepts `true` or `false`") cx.span_fatal(sp, "trace_macros! only accepts `true` or `false`")

View file

@ -14,6 +14,7 @@ use ast;
use codemap::{BytePos, spanned}; use codemap::{BytePos, spanned};
use parse::lexer::reader; use parse::lexer::reader;
use parse::parser::Parser; use parse::parser::Parser;
use parse::token::keywords;
use parse::token; use parse::token;
use opt_vec; use opt_vec;
@ -133,54 +134,15 @@ pub impl Parser {
return if *self.token == *tok { self.bump(); true } else { false }; return if *self.token == *tok { self.bump(); true } else { false };
} }
// Storing keywords as interned idents instead of strings would be nifty. fn is_keyword(&self, kw: keywords::Keyword) -> bool {
token::is_keyword(kw, self.token)
// A sanity check that the word we are asking for is a known keyword
// NOTE: this could be done statically....
fn require_keyword(&self, word: &str) {
if !self.keywords.contains_equiv(&word) {
self.bug(fmt!("unknown keyword: %s", word));
}
} }
// return true when this token represents the given string, and is not
// followed immediately by :: .
fn token_is_word(&self, word: &str, tok: &token::Token) -> bool {
match *tok {
token::IDENT(sid, false) => { word == *self.id_to_str(sid) }
_ => { false }
}
}
fn token_is_keyword(&self, word: &str, tok: &token::Token) -> bool {
self.require_keyword(word);
self.token_is_word(word, tok)
}
fn is_keyword(&self, word: &str) -> bool {
self.token_is_keyword(word, &copy *self.token)
}
fn id_is_any_keyword(&self, id: ast::ident) -> bool {
self.keywords.contains(self.id_to_str(id))
}
fn is_any_keyword(&self, tok: &token::Token) -> bool {
match *tok {
token::IDENT(sid, false) => {
self.keywords.contains(self.id_to_str(sid))
}
_ => false
}
}
// if the given word is not a keyword, signal an error.
// if the next token is the given keyword, eat it and return // if the next token is the given keyword, eat it and return
// true. Otherwise, return false. // true. Otherwise, return false.
fn eat_keyword(&self, word: &str) -> bool { fn eat_keyword(&self, kw: keywords::Keyword) -> bool {
self.require_keyword(word);
let is_kw = match *self.token { let is_kw = match *self.token {
token::IDENT(sid, false) => word == *self.id_to_str(sid), token::IDENT(sid, false) => kw.to_ident().repr == sid.repr,
_ => false _ => false
}; };
if is_kw { self.bump() } if is_kw { self.bump() }
@ -190,63 +152,30 @@ pub impl Parser {
// if the given word is not a keyword, signal an error. // if the given word is not a keyword, signal an error.
// if the next token is not the given word, signal an error. // if the next token is not the given word, signal an error.
// otherwise, eat it. // otherwise, eat it.
fn expect_keyword(&self, word: &str) { fn expect_keyword(&self, kw: keywords::Keyword) {
self.require_keyword(word); if !self.eat_keyword(kw) {
if !self.eat_keyword(word) {
self.fatal( self.fatal(
fmt!( fmt!(
"expected `%s`, found `%s`", "expected `%s`, found `%s`",
word, *self.id_to_str(kw.to_ident()),
self.this_token_to_str() self.this_token_to_str()
) )
); );
} }
} }
// return true if the given string is a strict keyword
fn is_strict_keyword(&self, word: &str) -> bool {
self.strict_keywords.contains_equiv(&word)
}
// signal an error if the current token is a strict keyword
fn check_strict_keywords(&self) {
match *self.token {
token::IDENT(_, false) => {
let w = token_to_str(self.reader, &copy *self.token);
self.check_strict_keywords_(w);
}
_ => ()
}
}
// signal an error if the given string is a strict keyword // signal an error if the given string is a strict keyword
fn check_strict_keywords_(&self, w: &str) { fn check_strict_keywords(&self) {
if self.is_strict_keyword(w) { if token::is_strict_keyword(self.token) {
self.span_err(*self.last_span, self.span_err(*self.last_span,
fmt!("found `%s` in ident position", w)); fmt!("found `%s` in ident position", self.this_token_to_str()));
} }
} }
// return true if this is a reserved keyword
fn is_reserved_keyword(&self, word: &str) -> bool {
self.reserved_keywords.contains_equiv(&word)
}
// signal an error if the current token is a reserved keyword // signal an error if the current token is a reserved keyword
fn check_reserved_keywords(&self) { fn check_reserved_keywords(&self) {
match *self.token { if token::is_reserved_keyword(self.token) {
token::IDENT(_, false) => { self.fatal(fmt!("`%s` is a reserved keyword", self.this_token_to_str()));
let w = token_to_str(self.reader, &copy *self.token);
self.check_reserved_keywords_(w);
}
_ => ()
}
}
// signal an error if the given string is a reserved keyword
fn check_reserved_keywords_(&self, w: &str) {
if self.is_reserved_keyword(w) {
self.fatal(fmt!("`%s` is a reserved keyword", w));
} }
} }

View file

@ -23,7 +23,7 @@ use ast::{expr, expr_lit, lit_nil, attribute};
use ast; use ast;
use codemap::{span, respan}; use codemap::{span, respan};
use parse::parser::Parser; use parse::parser::Parser;
use parse::token::Token; use parse::token::{keywords, Token};
use parse::token; use parse::token;
use core::to_bytes; use core::to_bytes;
@ -295,9 +295,9 @@ pub impl Parser {
} }
fn try_parse_obsolete_priv_section(&self, attrs: &[attribute]) -> bool { fn try_parse_obsolete_priv_section(&self, attrs: &[attribute]) -> bool {
if self.is_keyword("priv") && self.look_ahead(1) == token::LBRACE { if self.is_keyword(keywords::Priv) && self.look_ahead(1) == token::LBRACE {
self.obsolete(copy *self.span, ObsoletePrivSection); self.obsolete(copy *self.span, ObsoletePrivSection);
self.eat_keyword("priv"); self.eat_keyword(keywords::Priv);
self.bump(); self.bump();
while *self.token != token::RBRACE { while *self.token != token::RBRACE {
self.parse_single_struct_field(ast::private, attrs.to_owned()); self.parse_single_struct_field(ast::private, attrs.to_owned());

View file

@ -86,7 +86,7 @@ use parse::obsolete::{ObsoletePurity, ObsoleteStaticMethod};
use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType}; use parse::obsolete::{ObsoleteConstItem, ObsoleteFixedLengthVectorType};
use parse::obsolete::{ObsoleteNamedExternModule}; use parse::obsolete::{ObsoleteNamedExternModule};
use parse::token::{can_begin_expr, is_ident, is_ident_or_path}; use parse::token::{can_begin_expr, is_ident, is_ident_or_path};
use parse::token::{is_plain_ident, INTERPOLATED, special_idents, token_to_binop}; use parse::token::{is_plain_ident, INTERPOLATED, keywords, special_idents, token_to_binop};
use parse::token; use parse::token;
use parse::{new_sub_parser_from_file, next_node_id, ParseSess}; use parse::{new_sub_parser_from_file, next_node_id, ParseSess};
use opt_vec; use opt_vec;
@ -234,9 +234,6 @@ pub fn Parser(sess: @mut ParseSess,
tokens_consumed: @mut 0, tokens_consumed: @mut 0,
restriction: @mut UNRESTRICTED, restriction: @mut UNRESTRICTED,
quote_depth: @mut 0, quote_depth: @mut 0,
keywords: token::keyword_table(),
strict_keywords: token::strict_keyword_table(),
reserved_keywords: token::reserved_keyword_table(),
obsolete_set: @mut HashSet::new(), obsolete_set: @mut HashSet::new(),
mod_path_stack: @mut ~[], mod_path_stack: @mut ~[],
} }
@ -260,9 +257,6 @@ pub struct Parser {
quote_depth: @mut uint, // not (yet) related to the quasiquoter quote_depth: @mut uint, // not (yet) related to the quasiquoter
reader: @reader, reader: @reader,
interner: @token::ident_interner, interner: @token::ident_interner,
keywords: HashSet<~str>,
strict_keywords: HashSet<~str>,
reserved_keywords: HashSet<~str>,
/// The set of seen errors about obsolete syntax. Used to suppress /// The set of seen errors about obsolete syntax. Used to suppress
/// extra detail when the same error is seen twice /// extra detail when the same error is seen twice
obsolete_set: @mut HashSet<ObsoleteSyntax>, obsolete_set: @mut HashSet<ObsoleteSyntax>,
@ -340,10 +334,10 @@ pub impl Parser {
// is this one of the keywords that signals a closure type? // is this one of the keywords that signals a closure type?
fn token_is_closure_keyword(&self, tok: &token::Token) -> bool { fn token_is_closure_keyword(&self, tok: &token::Token) -> bool {
self.token_is_keyword("pure", tok) || token::is_keyword(keywords::Pure, tok) ||
self.token_is_keyword("unsafe", tok) || token::is_keyword(keywords::Unsafe, tok) ||
self.token_is_keyword("once", tok) || token::is_keyword(keywords::Once, tok) ||
self.token_is_keyword("fn", tok) token::is_keyword(keywords::Fn, tok)
} }
fn token_is_lifetime(&self, tok: &token::Token) -> bool { fn token_is_lifetime(&self, tok: &token::Token) -> bool {
@ -380,7 +374,7 @@ pub impl Parser {
let opt_abis = self.parse_opt_abis(); let opt_abis = self.parse_opt_abis();
let abis = opt_abis.get_or_default(AbiSet::Rust()); let abis = opt_abis.get_or_default(AbiSet::Rust());
let purity = self.parse_unsafety(); let purity = self.parse_unsafety();
self.expect_keyword("fn"); self.expect_keyword(keywords::Fn);
let (decl, lifetimes) = self.parse_ty_fn_decl(); let (decl, lifetimes) = self.parse_ty_fn_decl();
return ty_bare_fn(@TyBareFn { return ty_bare_fn(@TyBareFn {
abis: abis, abis: abis,
@ -416,7 +410,7 @@ pub impl Parser {
let purity = self.parse_unsafety(); let purity = self.parse_unsafety();
let onceness = parse_onceness(self); let onceness = parse_onceness(self);
self.expect_keyword("fn"); self.expect_keyword(keywords::Fn);
let bounds = self.parse_optional_ty_param_bounds(); let bounds = self.parse_optional_ty_param_bounds();
if self.parse_fn_ty_sigil().is_some() { if self.parse_fn_ty_sigil().is_some() {
@ -436,7 +430,7 @@ pub impl Parser {
}); });
fn parse_onceness(this: &Parser) -> Onceness { fn parse_onceness(this: &Parser) -> Onceness {
if this.eat_keyword("once") { if this.eat_keyword(keywords::Once) {
Once Once
} else { } else {
Many Many
@ -446,10 +440,10 @@ pub impl Parser {
// looks like this should be called parse_unsafety // looks like this should be called parse_unsafety
fn parse_unsafety(&self) -> purity { fn parse_unsafety(&self) -> purity {
if self.eat_keyword("pure") { if self.eat_keyword(keywords::Pure) {
self.obsolete(*self.last_span, ObsoletePurity); self.obsolete(*self.last_span, ObsoletePurity);
return impure_fn; return impure_fn;
} else if self.eat_keyword("unsafe") { } else if self.eat_keyword(keywords::Unsafe) {
return unsafe_fn; return unsafe_fn;
} else { } else {
return impure_fn; return impure_fn;
@ -704,7 +698,7 @@ pub impl Parser {
// BORROWED POINTER // BORROWED POINTER
self.bump(); self.bump();
self.parse_borrowed_pointee() self.parse_borrowed_pointee()
} else if self.eat_keyword("extern") { } else if self.eat_keyword(keywords::Extern) {
// EXTERN FUNCTION // EXTERN FUNCTION
self.parse_ty_bare_fn() self.parse_ty_bare_fn()
} else if self.token_is_closure_keyword(&copy *self.token) { } else if self.token_is_closure_keyword(&copy *self.token) {
@ -828,7 +822,7 @@ pub impl Parser {
let mut is_mutbl = false; let mut is_mutbl = false;
let pat = if require_name || self.is_named_argument() { let pat = if require_name || self.is_named_argument() {
self.parse_arg_mode(); self.parse_arg_mode();
is_mutbl = self.eat_keyword("mut"); is_mutbl = self.eat_keyword(keywords::Mut);
let pat = self.parse_pat(false); let pat = self.parse_pat(false);
self.expect(&token::COLON); self.expect(&token::COLON);
pat pat
@ -856,7 +850,7 @@ pub impl Parser {
// parse an argument in a lambda header e.g. |arg, arg| // parse an argument in a lambda header e.g. |arg, arg|
fn parse_fn_block_arg(&self) -> arg_or_capture_item { fn parse_fn_block_arg(&self) -> arg_or_capture_item {
self.parse_arg_mode(); self.parse_arg_mode();
let is_mutbl = self.eat_keyword("mut"); let is_mutbl = self.eat_keyword(keywords::Mut);
let pat = self.parse_pat(false); let pat = self.parse_pat(false);
let t = if self.eat(&token::COLON) { let t = if self.eat(&token::COLON) {
self.parse_ty(false) self.parse_ty(false)
@ -907,9 +901,9 @@ pub impl Parser {
// matches lit = true | false | token_lit // matches lit = true | false | token_lit
fn parse_lit(&self) -> lit { fn parse_lit(&self) -> lit {
let lo = self.span.lo; let lo = self.span.lo;
let lit = if self.eat_keyword("true") { let lit = if self.eat_keyword(keywords::True) {
lit_bool(true) lit_bool(true)
} else if self.eat_keyword("false") { } else if self.eat_keyword(keywords::False) {
lit_bool(false) lit_bool(false)
} else { } else {
// XXX: This is a really bad copy! // XXX: This is a really bad copy!
@ -1145,15 +1139,15 @@ pub impl Parser {
} }
fn token_is_mutability(&self, tok: &token::Token) -> bool { fn token_is_mutability(&self, tok: &token::Token) -> bool {
self.token_is_keyword("mut", tok) || token::is_keyword(keywords::Mut, tok) ||
self.token_is_keyword("const", tok) token::is_keyword(keywords::Const, tok)
} }
// parse mutability declaration (mut/const/imm) // parse mutability declaration (mut/const/imm)
fn parse_mutability(&self) -> mutability { fn parse_mutability(&self) -> mutability {
if self.eat_keyword("mut") { if self.eat_keyword(keywords::Mut) {
m_mutbl m_mutbl
} else if self.eat_keyword("const") { } else if self.eat_keyword(keywords::Const) {
m_const m_const
} else { } else {
m_imm m_imm
@ -1251,30 +1245,30 @@ pub impl Parser {
expr_block(blk)); expr_block(blk));
} else if token::is_bar(&*self.token) { } else if token::is_bar(&*self.token) {
return self.parse_lambda_expr(); return self.parse_lambda_expr();
} else if self.eat_keyword("self") { } else if self.eat_keyword(keywords::Self) {
ex = expr_self; ex = expr_self;
hi = self.span.hi; hi = self.span.hi;
} else if self.eat_keyword("if") { } else if self.eat_keyword(keywords::If) {
return self.parse_if_expr(); return self.parse_if_expr();
} else if self.eat_keyword("for") { } else if self.eat_keyword(keywords::For) {
return self.parse_sugary_call_expr(~"for", ForSugar, return self.parse_sugary_call_expr(~"for", ForSugar,
expr_loop_body); expr_loop_body);
} else if self.eat_keyword("do") { } else if self.eat_keyword(keywords::Do) {
return self.parse_sugary_call_expr(~"do", DoSugar, return self.parse_sugary_call_expr(~"do", DoSugar,
expr_do_body); expr_do_body);
} else if self.eat_keyword("while") { } else if self.eat_keyword(keywords::While) {
return self.parse_while_expr(); return self.parse_while_expr();
} else if self.token_is_lifetime(&*self.token) { } else if self.token_is_lifetime(&*self.token) {
let lifetime = self.get_lifetime(&*self.token); let lifetime = self.get_lifetime(&*self.token);
self.bump(); self.bump();
self.expect(&token::COLON); self.expect(&token::COLON);
self.expect_keyword("loop"); self.expect_keyword(keywords::Loop);
return self.parse_loop_expr(Some(lifetime)); return self.parse_loop_expr(Some(lifetime));
} else if self.eat_keyword("loop") { } else if self.eat_keyword(keywords::Loop) {
return self.parse_loop_expr(None); return self.parse_loop_expr(None);
} else if self.eat_keyword("match") { } else if self.eat_keyword(keywords::Match) {
return self.parse_match_expr(); return self.parse_match_expr();
} else if self.eat_keyword("unsafe") { } else if self.eat_keyword(keywords::Unsafe) {
return self.parse_block_expr(lo, unsafe_blk); return self.parse_block_expr(lo, unsafe_blk);
} else if *self.token == token::LBRACKET { } else if *self.token == token::LBRACKET {
self.bump(); self.bump();
@ -1314,7 +1308,7 @@ pub impl Parser {
} }
} }
hi = self.last_span.hi; hi = self.last_span.hi;
} else if self.eat_keyword("__log") { } else if self.eat_keyword(keywords::__Log) {
// LOG expression // LOG expression
self.expect(&token::LPAREN); self.expect(&token::LPAREN);
let lvl = self.parse_expr(); let lvl = self.parse_expr();
@ -1323,14 +1317,14 @@ pub impl Parser {
ex = expr_log(lvl, e); ex = expr_log(lvl, e);
hi = self.span.hi; hi = self.span.hi;
self.expect(&token::RPAREN); self.expect(&token::RPAREN);
} else if self.eat_keyword("return") { } else if self.eat_keyword(keywords::Return) {
// RETURN expression // RETURN expression
if can_begin_expr(&*self.token) { if can_begin_expr(&*self.token) {
let e = self.parse_expr(); let e = self.parse_expr();
hi = e.span.hi; hi = e.span.hi;
ex = expr_ret(Some(e)); ex = expr_ret(Some(e));
} else { ex = expr_ret(None); } } else { ex = expr_ret(None); }
} else if self.eat_keyword("break") { } else if self.eat_keyword(keywords::Break) {
// BREAK expression // BREAK expression
if self.token_is_lifetime(&*self.token) { if self.token_is_lifetime(&*self.token) {
let lifetime = self.get_lifetime(&*self.token); let lifetime = self.get_lifetime(&*self.token);
@ -1340,14 +1334,14 @@ pub impl Parser {
ex = expr_break(None); ex = expr_break(None);
} }
hi = self.span.hi; hi = self.span.hi;
} else if self.eat_keyword("copy") { } else if self.eat_keyword(keywords::Copy) {
// COPY expression // COPY expression
let e = self.parse_expr(); let e = self.parse_expr();
ex = expr_copy(e); ex = expr_copy(e);
hi = e.span.hi; hi = e.span.hi;
} else if *self.token == token::MOD_SEP || } else if *self.token == token::MOD_SEP ||
is_ident(&*self.token) && !self.is_keyword("true") && is_ident(&*self.token) && !self.is_keyword(keywords::True) &&
!self.is_keyword("false") { !self.is_keyword(keywords::False) {
let pth = self.parse_path_with_tps(true); let pth = self.parse_path_with_tps(true);
// `!`, as an operator, is prefix, so we know this isn't that // `!`, as an operator, is prefix, so we know this isn't that
@ -1827,7 +1821,7 @@ pub impl Parser {
} }
} }
None => { None => {
if as_prec > min_prec && self.eat_keyword("as") { if as_prec > min_prec && self.eat_keyword(keywords::As) {
let rhs = self.parse_ty(true); let rhs = self.parse_ty(true);
let _as = self.mk_expr(lhs.span.lo, let _as = self.mk_expr(lhs.span.lo,
rhs.span.hi, rhs.span.hi,
@ -1901,7 +1895,7 @@ pub impl Parser {
let thn = self.parse_block(); let thn = self.parse_block();
let mut els: Option<@expr> = None; let mut els: Option<@expr> = None;
let mut hi = thn.span.hi; let mut hi = thn.span.hi;
if self.eat_keyword("else") { if self.eat_keyword(keywords::Else) {
let elexpr = self.parse_else_expr(); let elexpr = self.parse_else_expr();
els = Some(elexpr); els = Some(elexpr);
hi = elexpr.span.hi; hi = elexpr.span.hi;
@ -1968,7 +1962,7 @@ pub impl Parser {
} }
fn parse_else_expr(&self) -> @expr { fn parse_else_expr(&self) -> @expr {
if self.eat_keyword("if") { if self.eat_keyword(keywords::If) {
return self.parse_if_expr(); return self.parse_if_expr();
} else { } else {
let blk = self.parse_block(); let blk = self.parse_block();
@ -2082,7 +2076,7 @@ pub impl Parser {
fn looking_at_record_literal(&self) -> bool { fn looking_at_record_literal(&self) -> bool {
let lookahead = self.look_ahead(1); let lookahead = self.look_ahead(1);
*self.token == token::LBRACE && *self.token == token::LBRACE &&
(self.token_is_keyword("mut", &lookahead) || (token::is_keyword(keywords::Mut, &lookahead) ||
(is_plain_ident(&lookahead) && (is_plain_ident(&lookahead) &&
self.look_ahead(2) == token::COLON)) self.look_ahead(2) == token::COLON))
} }
@ -2095,7 +2089,7 @@ pub impl Parser {
while *self.token != token::RBRACE { while *self.token != token::RBRACE {
let pats = self.parse_pats(); let pats = self.parse_pats();
let mut guard = None; let mut guard = None;
if self.eat_keyword("if") { guard = Some(self.parse_expr()); } if self.eat_keyword(keywords::If) { guard = Some(self.parse_expr()); }
self.expect(&token::FAT_ARROW); self.expect(&token::FAT_ARROW);
let expr = self.parse_expr_res(RESTRICT_STMT_EXPR); let expr = self.parse_expr_res(RESTRICT_STMT_EXPR);
@ -2384,8 +2378,8 @@ pub impl Parser {
} }
ref tok => { ref tok => {
if !is_ident_or_path(tok) if !is_ident_or_path(tok)
|| self.is_keyword("true") || self.is_keyword(keywords::True)
|| self.is_keyword("false") || self.is_keyword(keywords::False)
{ {
// Parse an expression pattern or exp .. exp. // Parse an expression pattern or exp .. exp.
// //
@ -2404,11 +2398,11 @@ pub impl Parser {
} else { } else {
pat = pat_lit(val); pat = pat_lit(val);
} }
} else if self.eat_keyword("ref") { } else if self.eat_keyword(keywords::Ref) {
// parse ref pat // parse ref pat
let mutbl = self.parse_mutability(); let mutbl = self.parse_mutability();
pat = self.parse_pat_ident(refutable, bind_by_ref(mutbl)); pat = self.parse_pat_ident(refutable, bind_by_ref(mutbl));
} else if self.eat_keyword("copy") { } else if self.eat_keyword(keywords::Copy) {
// parse copy pat // parse copy pat
pat = self.parse_pat_ident(refutable, bind_by_copy); pat = self.parse_pat_ident(refutable, bind_by_copy);
} else { } else {
@ -2558,7 +2552,7 @@ pub impl Parser {
// parse a "let" stmt // parse a "let" stmt
fn parse_let(&self) -> @decl { fn parse_let(&self) -> @decl {
let is_mutbl = self.eat_keyword("mut"); let is_mutbl = self.eat_keyword(keywords::Mut);
let lo = self.span.lo; let lo = self.span.lo;
let mut locals = ~[self.parse_local(is_mutbl)]; let mut locals = ~[self.parse_local(is_mutbl)];
while self.eat(&token::COMMA) { while self.eat(&token::COMMA) {
@ -2572,7 +2566,7 @@ pub impl Parser {
pr: visibility, pr: visibility,
attrs: ~[attribute]) -> @struct_field { attrs: ~[attribute]) -> @struct_field {
let lo = self.span.lo; let lo = self.span.lo;
if self.eat_keyword("mut") { if self.eat_keyword(keywords::Mut) {
// Do nothing, for backwards compatibility. // Do nothing, for backwards compatibility.
// XXX: Remove after snapshot. // XXX: Remove after snapshot.
} }
@ -2604,13 +2598,13 @@ pub impl Parser {
} }
let lo = self.span.lo; let lo = self.span.lo;
if self.is_keyword("let") { if self.is_keyword(keywords::Let) {
check_expected_item(self, item_attrs); check_expected_item(self, item_attrs);
self.expect_keyword("let"); self.expect_keyword(keywords::Let);
let decl = self.parse_let(); let decl = self.parse_let();
return @spanned(lo, decl.span.hi, stmt_decl(decl, self.get_id())); return @spanned(lo, decl.span.hi, stmt_decl(decl, self.get_id()));
} else if is_ident(&*self.token) } else if is_ident(&*self.token)
&& !self.is_any_keyword(&copy *self.token) && !token::is_any_keyword(self.token)
&& self.look_ahead(1) == token::NOT { && self.look_ahead(1) == token::NOT {
// parse a macro invocation. Looks like there's serious // parse a macro invocation. Looks like there's serious
// overlap here; if this clause doesn't catch it (and it // overlap here; if this clause doesn't catch it (and it
@ -2690,7 +2684,7 @@ pub impl Parser {
maybe_whole!(self, nt_block); maybe_whole!(self, nt_block);
let lo = self.span.lo; let lo = self.span.lo;
if self.eat_keyword("unsafe") { if self.eat_keyword(keywords::Unsafe) {
self.obsolete(copy *self.span, ObsoleteUnsafeBlock); self.obsolete(copy *self.span, ObsoleteUnsafeBlock);
} }
self.expect(&token::LBRACE); self.expect(&token::LBRACE);
@ -2705,7 +2699,7 @@ pub impl Parser {
maybe_whole!(pair_empty self, nt_block); maybe_whole!(pair_empty self, nt_block);
let lo = self.span.lo; let lo = self.span.lo;
if self.eat_keyword("unsafe") { if self.eat_keyword(keywords::Unsafe) {
self.obsolete(copy *self.span, ObsoleteUnsafeBlock); self.obsolete(copy *self.span, ObsoleteUnsafeBlock);
} }
self.expect(&token::LBRACE); self.expect(&token::LBRACE);
@ -2849,10 +2843,10 @@ pub impl Parser {
} }
fn parse_optional_purity(&self) -> ast::purity { fn parse_optional_purity(&self) -> ast::purity {
if self.eat_keyword("pure") { if self.eat_keyword(keywords::Pure) {
self.obsolete(*self.last_span, ObsoletePurity); self.obsolete(*self.last_span, ObsoletePurity);
ast::impure_fn ast::impure_fn
} else if self.eat_keyword("unsafe") { } else if self.eat_keyword(keywords::Unsafe) {
ast::unsafe_fn ast::unsafe_fn
} else { } else {
ast::impure_fn ast::impure_fn
@ -2860,7 +2854,7 @@ pub impl Parser {
} }
fn parse_optional_onceness(&self) -> ast::Onceness { fn parse_optional_onceness(&self) -> ast::Onceness {
if self.eat_keyword("once") { ast::Once } else { ast::Many } if self.eat_keyword(keywords::Once) { ast::Once } else { ast::Many }
} }
// matches optbounds = ( ( : ( boundseq )? )? ) // matches optbounds = ( ( : ( boundseq )? )? )
@ -3023,10 +3017,10 @@ pub impl Parser {
p: &Parser p: &Parser
) -> ast::explicit_self_ { ) -> ast::explicit_self_ {
// We need to make sure it isn't a mode or a type // We need to make sure it isn't a mode or a type
if p.token_is_keyword("self", &p.look_ahead(1)) || if token::is_keyword(keywords::Self, &p.look_ahead(1)) ||
((p.token_is_keyword("const", &p.look_ahead(1)) || ((token::is_keyword(keywords::Const, &p.look_ahead(1)) ||
p.token_is_keyword("mut", &p.look_ahead(1))) && token::is_keyword(keywords::Mut, &p.look_ahead(1))) &&
p.token_is_keyword("self", &p.look_ahead(2))) { token::is_keyword(keywords::Self, &p.look_ahead(2))) {
p.bump(); p.bump();
let mutability = p.parse_mutability(); let mutability = p.parse_mutability();
@ -3047,25 +3041,25 @@ pub impl Parser {
// //
// We already know that the current token is `&`. // We already know that the current token is `&`.
if (this.token_is_keyword("self", &this.look_ahead(1))) { if (token::is_keyword(keywords::Self, &this.look_ahead(1))) {
this.bump(); this.bump();
this.expect_self_ident(); this.expect_self_ident();
sty_region(None, m_imm) sty_region(None, m_imm)
} else if (this.token_is_mutability(&this.look_ahead(1)) && } else if (this.token_is_mutability(&this.look_ahead(1)) &&
this.token_is_keyword("self", &this.look_ahead(2))) { token::is_keyword(keywords::Self, &this.look_ahead(2))) {
this.bump(); this.bump();
let mutability = this.parse_mutability(); let mutability = this.parse_mutability();
this.expect_self_ident(); this.expect_self_ident();
sty_region(None, mutability) sty_region(None, mutability)
} else if (this.token_is_lifetime(&this.look_ahead(1)) && } else if (this.token_is_lifetime(&this.look_ahead(1)) &&
this.token_is_keyword("self", &this.look_ahead(2))) { token::is_keyword(keywords::Self, &this.look_ahead(2))) {
this.bump(); this.bump();
let lifetime = @this.parse_lifetime(); let lifetime = @this.parse_lifetime();
this.expect_self_ident(); this.expect_self_ident();
sty_region(Some(lifetime), m_imm) sty_region(Some(lifetime), m_imm)
} else if (this.token_is_lifetime(&this.look_ahead(1)) && } else if (this.token_is_lifetime(&this.look_ahead(1)) &&
this.token_is_mutability(&this.look_ahead(2)) && this.token_is_mutability(&this.look_ahead(2)) &&
this.token_is_keyword("self", &this.look_ahead(3))) { token::is_keyword(keywords::Self, &this.look_ahead(3))) {
this.bump(); this.bump();
let lifetime = @this.parse_lifetime(); let lifetime = @this.parse_lifetime();
let mutability = this.parse_mutability(); let mutability = this.parse_mutability();
@ -3274,7 +3268,7 @@ pub impl Parser {
let mut ty = self.parse_ty(false); let mut ty = self.parse_ty(false);
// Parse traits, if necessary. // Parse traits, if necessary.
let opt_trait = if could_be_trait && self.eat_keyword("for") { let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
// New-style trait. Reinterpret the type as a trait. // New-style trait. Reinterpret the type as a trait.
let opt_trait_ref = match ty.node { let opt_trait_ref = match ty.node {
ty_path(path, node_id) => { ty_path(path, node_id) => {
@ -3449,11 +3443,11 @@ pub impl Parser {
return ~[]; return ~[];
} }
if self.eat_keyword("priv") { if self.eat_keyword(keywords::Priv) {
return ~[self.parse_single_struct_field(private, attrs)] return ~[self.parse_single_struct_field(private, attrs)]
} }
if self.eat_keyword("pub") { if self.eat_keyword(keywords::Pub) {
return ~[self.parse_single_struct_field(public, attrs)]; return ~[self.parse_single_struct_field(public, attrs)];
} }
@ -3466,13 +3460,13 @@ pub impl Parser {
// parse visiility: PUB, PRIV, or nothing // parse visiility: PUB, PRIV, or nothing
fn parse_visibility(&self) -> visibility { fn parse_visibility(&self) -> visibility {
if self.eat_keyword("pub") { public } if self.eat_keyword(keywords::Pub) { public }
else if self.eat_keyword("priv") { private } else if self.eat_keyword(keywords::Priv) { private }
else { inherited } else { inherited }
} }
fn parse_staticness(&self) -> bool { fn parse_staticness(&self) -> bool {
if self.eat_keyword("static") { if self.eat_keyword(keywords::Static) {
self.obsolete(*self.last_span, ObsoleteStaticMethod); self.obsolete(*self.last_span, ObsoleteStaticMethod);
true true
} else { } else {
@ -3692,10 +3686,10 @@ pub impl Parser {
let lo = self.span.lo; let lo = self.span.lo;
// XXX: Obsolete; remove after snap. // XXX: Obsolete; remove after snap.
if self.eat_keyword("const") { if self.eat_keyword(keywords::Const) {
self.obsolete(*self.last_span, ObsoleteConstItem); self.obsolete(*self.last_span, ObsoleteConstItem);
} else { } else {
self.expect_keyword("static"); self.expect_keyword(keywords::Static);
} }
let ident = self.parse_ident(); let ident = self.parse_ident();
@ -3713,14 +3707,14 @@ pub impl Parser {
// parse safe/unsafe and fn // parse safe/unsafe and fn
fn parse_fn_purity(&self) -> purity { fn parse_fn_purity(&self) -> purity {
if self.eat_keyword("fn") { impure_fn } if self.eat_keyword(keywords::Fn) { impure_fn }
else if self.eat_keyword("pure") { else if self.eat_keyword(keywords::Pure) {
self.obsolete(*self.last_span, ObsoletePurity); self.obsolete(*self.last_span, ObsoletePurity);
self.expect_keyword("fn"); self.expect_keyword(keywords::Fn);
// NB: We parse this as impure for bootstrapping purposes. // NB: We parse this as impure for bootstrapping purposes.
impure_fn impure_fn
} else if self.eat_keyword("unsafe") { } else if self.eat_keyword(keywords::Unsafe) {
self.expect_keyword("fn"); self.expect_keyword(keywords::Fn);
unsafe_fn unsafe_fn
} }
else { self.unexpected(); } else { self.unexpected(); }
@ -3762,9 +3756,9 @@ pub impl Parser {
items_allowed: bool) items_allowed: bool)
-> item_or_view_item { -> item_or_view_item {
let mut must_be_named_mod = false; let mut must_be_named_mod = false;
if self.is_keyword("mod") { if self.is_keyword(keywords::Mod) {
must_be_named_mod = true; must_be_named_mod = true;
self.expect_keyword("mod"); self.expect_keyword(keywords::Mod);
} else if *self.token != token::LBRACE { } else if *self.token != token::LBRACE {
self.span_fatal( self.span_fatal(
copy *self.span, copy *self.span,
@ -4049,7 +4043,7 @@ pub impl Parser {
let visibility = self.parse_visibility(); let visibility = self.parse_visibility();
// must be a view item: // must be a view item:
if self.eat_keyword("use") { if self.eat_keyword(keywords::Use) {
// USE ITEM (iovi_view_item) // USE ITEM (iovi_view_item)
let view_item = self.parse_use(); let view_item = self.parse_use();
self.expect(&token::SEMI); self.expect(&token::SEMI);
@ -4061,10 +4055,10 @@ pub impl Parser {
}); });
} }
// either a view item or an item: // either a view item or an item:
if self.eat_keyword("extern") { if self.eat_keyword(keywords::Extern) {
let opt_abis = self.parse_opt_abis(); let opt_abis = self.parse_opt_abis();
if self.eat_keyword("fn") { if self.eat_keyword(keywords::Fn) {
// EXTERN FUNCTION ITEM // EXTERN FUNCTION ITEM
let abis = opt_abis.get_or_default(AbiSet::C()); let abis = opt_abis.get_or_default(AbiSet::C());
let (ident, item_, extra_attrs) = let (ident, item_, extra_attrs) =
@ -4080,11 +4074,11 @@ pub impl Parser {
} }
} }
// the rest are all guaranteed to be items: // the rest are all guaranteed to be items:
if (self.is_keyword("const") || if (self.is_keyword(keywords::Const) ||
(self.is_keyword("static") && (self.is_keyword(keywords::Static) &&
!self.token_is_keyword("fn", &self.look_ahead(1)))) { !token::is_keyword(keywords::Fn, &self.look_ahead(1)))) {
// CONST / STATIC ITEM // CONST / STATIC ITEM
if self.is_keyword("const") { if self.is_keyword(keywords::Const) {
self.obsolete(*self.span, ObsoleteConstItem); self.obsolete(*self.span, ObsoleteConstItem);
} }
self.bump(); self.bump();
@ -4093,7 +4087,7 @@ pub impl Parser {
visibility, visibility,
maybe_append(attrs, extra_attrs))); maybe_append(attrs, extra_attrs)));
} }
if self.is_keyword("fn") && if self.is_keyword(keywords::Fn) &&
!self.fn_expr_lookahead(self.look_ahead(1u)) { !self.fn_expr_lookahead(self.look_ahead(1u)) {
// FUNCTION ITEM // FUNCTION ITEM
self.bump(); self.bump();
@ -4103,28 +4097,28 @@ pub impl Parser {
visibility, visibility,
maybe_append(attrs, extra_attrs))); maybe_append(attrs, extra_attrs)));
} }
if self.eat_keyword("pure") { if self.eat_keyword(keywords::Pure) {
// PURE FUNCTION ITEM (obsolete) // PURE FUNCTION ITEM (obsolete)
self.obsolete(*self.last_span, ObsoletePurity); self.obsolete(*self.last_span, ObsoletePurity);
self.expect_keyword("fn"); self.expect_keyword(keywords::Fn);
let (ident, item_, extra_attrs) = let (ident, item_, extra_attrs) =
self.parse_item_fn(impure_fn, AbiSet::Rust()); self.parse_item_fn(impure_fn, AbiSet::Rust());
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs))); maybe_append(attrs, extra_attrs)));
} }
if self.is_keyword("unsafe") if self.is_keyword(keywords::Unsafe)
&& self.look_ahead(1u) != token::LBRACE { && self.look_ahead(1u) != token::LBRACE {
// UNSAFE FUNCTION ITEM // UNSAFE FUNCTION ITEM
self.bump(); self.bump();
self.expect_keyword("fn"); self.expect_keyword(keywords::Fn);
let (ident, item_, extra_attrs) = let (ident, item_, extra_attrs) =
self.parse_item_fn(unsafe_fn, AbiSet::Rust()); self.parse_item_fn(unsafe_fn, AbiSet::Rust());
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs))); maybe_append(attrs, extra_attrs)));
} }
if self.eat_keyword("mod") { if self.eat_keyword(keywords::Mod) {
// MODULE ITEM // MODULE ITEM
let (ident, item_, extra_attrs) = let (ident, item_, extra_attrs) =
self.parse_item_mod(/*bad*/ copy attrs); self.parse_item_mod(/*bad*/ copy attrs);
@ -4132,28 +4126,28 @@ pub impl Parser {
visibility, visibility,
maybe_append(attrs, extra_attrs))); maybe_append(attrs, extra_attrs)));
} }
if self.eat_keyword("type") { if self.eat_keyword(keywords::Type) {
// TYPE ITEM // TYPE ITEM
let (ident, item_, extra_attrs) = self.parse_item_type(); let (ident, item_, extra_attrs) = self.parse_item_type();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs))); maybe_append(attrs, extra_attrs)));
} }
if self.eat_keyword("enum") { if self.eat_keyword(keywords::Enum) {
// ENUM ITEM // ENUM ITEM
let (ident, item_, extra_attrs) = self.parse_item_enum(); let (ident, item_, extra_attrs) = self.parse_item_enum();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs))); maybe_append(attrs, extra_attrs)));
} }
if self.eat_keyword("trait") { if self.eat_keyword(keywords::Trait) {
// TRAIT ITEM // TRAIT ITEM
let (ident, item_, extra_attrs) = self.parse_item_trait(); let (ident, item_, extra_attrs) = self.parse_item_trait();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs))); maybe_append(attrs, extra_attrs)));
} }
if self.eat_keyword("impl") { if self.eat_keyword(keywords::Impl) {
// IMPL ITEM // IMPL ITEM
let (ident, item_, extra_attrs) = let (ident, item_, extra_attrs) =
self.parse_item_impl(visibility); self.parse_item_impl(visibility);
@ -4161,7 +4155,7 @@ pub impl Parser {
visibility, visibility,
maybe_append(attrs, extra_attrs))); maybe_append(attrs, extra_attrs)));
} }
if self.eat_keyword("struct") { if self.eat_keyword(keywords::Struct) {
// STRUCT ITEM // STRUCT ITEM
let (ident, item_, extra_attrs) = self.parse_item_struct(); let (ident, item_, extra_attrs) = self.parse_item_struct();
return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_,
@ -4182,13 +4176,13 @@ pub impl Parser {
let visibility = self.parse_visibility(); let visibility = self.parse_visibility();
if (self.is_keyword("const") || self.is_keyword("static")) { if (self.is_keyword(keywords::Const) || self.is_keyword(keywords::Static)) {
// FOREIGN CONST ITEM // FOREIGN CONST ITEM
let item = self.parse_item_foreign_const(visibility, attrs); let item = self.parse_item_foreign_const(visibility, attrs);
return iovi_foreign_item(item); return iovi_foreign_item(item);
} }
if (self.is_keyword("fn") || self.is_keyword("pure") || if (self.is_keyword(keywords::Fn) || self.is_keyword(keywords::Pure) ||
self.is_keyword("unsafe")) { self.is_keyword(keywords::Unsafe)) {
// FOREIGN FUNCTION ITEM // FOREIGN FUNCTION ITEM
let item = self.parse_item_foreign_fn(attrs); let item = self.parse_item_foreign_fn(attrs);
return iovi_foreign_item(item); return iovi_foreign_item(item);
@ -4204,7 +4198,7 @@ pub impl Parser {
lo : BytePos, lo : BytePos,
visibility : visibility visibility : visibility
) -> item_or_view_item { ) -> item_or_view_item {
if macros_allowed && !self.is_any_keyword(&copy *self.token) if macros_allowed && !token::is_any_keyword(self.token)
&& self.look_ahead(1) == token::NOT && self.look_ahead(1) == token::NOT
&& (is_plain_ident(&self.look_ahead(2)) && (is_plain_ident(&self.look_ahead(2))
|| self.look_ahead(2) == token::LPAREN || self.look_ahead(2) == token::LPAREN
@ -4379,16 +4373,16 @@ pub impl Parser {
fn is_view_item(&self) -> bool { fn is_view_item(&self) -> bool {
let tok, next_tok; let tok, next_tok;
if !self.is_keyword("pub") && !self.is_keyword("priv") { if !self.is_keyword(keywords::Pub) && !self.is_keyword(keywords::Priv) {
tok = copy *self.token; tok = copy *self.token;
next_tok = self.look_ahead(1); next_tok = self.look_ahead(1);
} else { } else {
tok = self.look_ahead(1); tok = self.look_ahead(1);
next_tok = self.look_ahead(2); next_tok = self.look_ahead(2);
}; };
self.token_is_keyword("use", &tok) token::is_keyword(keywords::Use, &tok)
|| (self.token_is_keyword("extern", &tok) && || (token::is_keyword(keywords::Extern, &tok) &&
self.token_is_keyword("mod", &next_tok)) token::is_keyword(keywords::Mod, &next_tok))
} }
// parse a view item. // parse a view item.
@ -4398,10 +4392,10 @@ pub impl Parser {
vis: visibility vis: visibility
) -> @view_item { ) -> @view_item {
let lo = self.span.lo; let lo = self.span.lo;
let node = if self.eat_keyword("use") { let node = if self.eat_keyword(keywords::Use) {
self.parse_use() self.parse_use()
} else if self.eat_keyword("extern") { } else if self.eat_keyword(keywords::Extern) {
self.expect_keyword("mod"); self.expect_keyword(keywords::Mod);
let ident = self.parse_ident(); let ident = self.parse_ident();
let metadata = self.parse_optional_meta(); let metadata = self.parse_optional_meta();
view_item_extern_mod(ident, metadata, self.get_id()) view_item_extern_mod(ident, metadata, self.get_id())

View file

@ -17,7 +17,6 @@ use util::interner::StrInterner;
use util::interner; use util::interner;
use core::cmp::Equiv; use core::cmp::Equiv;
use core::hashmap::HashSet;
use core::to_bytes; use core::to_bytes;
#[deriving(Encodable, Decodable, Eq)] #[deriving(Encodable, Decodable, Eq)]
@ -452,6 +451,45 @@ fn mk_fresh_ident_interner() -> @ident_interner {
"__field__", // 32 "__field__", // 32
"C", // 33 "C", // 33
"Self", // 34 "Self", // 34
"as", // 35
"break", // 36
"const", // 37
"copy", // 38
"do", // 39
"drop", // 40
"else", // 41
"enum", // 42
"extern", // 43
"false", // 44
"fn", // 45
"for", // 46
"if", // 47
"impl", // 48
"let", // 49
"__log", // 50
"loop", // 51
"match", // 52
"mod", // 53
"mut", // 54
"once", // 55
"priv", // 56
"pub", // 57
"pure", // 58
"ref", // 59
"return", // 60
"static", // 29 -- also a special ident
"self", // 8 -- also a special ident
"struct", // 61
"super", // 62
"true", // 63
"trait", // 64
"type", // 65
"unsafe", // 66
"use", // 67
"while", // 68
"be", // 69
]; ];
@ident_interner { @ident_interner {
@ -495,61 +533,134 @@ pub fn intern(str : &str) -> ast::ident {
/** /**
* All the valid words that have meaning in the Rust language. * All the valid words that have meaning in the Rust language.
* *
* Rust keywords are either 'temporary', 'strict' or 'reserved'. Temporary * Rust keywords are either 'strict' or 'reserved'. Strict keywords may not
* keywords are contextual and may be used as identifiers anywhere. They are
* expected to disappear from the grammar soon. Strict keywords may not
* appear as identifiers at all. Reserved keywords are not used anywhere in * appear as identifiers at all. Reserved keywords are not used anywhere in
* the language and may not appear as identifiers. * the language and may not appear as identifiers.
*/ */
pub fn keyword_table() -> HashSet<~str> { pub mod keywords {
let mut keywords = HashSet::new(); use ast::ident;
let mut strict = strict_keyword_table();
let mut reserved = reserved_keyword_table();
do strict.consume |word| { pub enum Keyword {
keywords.insert(word); // Strict keywords
} As,
do reserved.consume |word| { Break,
keywords.insert(word); Const,
Copy,
Do,
Drop,
Else,
Enum,
Extern,
False,
Fn,
For,
If,
Impl,
Let,
__Log,
Loop,
Match,
Mod,
Mut,
Once,
Priv,
Pub,
Pure,
Ref,
Return,
Static,
Self,
Struct,
Super,
True,
Trait,
Type,
Unsafe,
Use,
While,
// Reserved keywords
Be,
} }
keywords pub impl Keyword {
fn to_ident(&self) -> ident {
match *self {
As => ident { repr: 35, ctxt: 0 },
Break => ident { repr: 36, ctxt: 0 },
Const => ident { repr: 37, ctxt: 0 },
Copy => ident { repr: 38, ctxt: 0 },
Do => ident { repr: 39, ctxt: 0 },
Drop => ident { repr: 40, ctxt: 0 },
Else => ident { repr: 41, ctxt: 0 },
Enum => ident { repr: 42, ctxt: 0 },
Extern => ident { repr: 43, ctxt: 0 },
False => ident { repr: 44, ctxt: 0 },
Fn => ident { repr: 45, ctxt: 0 },
For => ident { repr: 46, ctxt: 0 },
If => ident { repr: 47, ctxt: 0 },
Impl => ident { repr: 48, ctxt: 0 },
Let => ident { repr: 49, ctxt: 0 },
__Log => ident { repr: 50, ctxt: 0 },
Loop => ident { repr: 51, ctxt: 0 },
Match => ident { repr: 52, ctxt: 0 },
Mod => ident { repr: 53, ctxt: 0 },
Mut => ident { repr: 54, ctxt: 0 },
Once => ident { repr: 55, ctxt: 0 },
Priv => ident { repr: 56, ctxt: 0 },
Pub => ident { repr: 57, ctxt: 0 },
Pure => ident { repr: 58, ctxt: 0 },
Ref => ident { repr: 59, ctxt: 0 },
Return => ident { repr: 60, ctxt: 0 },
Static => ident { repr: 29, ctxt: 0 },
Self => ident { repr: 8, ctxt: 0 },
Struct => ident { repr: 61, ctxt: 0 },
Super => ident { repr: 62, ctxt: 0 },
True => ident { repr: 63, ctxt: 0 },
Trait => ident { repr: 64, ctxt: 0 },
Type => ident { repr: 65, ctxt: 0 },
Unsafe => ident { repr: 66, ctxt: 0 },
Use => ident { repr: 67, ctxt: 0 },
While => ident { repr: 68, ctxt: 0 },
Be => ident { repr: 69, ctxt: 0 },
}
}
}
} }
/// Full keywords. May not appear anywhere else. pub fn is_keyword(kw: keywords::Keyword, tok: &Token) -> bool {
pub fn strict_keyword_table() -> HashSet<~str> { match *tok {
let mut words = HashSet::new(); token::IDENT(sid, false) => { kw.to_ident().repr == sid.repr }
let keys = ~[ _ => { false }
~"as",
~"break",
~"const", ~"copy",
~"do", ~"drop",
~"else", ~"enum", ~"extern",
~"false", ~"fn", ~"for",
~"if", ~"impl",
~"let", ~"__log", ~"loop",
~"match", ~"mod", ~"mut",
~"once",
~"priv", ~"pub", ~"pure",
~"ref", ~"return",
~"static", ~"self", ~"struct", ~"super",
~"true", ~"trait", ~"type",
~"unsafe", ~"use",
~"while"
];
do vec::consume(keys) |_, w| {
words.insert(w);
} }
return words;
} }
pub fn reserved_keyword_table() -> HashSet<~str> { pub fn is_any_keyword(tok: &Token) -> bool {
let mut words = HashSet::new(); match *tok {
let keys = ~[ token::IDENT(sid, false) => match sid.repr {
~"be" 8 | 29 | 35 .. 69 => true,
]; _ => false,
do vec::consume(keys) |_, s| { },
words.insert(s); _ => false
}
}
pub fn is_strict_keyword(tok: &Token) -> bool {
match *tok {
token::IDENT(sid, false) => match sid.repr {
8 | 29 | 35 .. 68 => true,
_ => false,
},
_ => false,
}
}
pub fn is_reserved_keyword(tok: &Token) -> bool {
match *tok {
token::IDENT(sid, false) => match sid.repr {
69 => true,
_ => false,
},
_ => false,
} }
return words;
} }