diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-04-28 22:45:17 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-04-28 22:45:17 +0200 |
commit | 74ed467e20f75f9301c1008015fc8c8c8e8571f3 (patch) | |
tree | ef98ebdf76bbb477e0a0c845ce9d7fcc76e7082b /crates/rebel-parse | |
parent | 611f6aaa7f6fc1b116bc681dec8cb05c4a6a51cd (diff) | |
download | rebel-74ed467e20f75f9301c1008015fc8c8c8e8571f3.tar rebel-74ed467e20f75f9301c1008015fc8c8c8e8571f3.zip |
rebel-parse: use phf for faster keyword parsing
Diffstat (limited to 'crates/rebel-parse')
-rw-r--r-- | crates/rebel-parse/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/rebel-parse/src/grammar/recipe.rs | 37 | ||||
-rw-r--r-- | crates/rebel-parse/src/grammar/tokenize.rs | 24 | ||||
-rw-r--r-- | crates/rebel-parse/src/token.rs | 12 |
4 files changed, 38 insertions, 36 deletions
diff --git a/crates/rebel-parse/Cargo.toml b/crates/rebel-parse/Cargo.toml index fcd802f..7159976 100644 --- a/crates/rebel-parse/Cargo.toml +++ b/crates/rebel-parse/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" [dependencies] peg = "0.8.3" +phf = { version = "0.11.2", features = ["macros"] } rebel-common = { path = "../rebel-common" } [dev-dependencies] diff --git a/crates/rebel-parse/src/grammar/recipe.rs b/crates/rebel-parse/src/grammar/recipe.rs index 4d24dce..61688f5 100644 --- a/crates/rebel-parse/src/grammar/recipe.rs +++ b/crates/rebel-parse/src/grammar/recipe.rs @@ -12,10 +12,10 @@ peg::parser! { = recipe:recipe_stmt()* { recipe } pub rule recipe_stmt() -> ast::RecipeStmt<'a> - = keyword_fetch() name:ident() p('{') body:body() p('}') { + = [Token::Keyword(Keyword::Fetch)] name:ident() p('{') body:body() p('}') { ast::RecipeStmt::Fetch { name, body: ast::Body(Vec::new()) } } - / keyword_task() name:ident() p('(') params:func_params() p(')') + / [Token::Keyword(Keyword::Task)] name:ident() p('(') params:func_params() p(')') p('{') body:body() p('}') { ast::RecipeStmt::Task { name, params, body } } @@ -99,8 +99,8 @@ peg::parser! { = name:ident() p(':') typ:expr() { ast::FuncParam { name, typ } } rule literal() -> ast::Literal<'a> - = keyword_true() { ast::Literal::Bool(true) } - / keyword_false() { ast::Literal::Bool(false) } + = [Token::Keyword(Keyword::True)] { ast::Literal::Bool(true) } + / [Token::Keyword(Keyword::False)] { ast::Literal::Bool(false) } / [Token::Number(content)] { ? ast::Literal::number(content) } @@ -146,34 +146,7 @@ peg::parser! { = p_(ch1) p(ch2) rule ident() -> ast::Ident<'a> - = !keyword() [Token::Ident(name)] { ast::Ident { name } } - - rule keyword() - = keyword_true() - / keyword_false() - / keyword_fetch() - / keyword_task() - / keyword_struct() - / keyword_set() - / keyword_map() - - rule keyword_true() - = const_ident("true") - rule keyword_false() - = const_ident("false") - rule keyword_fetch() - = const_ident("fetch") - rule keyword_task() - = const_ident("task") - rule keyword_struct() - = const_ident("struct") - rule keyword_set() - = const_ident("set") - rule keyword_map() - = const_ident("map") - - rule const_ident(keyword: &str) - = [Token::Ident(name) if *name == keyword] + = [Token::Ident(name)] { ast::Ident { name } } rule delimited<T>(expr: rule<T>, delim: rule<()>) -> Vec<T> = values:(expr() ++ delim()) delim()? { values } diff --git a/crates/rebel-parse/src/grammar/tokenize.rs b/crates/rebel-parse/src/grammar/tokenize.rs index 4758e9e..a696852 100644 --- a/crates/rebel-parse/src/grammar/tokenize.rs +++ b/crates/rebel-parse/src/grammar/tokenize.rs @@ -2,6 +2,16 @@ use crate::token::*; pub use rules::*; +static KEYWORDS: phf::Map<&'static str, Keyword> = phf::phf_map! { + "true" => Keyword::True, + "false" => Keyword::False, + "fetch" => Keyword::Fetch, + "task" => Keyword::Task, + "struct" => Keyword::Struct, + "set" => Keyword::Set, + "map" => Keyword::Map, +}; + peg::parser! { pub grammar rules() for str { pub rule token_stream() -> TokenStream<'input> @@ -10,14 +20,20 @@ peg::parser! { pub rule token() -> Token<'input> = number:number() { Token::Number(number) } / string:string() { Token::Str(string) } - / ident:ident() { Token::Ident(ident) } + / token:ident_or_keyword() { token } / punct:punct() { Token::Punct(punct) } - rule ident() -> &'input str - = $( + rule ident_or_keyword() -> Token<'input> + = s:$( ['a'..='z' | 'A' ..='Z' | '_' ] ['a'..='z' | 'A' ..='Z' | '_' | '0'..='9']* - ) + ) { + if let Some(kw) = KEYWORDS.get(s) { + Token::Keyword(*kw) + } else { + Token::Ident(s) + } + } rule punct() -> Punct = ch:punct_char() spacing:spacing() { Punct(ch, spacing) } diff --git a/crates/rebel-parse/src/token.rs b/crates/rebel-parse/src/token.rs index 80d758d..bfa9c42 100644 --- a/crates/rebel-parse/src/token.rs +++ b/crates/rebel-parse/src/token.rs @@ -1,5 +1,6 @@ #[derive(Clone, Debug, PartialEq, Eq)] pub enum Token<'a> { + Keyword(Keyword), Ident(&'a str), Punct(Punct), Str(Str<'a>), @@ -7,6 +8,17 @@ pub enum Token<'a> { } #[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Keyword { + True, + False, + Fetch, + Task, + Struct, + Set, + Map, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Punct(pub char, pub Spacing); #[derive(Clone, Copy, Debug, PartialEq, Eq)] |