summaryrefslogtreecommitdiffstats
path: root/crates/driver/src/parse.rs
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/driver/src/parse.rs
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/driver/src/parse.rs')
-rw-r--r--crates/driver/src/parse.rs120
1 files changed, 44 insertions, 76 deletions
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::*;