1use std::f64;
4
5use lazy_static::lazy_static;
6use pest::prec_climber as pcl;
7use pest::prec_climber::PrecClimber;
8use pest_consume::{match_nodes, Error, Parser};
9use enquote::unquote;
10
11use crate::types::*;
12
13pub type Result<T> = std::result::Result<T, Error<Rule>>;
14pub(crate) type Node<'i> = pest_consume::Node<'i, Rule, ()>;
15
16lazy_static! {
17 static ref PRECCLIMBER: PrecClimber<Rule> = PrecClimber::new(
18 vec![
19 pcl::Operator::new(Rule::op_or, pcl::Assoc::Left),
20 pcl::Operator::new(Rule::op_unless, pcl::Assoc::Left),
21 pcl::Operator::new(Rule::op_and, pcl::Assoc::Left),
22 pcl::Operator::new(Rule::op_greater_than, pcl::Assoc::Left),
23 pcl::Operator::new(Rule::op_greater_than_equal, pcl::Assoc::Left),
24 pcl::Operator::new(Rule::op_less_than, pcl::Assoc::Left),
25 pcl::Operator::new(Rule::op_less_than_equal, pcl::Assoc::Left),
26 pcl::Operator::new(Rule::op_not_equal, pcl::Assoc::Left),
27 pcl::Operator::new(Rule::op_equal, pcl::Assoc::Left),
28 pcl::Operator::new(Rule::op_subtract, pcl::Assoc::Left),
29 pcl::Operator::new(Rule::op_add, pcl::Assoc::Left),
30 pcl::Operator::new(Rule::op_modulo, pcl::Assoc::Left),
31 pcl::Operator::new(Rule::op_divide, pcl::Assoc::Left),
32 pcl::Operator::new(Rule::op_multiply, pcl::Assoc::Left),
33 pcl::Operator::new(Rule::op_power, pcl::Assoc::Right)
34 ]
35 );
36}
37
38struct MetricSelectorIntermediate {
41 metric: String,
42 labels: Vec<Label>
43}
44
45struct MatchingIntermediate {
46 op: MatchingOp,
47 labels: Vec<String>
48}
49
50#[derive(Parser)]
51#[grammar = "prometheus.pest"]
52struct PrometheusParser;
53
54#[allow(clippy::int_plus_one)]
55#[pest_consume::parser]
56impl PrometheusParser {
57 fn EOI(_input: Node) -> Result<()> {
58 Ok(())
59 }
60
61 fn signed_float(input: Node) -> Result<Expression> {
62 let val = match input.as_str().trim() {
63 "Inf" | "+Inf" => f64::INFINITY,
64 "-Inf" => f64::NEG_INFINITY,
65 "NaN" | "+NaN" | "-NaN" => f64::NAN,
66 f => f.parse().map_err(|e| input.error(e))?
67 };
68
69 Ok(Expression::Float(val))
70 }
71
72 fn string(input: Node) -> Result<Expression> {
73 let s = unquote(input.as_str()).map_err(|e| input.error(e))?;
74
75 Ok(Expression::String(s))
76 }
77
78 fn label_key(input: Node) -> Result<String> {
79 Ok(input.as_str().trim().to_string())
80 }
81
82 fn label_value(input: Node) -> Result<String> {
83 unquote(input.as_str()).map_err(|e| input.error(e))
84 }
85
86 fn group(input: Node) -> Result<Expression> {
87 let span = Span::from_node(&input);
88 Ok(match_nodes!(input.into_children();
89 [expression(e)] => Group::new(e).span(span).wrap(),
90 [expression(e), subquery(s)] => Group::new(e)
91 .subquery(s)
92 .span(span)
93 .wrap()
94 ))
95 }
96
97 fn selector_metric(input: Node) -> Result<String> {
98 Ok(input.as_str().trim().to_string())
99 }
100
101 fn label_op_equal(_input: Node) -> Result<LabelOp> {
102 Ok(LabelOp::Equal)
103 }
104
105 fn label_op_not_equal(_input: Node) -> Result<LabelOp> {
106 Ok(LabelOp::NotEqual)
107 }
108
109 fn label_op_regex_equal(_input: Node) -> Result<LabelOp> {
110 Ok(LabelOp::RegexEqual)
111 }
112
113 fn label_op_regex_not_equal(_input: Node) -> Result<LabelOp> {
114 Ok(LabelOp::RegexNotEqual)
115 }
116
117 fn label_operator(input: Node) -> Result<LabelOp> {
118 Ok(match_nodes!(input.into_children();
119 [label_op_equal(op)] => op,
120 [label_op_not_equal(op)] => op,
121 [label_op_regex_equal(op)] => op,
122 [label_op_regex_not_equal(op)] => op,
123 ))
124 }
125
126 fn label(input: Node) -> Result<Label> {
127 let span = Some(Span::from_node(&input));
128 Ok(match_nodes!(input.into_children();
129 [label_key(key), label_operator(op), label_value(value)] => Label {
130 op, key, value, span
131 }
132 ))
133 }
134
135 fn selector_label(input: Node) -> Result<Vec<Label>> {
136 Ok(match_nodes!(input.into_children();
137 [label(l)..] => l.collect()
138 ))
139 }
140
141 fn duration_value(input: Node) -> Result<u64> {
142 Ok(input.as_str().trim().parse().map_err(|e| input.error(e))?)
143 }
144
145 fn duration_unit(input: Node) -> Result<String> {
146 Ok(input.as_str().trim().to_string())
147 }
148
149 fn subquery_duration(input: Node) -> Result<PromDuration> {
150 Ok(match_nodes!(input.children();
151 [duration_value(val), duration_unit(unit)] => {
152 PromDuration::from_pair(&unit, val).map_err(|e| input.error(e))?
153 }
154 ))
155 }
156
157 fn subquery(input: Node) -> Result<Subquery> {
158 let span = Some(Span::from_node(&input));
159 Ok(match_nodes!(input.children();
160 [subquery_duration(range)] => Subquery {
161 range, resolution: None, span
162 },
163 [subquery_duration(range), subquery_duration(resolution)] => Subquery {
164 range, resolution: Some(resolution), span
165 }
166 ))
167 }
168
169 fn selector_range(input: Node) -> Result<PromDuration> {
170 Ok(match_nodes!(input.children();
171 [duration_value(val), duration_unit(unit)] => {
172 PromDuration::from_pair(&unit, val).map_err(|e| input.error(e))?
173 }
174 ))
175 }
176
177 fn offset(input: Node) -> Result<PromDuration> {
178 Ok(match_nodes!(input.children();
179 [duration_value(val), duration_unit(unit)] => {
180 PromDuration::from_pair(&unit, val).map_err(|e| input.error(e))?
181 }
182 ))
183 }
184
185 fn metric_selector(input: Node) -> Result<MetricSelectorIntermediate> {
186 Ok(match_nodes!(input.into_children();
187 [selector_metric(metric)] => MetricSelectorIntermediate {
188 metric, labels: vec![]
189 },
190 [selector_metric(metric), selector_label(labels)] => {
191 MetricSelectorIntermediate {
192 metric, labels
193 }
194 }
195 ))
196 }
197
198 fn selector(input: Node) -> Result<Expression> {
199 let span = Some(Span::from_node(&input));
200
201 let mut metric = None;
202 let mut labels = None;
203 let mut range = None;
204 let mut offset = None;
205 let mut subquery = None;
206
207 for child in input.into_children() {
208 match child.as_rule() {
209 Rule::metric_selector => {
210 let intermediate = PrometheusParser::metric_selector(child)?;
211 metric = Some(intermediate.metric);
212 labels = Some(intermediate.labels);
213 },
214 Rule::selector_label => {
215 labels = Some(PrometheusParser::selector_label(child)?);
216 },
217 Rule::selector_range => {
218 range = Some(PrometheusParser::selector_range(child)?);
219 },
220 Rule::offset => {
221 offset = Some(PrometheusParser::offset(child)?);
222 },
223 Rule::subquery => {
224 subquery = Some(PrometheusParser::subquery(child)?);
225 },
226 r => return Err(child.error(format!(
227 "invalid rule {:?} in selector", r
228 )))
229 }
230 }
231
232 let labels = labels.unwrap_or_else(|| vec![]);
233
234 Ok(Expression::Selector(Selector {
235 metric,
236 labels,
237 range,
238 offset,
239 subquery,
240 span
241 }))
242 }
243
244 fn function_name(input: Node) -> Result<String> {
245 Ok(input.as_str().trim().to_string())
246 }
247
248 fn function_agg_op_by(_input: Node) -> Result<AggregationOp> {
249 Ok(AggregationOp::By)
250 }
251
252 fn function_agg_op_without(_input: Node) -> Result<AggregationOp> {
253 Ok(AggregationOp::Without)
254 }
255
256 fn function_agg_op(input: Node) -> Result<AggregationOp> {
257 Ok(match_nodes!(input.into_children();
258 [function_agg_op_by(o)] => o,
259 [function_agg_op_without(o)] => o
260 ))
261 }
262
263 fn function_agg(input: Node) -> Result<Aggregation> {
264 let span = Some(Span::from_node(&input));
265
266 Ok(match_nodes!(input.into_children();
267 [function_agg_op(op), label_key(labels)..] => Aggregation {
268 op,
269 labels: labels.collect(),
270 span
271 }
272 ))
273 }
274
275 fn function(input: Node) -> Result<Expression> {
276 let span = Some(Span::from_node(&input));
277
278 let mut name = None;
279 let mut args = Vec::new();
280 let mut aggregation = None;
281 let mut subquery = None;
282
283 for child in input.children() {
286 match child.as_rule() {
287 Rule::function_name => name = Some(PrometheusParser::function_name(child)?),
288 Rule::expression => args.push(Box::new(PrometheusParser::expression(child)?)),
289 Rule::function_agg => aggregation = Some(PrometheusParser::function_agg(child)?),
290 Rule::subquery => subquery = Some(PrometheusParser::subquery(child)?),
291 r => return Err(child.error(format!(
292 "invalid rule {:?} in function", r
293 )))
294 }
295 }
296
297 let name = match name {
298 Some(name) => name,
299 None => return Err(input.error("function name is required"))
300 };
301
302 Ok(Expression::Function(Function {
303 name,
304 args,
305 aggregation,
306 subquery,
307 span
308 }))
309 }
310
311 fn matching_on(_input: Node) -> Result<MatchingOp> {
312 Ok(MatchingOp::On)
313 }
314
315 fn matching_ignoring(_input: Node) -> Result<MatchingOp> {
316 Ok(MatchingOp::Ignoring)
317 }
318
319 fn matching(input: Node) -> Result<MatchingIntermediate> {
320 Ok(match_nodes!(input.into_children();
321 [matching_on(op), label_key(labels)..] => MatchingIntermediate {
322 op, labels: labels.collect()
323 },
324 [matching_ignoring(op), label_key(labels)..] => MatchingIntermediate {
325 op, labels: labels.collect()
326 }
327 ))
328 }
329
330 fn matching_group_left(_input: Node) -> Result<MatchingGroupOp> {
331 Ok(MatchingGroupOp::Left)
332 }
333
334 fn matching_group_right(_input: Node) -> Result<MatchingGroupOp> {
335 Ok(MatchingGroupOp::Right)
336 }
337
338 fn matching_group(input: Node) -> Result<MatchingGroup> {
339 let span = Some(Span::from_node(&input));
340
341 Ok(match_nodes!(input.into_children();
342 [matching_group_left(op), label_key(labels)..] => MatchingGroup {
343 op, labels: labels.collect(), span
344 },
345 [matching_group_right(op), label_key(labels)..] => MatchingGroup {
346 op, labels: labels.collect(), span
347 }
348 ))
349 }
350
351 fn matching_expression(input: Node) -> Result<Matching> {
352 let span = Some(Span::from_node(&input));
353
354 Ok(match_nodes!(input.into_children();
355 [matching(m)] => Matching {
356 op: m.op,
357 labels: m.labels,
358
359 group: None,
360
361 span
362 },
363 [matching(m), matching_group(g)] => Matching {
364 op: m.op,
365 labels: m.labels,
366
367 group: Some(g),
368
369 span
370 }
371 ))
372 }
373
374 #[prec_climb(expression_term, PRECCLIMBER)]
375 fn expression(lhs: Expression, op: Node, rhs: Expression) -> Result<Expression> {
376 let span = Some(Span::from_node(&op));
377
378 use Rule::*;
379 let kind = match op.as_rule() {
380 op_or => OperatorKind::Or,
381 op_unless => OperatorKind::Unless,
382 op_and => OperatorKind::And,
383 op_greater_than => OperatorKind::GreaterThan,
384 op_greater_than_equal => OperatorKind::GreaterThanEqual,
385 op_less_than => OperatorKind::LessThan,
386 op_less_than_equal => OperatorKind::LessThanEqual,
387 op_not_equal => OperatorKind::NotEqual,
388 op_equal => OperatorKind::Equal,
389 op_subtract => OperatorKind::Subtract,
390 op_add => OperatorKind::Add,
391 op_modulo => OperatorKind::Modulo,
392 op_divide => OperatorKind::Divide,
393 op_multiply => OperatorKind::Multiply,
394 op_power => OperatorKind::Power,
395 r => return Err(op.error(format!("rule {:?} isn't an operator", r)))
396 };
397
398 let mut matching_clause = None;
400 for child in op.into_children() {
401 if let Rule::matching_expression = child.as_rule() {
402 matching_clause = Some(PrometheusParser::matching_expression(child)?);
403 break;
404 }
405 }
406
407 Ok(Expression::Operator(Operator {
408 kind,
409 lhs: Box::new(lhs),
410 rhs: Box::new(rhs),
411
412 matching: matching_clause,
413
414 span
415 }))
416 }
417
418 fn expression_term(input: Node) -> Result<Expression> {
419 Ok(match_nodes!(input.into_children();
420 [signed_float(f)] => f,
421 [string(s)] => s,
422 [group(g)] => g,
423 [function(f)] => f,
424 [selector(s)] => s
425 ))
426 }
427
428 fn prometheus(input: Node) -> Result<Expression> {
429 Ok(match_nodes!(input.into_children();
430 [expression(e), EOI(_)] => e,
431 ))
432 }
433
434}
435
436pub fn parse_expr(expr: &str) -> Result<Expression> {
452 let inputs = PrometheusParser::parse(Rule::prometheus, expr)?;
453 let input = inputs.single()?;
454
455 let expr = PrometheusParser::prometheus(input)?;
456
457 Ok(expr)
458}