summaryrefslogtreecommitdiffstats
path: root/crates/driver/src/parse.rs
blob: da85c99f56251374793264e5046181f35232824a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#[derive(Debug, Clone, Copy)]
pub struct TaskID<'a> {
	pub recipe: &'a str,
	pub task: &'a str,
}

#[derive(Debug, Clone, Copy, Default)]
pub struct TaskArgs<'a> {
	pub host: Option<&'a str>,
	pub target: Option<&'a str>,
}

#[derive(Debug, Clone, Copy)]
pub struct Task<'a> {
	pub id: TaskID<'a>,
	pub args: TaskArgs<'a>,
}

#[derive(Debug, Clone, Copy)]
pub struct TaskFlags {
	pub force_run: bool,
}

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 recipe_id() -> &'input str
			= $(name() ("/" name())?)

		rule task_id() -> TaskID<'input>
			= recipe:recipe_id() ":" 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) }
	}
}

pub use rules::*;