diff options
| author | Björn Steinbrink <bsteinbr@gmail.com> | 2013-05-25 17:45:45 +0200 |
|---|---|---|
| committer | Björn Steinbrink <bsteinbr@gmail.com> | 2013-05-25 17:57:22 +0200 |
| commit | 6c62d77830d75c5bbc9f546f944c038be2622a8b (patch) | |
| tree | 34bd1e833ec112b7a20ee54605214e3860ac336a /src/libsyntax/parse/common.rs | |
| parent | b238a0872507293b2650f6d225ef94071bd53f54 (diff) | |
| download | rust-6c62d77830d75c5bbc9f546f944c038be2622a8b.tar.gz rust-6c62d77830d75c5bbc9f546f944c038be2622a8b.zip | |
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.
Diffstat (limited to 'src/libsyntax/parse/common.rs')
| -rw-r--r-- | src/libsyntax/parse/common.rs | 97 |
1 files changed, 13 insertions, 84 deletions
diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index 7182b80880f..6a868fbf173 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -14,6 +14,7 @@ use ast; use codemap::{BytePos, spanned}; use parse::lexer::reader; use parse::parser::Parser; +use parse::token::keywords; use parse::token; use opt_vec; @@ -133,54 +134,15 @@ pub impl Parser { return if *self.token == *tok { self.bump(); true } else { false }; } - // Storing keywords as interned idents instead of strings would be nifty. - - // 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, © *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 - } + fn is_keyword(&self, kw: keywords::Keyword) -> bool { + token::is_keyword(kw, self.token) } - // if the given word is not a keyword, signal an error. // if the next token is the given keyword, eat it and return // true. Otherwise, return false. - fn eat_keyword(&self, word: &str) -> bool { - self.require_keyword(word); + fn eat_keyword(&self, kw: keywords::Keyword) -> bool { 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 }; 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 next token is not the given word, signal an error. // otherwise, eat it. - fn expect_keyword(&self, word: &str) { - self.require_keyword(word); - if !self.eat_keyword(word) { + fn expect_keyword(&self, kw: keywords::Keyword) { + if !self.eat_keyword(kw) { self.fatal( fmt!( "expected `%s`, found `%s`", - word, + *self.id_to_str(kw.to_ident()), 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, © *self.token); - self.check_strict_keywords_(w); - } - _ => () - } - } - // signal an error if the given string is a strict keyword - fn check_strict_keywords_(&self, w: &str) { - if self.is_strict_keyword(w) { + fn check_strict_keywords(&self) { + if token::is_strict_keyword(self.token) { 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 fn check_reserved_keywords(&self) { - match *self.token { - token::IDENT(_, false) => { - let w = token_to_str(self.reader, © *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)); + if token::is_reserved_keyword(self.token) { + self.fatal(fmt!("`%s` is a reserved keyword", self.this_token_to_str())); } } |
