summaryrefslogtreecommitdiffstats
path: root/crates
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2024-04-03 21:43:46 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2024-04-03 22:31:14 +0200
commit142ab0db2902a42b1c11f9682d366a5c7750c649 (patch)
treef090807ba019a31ad963246159c3cd1b8cc842d1 /crates
parent42e667a5086fa4a6557ef7a64e40b833a93f3124 (diff)
downloadrebel-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.
Diffstat (limited to 'crates')
-rw-r--r--crates/driver/Cargo.toml2
-rw-r--r--crates/driver/src/context.rs4
-rw-r--r--crates/driver/src/parse.rs120
3 files changed, 48 insertions, 78 deletions
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::*;