1use crate::ast::*;
2use crate::function::FUNCTIONS;
3use pest::iterators::Pair;
4use pest::pratt_parser::{Assoc::*, Op, PrattParser};
5use pest::Parser;
6use pest_derive::Parser;
7use std::fmt::Display;
8use std::str::FromStr;
9use std::time::Duration;
10
11#[derive(Parser)]
12#[grammar = "promql.pest"]
13struct PromQLParser;
14
15lazy_static::lazy_static! {
16 static ref PRATT_PARSER: PrattParser<Rule> = {
17 use Rule::*;
18
19 PrattParser::new()
33 .op(Op::infix(or, Left))
34 .op(Op::infix(and, Left) | Op::infix(unless, Left))
35 .op(Op::infix(eq, Left)
36 | Op::infix(ne, Left)
37 | Op::infix(le, Left)
38 | Op::infix(lt, Left)
39 | Op::infix(ge, Left)
40 | Op::infix(gt, Left))
41 .op(Op::infix(add, Left) | Op::infix(sub, Left))
42 .op(Op::infix(mul, Left)
43 | Op::infix(div, Left)
44 | Op::infix(r#mod, Left)
45 | Op::infix(atan2, Left))
46 .op(Op::postfix(offset) | Op::postfix(at))
47 .op(Op::postfix(matrix) | Op::postfix(subquery))
48 .op(Op::prefix(neg) | Op::prefix(pos))
49 .op(Op::infix(pow, Right))
50 };
51}
52
53#[derive(Debug)]
55pub struct ParseError {
56 pub message: String,
57}
58
59impl ParseError {
60 pub fn new(message: String) -> Self {
61 ParseError { message }
62 }
63}
64
65impl Display for ParseError {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 self.message.fmt(f)
68 }
69}
70
71impl<T> From<pest::error::Error<T>> for ParseError
72where
73 T: pest::RuleType,
74{
75 fn from(e: pest::error::Error<T>) -> Self {
76 ParseError {
77 message: e.to_string(),
78 }
79 }
80}
81
82impl From<String> for ParseError {
83 fn from(e: String) -> Self {
84 ParseError { message: e }
85 }
86}
87
88impl From<&str> for ParseError {
89 fn from(e: &str) -> Self {
90 ParseError {
91 message: e.to_string(),
92 }
93 }
94}
95
96pub fn parse(promql: &str) -> Result<Expr, ParseError> {
98 let mut pairs = PromQLParser::parse(Rule::promql, promql)?;
99 Ok(parse_expr(pairs.next().unwrap())?)
100}
101
102fn parse_expr(pair: Pair<Rule>) -> Result<Expr, ParseError> {
103 let parse_primary = |primary: Pair<Rule>| match primary.as_rule() {
104 Rule::aggregate_expr => parse_aggregate_expr(primary),
105 Rule::function_call => parse_function_call(primary),
106 Rule::number_literal => parse_number_literal(primary),
107 Rule::paren_expr => parse_paren_expr(primary),
108 Rule::string_literal => parse_string_literal(primary),
109 Rule::vector_selector => parse_vector_selector(primary),
110 _ => unreachable!(),
111 };
112
113 let parse_postfix = |lhs: Result<Expr, ParseError>, op: Pair<Rule>| parse_postfix(lhs, op);
114 let parse_prefix = |op, rhs| parse_prefix(op, rhs);
115 let parse_infix = |lhs, op, rhs| parse_infix(lhs, op, rhs);
116
117 PRATT_PARSER
118 .map_primary(parse_primary)
119 .map_postfix(parse_postfix)
120 .map_prefix(parse_prefix)
121 .map_infix(parse_infix)
122 .parse(pair.into_inner())
123}
124
125fn parse_postfix(lhs: Result<Expr, ParseError>, op: Pair<Rule>) -> Result<Expr, ParseError> {
126 let mut expr = lhs?;
127
128 match op.as_rule() {
129 Rule::matrix => {
130 let mut pairs = op.into_inner();
131 let range = parse_duration(pairs.next().unwrap())?;
132 Ok(Expr::MatrixSelector(MatrixSelector {
133 vector_selector: Box::new(expr),
134 range,
135 }))
136 }
137 Rule::subquery => {
138 let mut pairs = op.into_inner();
139 let range = parse_duration(pairs.next().unwrap())?;
140 let step = parse_duration(pairs.next().unwrap())?;
141 Ok(Expr::SubqueryExpr(SubqueryExpr {
142 expr: Box::new(expr),
143 at: AtModifier::None,
144 offset: Duration::default(),
145 range,
146 step,
147 }))
148 }
149 Rule::offset => {
150 let offset = parse_duration(op.into_inner().next().unwrap())?;
151 match expr {
152 Expr::VectorSelector(ref mut vs) => {
153 vs.offset = offset;
154 }
155 Expr::MatrixSelector(ref mut ms) => match ms.vector_selector.as_mut() {
156 Expr::VectorSelector(ref mut vs) => {
157 vs.offset = offset;
158 }
159 _ => return Err("invalid matrix selector".into()),
160 },
161 Expr::SubqueryExpr(ref mut sq) => {
162 sq.offset = offset;
163 }
164 _ => return Err("offset modifier must be preceded by an instant vector selector, a range vector selector, or a subquery".into()),
165 }
166 Ok(expr)
167 }
168 Rule::at => {
169 let at_modifier = parse_at_modifier(op.into_inner().next().unwrap())?;
170 match expr {
171 Expr::VectorSelector(ref mut vs) => {
172 vs.at = at_modifier;
173 }
174 Expr::MatrixSelector(ref mut ms) => match ms.vector_selector.as_mut() {
175 Expr::VectorSelector(ref mut vs) => {
176 vs.at = at_modifier;
177 }
178 _ => return Err("invalid matrix selector".into()),
179 },
180 Expr::SubqueryExpr(ref mut sq) => {
181 sq.at = at_modifier;
182 }
183 _ => return Err("@ modifier must be preceded by an instant vector selector, a range vector selector, or a subquery".into()),
184 }
185 Ok(expr)
186 }
187 _ => unreachable!(),
188 }
189}
190
191fn parse_prefix(op: Pair<Rule>, rhs: Result<Expr, ParseError>) -> Result<Expr, ParseError> {
192 match rhs? {
193 Expr::NumberLiteral(n) => match op.as_str() {
194 "+" => return Ok(Expr::NumberLiteral(NumberLiteral { value: n.value })),
195 "-" => return Ok(Expr::NumberLiteral(NumberLiteral { value: -n.value })),
196 _ => unreachable!(),
197 },
198 expr => Ok(Expr::UnaryExpr(UnaryExpr {
199 op: UnaryOp::from_str(op.as_str())?,
200 rhs: Box::new(expr),
201 })),
202 }
203}
204
205fn parse_infix(
206 lhs: Result<Expr, ParseError>,
207 op: Pair<Rule>,
208 rhs: Result<Expr, ParseError>,
209) -> Result<Expr, ParseError> {
210 let mut pairs = op.into_inner();
211 let op = BinaryOp::from_str(pairs.next().unwrap().as_str())?;
212 let mut return_bool = false;
213 let mut vector_matching: VectorMatching = VectorMatching::default();
214
215 if let Some(pair) = pairs.next() {
216 let mut pairs = pair.into_inner();
217
218 if let Rule::bool_modifier = pairs.peek().unwrap().as_rule() {
219 return_bool = true;
220 pairs.next();
221 }
222
223 while let Some(pair) = pairs.next() {
224 match pair.as_rule() {
225 Rule::on_or_ignoring_modifier => {
226 vector_matching.grouping = parse_on_or_ignoring_modifier(pair)?
227 }
228 Rule::left_or_right_modifier => {
229 vector_matching.cardinality = parse_left_or_right_modifier(pair)?
230 }
231 _ => unreachable!(),
232 }
233 }
234 }
235
236 Ok(Expr::BinaryExpr(BinaryExpr {
237 op,
238 lhs: Box::new(lhs?),
239 rhs: Box::new(rhs?),
240 return_bool,
241 vector_matching,
242 }))
243}
244
245fn parse_at_modifier(pair: Pair<Rule>) -> Result<AtModifier, ParseError> {
246 let value = pair.as_str();
247 match value {
248 "start()" => Ok(AtModifier::Start),
249 "end()" => Ok(AtModifier::End),
250 _ => Ok(AtModifier::Timestamp(value.parse::<u64>().unwrap())),
251 }
252}
253
254fn parse_duration(pair: Pair<Rule>) -> Result<Duration, ParseError> {
255 let mut duration = Duration::default();
256 let mut num = String::new();
257 let mut unit = String::new();
258
259 let add_duration = |duration: &mut Duration,
260 num: &mut String,
261 unit: &mut String|
262 -> Result<(), Box<dyn std::error::Error>> {
263 let value = num.parse::<u64>().unwrap();
264 match unit.as_str() {
265 "y" => *duration += Duration::from_secs(value * 365 * 24 * 60 * 60),
266 "w" => *duration += Duration::from_secs(value * 7 * 24 * 60 * 60),
267 "d" => *duration += Duration::from_secs(value * 24 * 60 * 60),
268 "h" => *duration += Duration::from_secs(value * 60 * 60),
269 "m" => *duration += Duration::from_secs(value * 60),
270 "s" => *duration += Duration::from_secs(value),
271 "ms" => *duration += Duration::from_millis(value),
272 _ => return Err("unknown duration unit".into()),
273 }
274 unit.clear();
275 num.clear();
276 Ok(())
277 };
278
279 for c in pair.as_str().chars() {
280 if c.is_digit(10) {
281 if !unit.is_empty() {
282 add_duration(&mut duration, &mut num, &mut unit).unwrap();
283 }
284 num.push(c);
285 } else {
286 unit.push(c);
287 }
288 }
289
290 if !unit.is_empty() {
291 add_duration(&mut duration, &mut num, &mut unit).unwrap();
292 }
293
294 Ok(duration)
295}
296
297fn parse_on_or_ignoring_modifier(pair: Pair<Rule>) -> Result<VectorMatchGrouping, ParseError> {
298 let mut pairs = pair.into_inner();
299 let modifier = pairs.next().unwrap();
300 let labels: Vec<_> = pairs.map(|s| s.as_str().to_string()).collect();
301 match modifier.as_str() {
302 "on" => Ok(VectorMatchGrouping::On(labels)),
303 "ignoring" => Ok(VectorMatchGrouping::Ignoring(labels)),
304 _ => Ok(VectorMatchGrouping::None),
305 }
306}
307
308fn parse_left_or_right_modifier(pair: Pair<Rule>) -> Result<VectorMatchCardinality, ParseError> {
309 let modifier = pair.into_inner().next().unwrap();
310 match modifier.as_str() {
311 "group_left" => Ok(VectorMatchCardinality::OneToMany),
312 "group_right" => Ok(VectorMatchCardinality::ManyToOne),
313 _ => unreachable!(),
314 }
315}
316
317fn parse_aggregate_expr(pair: Pair<Rule>) -> Result<Expr, ParseError> {
318 let mut pairs = pair.into_inner();
319 let op = AggregateOp::from_str(pairs.next().unwrap().as_str())?;
320
321 let mut modifier = match pairs.peek() {
322 Some(pair) if pair.as_rule() == Rule::aggregate_modifier => {
323 parse_aggregate_modifier(pairs.next().unwrap())?
324 }
325 _ => AggregateModifier::None,
326 };
327
328 let mut args = parse_function_args(pairs.next().unwrap())?;
329 let expr = args.pop().ok_or("missing expression".to_string())?;
330
331 if let Some(pair) = pairs.next() {
332 modifier = parse_aggregate_modifier(pair)?;
333 }
334
335 Ok(Expr::AggregateExpr(AggregateExpr {
336 op,
337 expr: Box::new(expr),
338 param: args.pop().map(Box::new),
339 modifier,
340 }))
341}
342
343fn parse_aggregate_modifier(pair: Pair<Rule>) -> Result<AggregateModifier, ParseError> {
344 let mut pairs = pair.into_inner();
345 let modifier = pairs.next().unwrap();
346 let labels: Vec<_> = pairs.map(|s| s.as_str().to_string()).collect();
347 match modifier.as_str() {
348 "by" => Ok(AggregateModifier::By(labels)),
349 "without" => Ok(AggregateModifier::Without(labels)),
350 _ => unreachable!(),
351 }
352}
353
354fn parse_function_call(pair: Pair<Rule>) -> Result<Expr, ParseError> {
355 let mut pairs = pair.into_inner();
356 let name = pairs.next().unwrap().as_str();
357 let func = FUNCTIONS
358 .iter()
359 .find(|f| f.name == name)
360 .ok_or("unknown function name")
361 .unwrap();
362
363 let args = parse_function_args(pairs.next().unwrap())?;
364 Ok(Expr::FunctionCall(FunctionCall { func, args }))
366}
367
368fn parse_function_args(pair: Pair<Rule>) -> Result<Vec<Expr>, ParseError> {
369 pair.into_inner().map(|expr| parse_expr(expr)).collect()
370}
371
372fn parse_number_literal(pair: Pair<Rule>) -> Result<Expr, ParseError> {
373 let s = pair.into_inner().next().unwrap().as_str();
374 match s {
375 _ if s.starts_with("0x") => Ok(Expr::NumberLiteral(NumberLiteral {
376 value: u64::from_str_radix(&s[2..], 16).unwrap() as f64,
377 })),
378 _ if s.starts_with("0") && s.len() > 1 && s.as_bytes()[1] != b'.' => {
379 Ok(Expr::NumberLiteral(NumberLiteral {
380 value: u64::from_str_radix(&s[1..], 8).unwrap() as f64,
381 }))
382 }
383 _ => Ok(Expr::NumberLiteral(NumberLiteral {
384 value: s.parse::<f64>().unwrap(),
385 })),
386 }
387}
388
389fn parse_paren_expr(pair: Pair<Rule>) -> Result<Expr, ParseError> {
390 Ok(Expr::ParenExpr(ParenExpr {
391 expr: Box::new(parse_expr(pair.into_inner().next().unwrap())?),
392 }))
393}
394
395fn parse_string_literal(pair: Pair<Rule>) -> Result<Expr, ParseError> {
396 Ok(Expr::StringLiteral(StringLiteral {
397 value: unescape(pair.into_inner().next().unwrap().as_str()),
398 }))
399}
400
401fn parse_vector_selector(pair: Pair<Rule>) -> Result<Expr, ParseError> {
402 let mut pairs = pair.into_inner();
403
404 let metric = match pairs.peek().unwrap().as_rule() {
405 Rule::metric => pairs.next().unwrap().as_str().to_string(),
406 _ => String::new(),
407 };
408
409 let label_matchers = match pairs.next() {
410 Some(pair) => pair
411 .into_inner()
412 .map(|pair| {
413 let mut pairs = pair.into_inner();
414 let name = pairs.next().unwrap().as_str().to_string();
415 let op = MatchOp::from_str(pairs.next().unwrap().as_str()).unwrap();
416 let value = pairs.next().unwrap().as_str().to_string();
417 LabelMatcher { op, name, value }
418 })
419 .collect(),
420 None => vec![],
421 };
422
423 Ok(Expr::VectorSelector(VectorSelector {
424 metric,
425 label_matchers,
426 original_offset: Duration::default(),
427 offset: Duration::default(),
428 at: AtModifier::None,
429 }))
430}
431
432fn unescape(s: &str) -> String {
433 let mut string = String::new();
434 let mut chars = s.chars().peekable();
435
436 while let Some(current) = chars.next() {
437 if current == '\\' && chars.peek().is_some() {
438 string.push(match chars.next().unwrap() {
439 '\\' => '\\',
440 '"' => '"',
441 '\'' => '\'',
442 '/' => '/',
443 'a' => char::from(0x07),
444 'b' => char::from(0x08),
445 'f' => char::from(0x0C),
446 'n' => '\n',
447 'r' => '\r',
448 't' => '\t',
449 'v' => char::from(0x0B),
450 'x' => u8::from_str_radix(&collect_chars(&mut chars, 2), 16).unwrap() as char,
451 'u' => {
452 char::from_u32(u32::from_str_radix(&collect_chars(&mut chars, 4), 16).unwrap())
453 .unwrap()
454 }
455 'U' => {
456 char::from_u32(u32::from_str_radix(&collect_chars(&mut chars, 8), 16).unwrap())
457 .unwrap()
458 }
459 d if d.is_digit(8) => char::from(
460 (d as u8 - 0x30) * 64
461 + u8::from_str_radix(&collect_chars(&mut chars, 2), 8).unwrap(),
462 ),
463 c => c,
464 });
465 } else {
466 string.push(current);
467 }
468 }
469
470 string
471}
472
473fn collect_chars(chars: &mut std::iter::Peekable<std::str::Chars>, n: usize) -> String {
474 (0..n).filter_map(|_| chars.next()).collect()
475}