diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-04-03 21:43:46 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-04-03 22:31:14 +0200 |
commit | 142ab0db2902a42b1c11f9682d366a5c7750c649 (patch) | |
tree | f090807ba019a31ad963246159c3cd1b8cc842d1 | |
parent | 42e667a5086fa4a6557ef7a64e40b833a93f3124 (diff) | |
download | rebel-142ab0db2902a42b1c11f9682d366a5c7750c649.tar rebel-142ab0db2902a42b1c11f9682d366a5c7750c649.zip |
driver: parse: replace nom with peg
The PEG-based parser is much more concise and easier to understand than
the old combinator solution.
-rw-r--r-- | Cargo.lock | 45 | ||||
-rw-r--r-- | crates/driver/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/driver/src/context.rs | 4 | ||||
-rw-r--r-- | crates/driver/src/parse.rs | 120 |
4 files changed, 76 insertions, 95 deletions
@@ -360,12 +360,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] name = "nix" version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -378,16 +372,6 @@ dependencies = [ ] [[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] name = "olpc-cjson" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -405,6 +389,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] +name = "peg" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "400bcab7d219c38abf8bd7cc2054eb9bbbd4312d66f6a5557d572a203f646f61" +dependencies = [ + "peg-macros", + "peg-runtime", +] + +[[package]] +name = "peg-macros" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46e61cce859b76d19090f62da50a9fe92bab7c2a5f09e183763559a2ac392c90" +dependencies = [ + "peg-runtime", + "proc-macro2", + "quote", +] + +[[package]] +name = "peg-runtime" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36bae92c60fa2398ce4678b98b2c4b5a7c61099961ca1fa305aec04a9ad28922" + +[[package]] name = "pest" version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -478,7 +489,7 @@ dependencies = [ "indoc", "lazy_static", "nix", - "nom", + "peg", "rebel-common", "rebel-runner", "scoped-tls-hkt", diff --git a/crates/driver/Cargo.toml b/crates/driver/Cargo.toml index 683ebbe..673e0ba 100644 --- a/crates/driver/Cargo.toml +++ b/crates/driver/Cargo.toml @@ -18,8 +18,8 @@ handlebars = "5.1.2" indoc = "2.0.4" lazy_static = "1.4.0" nix = { version = "0.28.0", features = ["poll"] } -nom = "7.1.0" scoped-tls-hkt = "0.1.2" serde = { version = "1", features = ["derive", "rc"] } serde_yaml = "0.9" walkdir = "2" +peg = "0.8.2" diff --git a/crates/driver/src/context.rs b/crates/driver/src/context.rs index 47259b3..4698171 100644 --- a/crates/driver/src/context.rs +++ b/crates/driver/src/context.rs @@ -355,7 +355,9 @@ impl Context { } pub fn parse(&self, s: &str) -> error::Result<(TaskRef, TaskFlags)> { - let (parsed, flags) = parse::parse_task_with_flags(s).context("Invalid task syntax")?; + let (parsed, flags) = parse::task_with_flags(s) + .ok() + .context("Invalid task syntax")?; let recipe = parsed.id.recipe.to_string(); let task = parsed.id.task.to_string(); diff --git a/crates/driver/src/parse.rs b/crates/driver/src/parse.rs index df540fc..f71fd18 100644 --- a/crates/driver/src/parse.rs +++ b/crates/driver/src/parse.rs @@ -1,10 +1,3 @@ -use nom::{ - bytes::complete::{tag, take_while1}, - combinator::{all_consuming, opt}, - error::ParseError, - Err, IResult, InputLength, Parser, -}; - #[derive(Debug, Clone, Copy)] pub struct TaskID<'a> { pub recipe: &'a str, @@ -28,74 +21,49 @@ pub struct TaskFlags { pub force_run: bool, } -fn is_name_char(c: char) -> bool { - matches!(c, 'a'..='z' | 'A' ..='Z' | '0'..='9' | '_' | '-') -} - -fn name(input: &str) -> IResult<&str, &str> { - take_while1(is_name_char)(input) -} - -fn task_id(input: &str) -> IResult<&str, TaskID> { - let (input, recipe) = name(input)?; - let (input, _) = tag(":")(input)?; - let (input, task) = name(input)?; - Ok((input, TaskID { recipe, task })) -} - -fn task_arg_target(input: &str) -> IResult<&str, &str> { - let (input, _) = tag(":")(input)?; - let (input, target) = name(input)?; - Ok((input, target)) -} - -fn task_args(input: &str) -> IResult<&str, TaskArgs> { - let (input, _) = tag("/")(input)?; - let (input, host) = opt(name)(input)?; - let (input, target) = opt(task_arg_target)(input)?; - - Ok((input, TaskArgs { host, target })) -} - -fn task(input: &str) -> IResult<&str, Task> { - let (input, id) = task_id(input)?; - let (input, args) = opt(task_args)(input)?; - - Ok(( - input, - Task { - id, - args: args.unwrap_or_default(), - }, - )) -} - -fn task_flags(input: &str) -> IResult<&str, TaskFlags> { - let (input, force_run) = opt(tag("+"))(input)?; - - Ok(( - input, - TaskFlags { - force_run: force_run.is_some(), - }, - )) +peg::parser! { + grammar rules() for str { + rule t<T>(tag: rule<()>, value: rule<T>) -> T + = tag() v:value() { v } + + rule name_char() + = ['a'..='z' | 'A' ..='Z' | '0'..='9' | '_' | '-'] + + rule name() -> &'input str + = $(name_char()+) + + rule task_id() -> TaskID<'input> + = recipe:name() ":" task:name() { + TaskID { recipe, task } + } + + rule task_args() -> TaskArgs<'input> + = "/" host:name()? target:t(<":">, <name()>)? { + TaskArgs { + host, + target, + } + } + / { Default::default() } + + pub rule task() -> Task<'input> + = id:task_id() args:task_args() { + Task { + id, + args, + } + } + + rule force_run() -> bool + = "+" { true } + / { false } + + rule task_flags() -> TaskFlags + = force_run:force_run() { TaskFlags { force_run } } + + pub rule task_with_flags() -> (Task<'input>, TaskFlags) + = task:task() flags:task_flags() { (task, flags) } + } } -fn task_with_flags(input: &str) -> IResult<&str, (Task, TaskFlags)> { - let (input, task) = task(input)?; - let (input, flags) = task_flags(input)?; - - Ok((input, (task, flags))) -} - -fn parse_all<I, O, E: ParseError<I>, F>(f: F, input: I) -> Result<O, Err<E>> -where - I: InputLength, - F: Parser<I, O, E>, -{ - all_consuming(f)(input).map(|(_, result)| result) -} - -pub fn parse_task_with_flags(input: &str) -> Option<(Task, TaskFlags)> { - parse_all(task_with_flags, input).ok() -} +pub use rules::*; |