summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2024-04-28 22:45:17 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2024-04-28 22:45:17 +0200
commit74ed467e20f75f9301c1008015fc8c8c8e8571f3 (patch)
treeef98ebdf76bbb477e0a0c845ce9d7fcc76e7082b
parent611f6aaa7f6fc1b116bc681dec8cb05c4a6a51cd (diff)
downloadrebel-74ed467e20f75f9301c1008015fc8c8c8e8571f3.tar
rebel-74ed467e20f75f9301c1008015fc8c8c8e8571f3.zip
rebel-parse: use phf for faster keyword parsing
-rw-r--r--Cargo.lock64
-rw-r--r--crates/rebel-parse/Cargo.toml1
-rw-r--r--crates/rebel-parse/src/grammar/recipe.rs37
-rw-r--r--crates/rebel-parse/src/grammar/tokenize.rs24
-rw-r--r--crates/rebel-parse/src/token.rs12
5 files changed, 102 insertions, 36 deletions
diff --git a/Cargo.lock b/Cargo.lock
index a6efe32..6476593 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -695,6 +695,48 @@ dependencies = [
]
[[package]]
+name = "phf"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
+dependencies = [
+ "phf_macros",
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
+dependencies = [
+ "phf_shared",
+ "rand",
+]
+
+[[package]]
+name = "phf_macros"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.60",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
name = "proc-macro2"
version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -713,6 +755,21 @@ dependencies = [
]
[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+
+[[package]]
name = "rebel"
version = "0.1.0"
dependencies = [
@@ -757,6 +814,7 @@ dependencies = [
"clap",
"divan",
"peg",
+ "phf",
"rebel-common",
]
@@ -960,6 +1018,12 @@ dependencies = [
]
[[package]]
+name = "siphasher"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
+
+[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
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)]