1use core::result;
2use std::{collections::HashMap, hash::BuildHasher, num::ParseFloatError, str::FromStr};
3
4use chrono::DateTime;
5use miette::SourceSpan;
6use pest::iterators::{Pair, Pairs};
7use regex::Regex;
8
9use crate::{
10 ParseError,
11 errors::pair_to_source_span,
12 linker::{
13 AlignFunction, ComputeFunction, Function, FunctionId, GroupFunction, Module, ModuleId,
14 },
15 query::{
16 Aggregate, Align, As, BucketBy, Cmp, DirectiveValue, Directives, Expr, Filter,
17 FilterOrIfDef, GroupBy, Mapping, MetricId, ParamDeclaration, ParamType, ParamValue, Params,
18 Query, RelativeTime, Source, StringFragment, TagExtend, TagType, TerminalParamType, Time,
19 TimeRange, TimeUnit, WarningReason, Warnings,
20 },
21 stdlib::STDLIB,
22 tags::TagValue,
23 types::{BucketSpec, BucketType, ConversionMethod, Dataset, Metric, Parameterized},
24};
25
26#[cfg(test)]
27mod tests;
28
29mod mpl_parser_impl {
33 #![allow(missing_docs)]
34 use pest_derive::Parser;
35
36 #[derive(Parser)]
40 #[grammar = "mpl.pest"]
41 pub struct MPLParser;
42}
43pub use mpl_parser_impl::{MPLParser, Rule};
44
45const SYSTEM_PARAM_PREFIX: &str = "__";
46
47type Result<T> = std::result::Result<T, ParseError>;
48
49trait PairsHelper<'i, R>
50where
51 R: pest::RuleType,
52{
53 fn n(&mut self) -> Result<Pair<'i, R>>;
54 fn assert_empty(&mut self) -> Result<()>;
55}
56
57impl<'i> PairsHelper<'i, Rule> for Pairs<'i, Rule> {
58 fn n(&mut self) -> Result<Pair<'i, Rule>> {
59 self.peek()
60 .map(|p| pair_to_source_span(&p))
61 .ok_or_else(|| ParseError::EOF {
62 span: miette::SourceSpan::new(0.into(), 0),
63 })
64 .and_then(|span| self.next().ok_or(ParseError::EOF { span }))
65 }
66 fn assert_empty(&mut self) -> Result<()> {
67 if !Pairs::is_empty(self) {
68 let first = self.peek();
69 let span = first.map_or_else(
70 || miette::SourceSpan::new(0.into(), 0),
71 |p| pair_to_source_span(&p),
72 );
73 return Err(ParseError::UnexpectedTokens {
74 span,
75 rules: self.map(|p| p.as_rule()).collect(),
76 });
77 }
78 Ok(())
79 }
80}
81
82trait PairHelper<R>
83where
84 R: pest::RuleType,
85{
86 fn assert_type(&self, expected: R) -> Result<()>;
87}
88
89impl PairHelper<Rule> for Pair<'_, Rule> {
90 fn assert_type(&self, expected: Rule) -> Result<()> {
91 if self.as_rule() != expected {
92 return Err(ParseError::Unexpected {
93 span: pair_to_source_span(self),
94 rule: self.as_rule(),
95 expected: vec![expected],
96 });
97 }
98 Ok(())
99 }
100}
101
102fn unescape_and_trim(data: &str, delim: char) -> String {
103 unescape(
104 data.trim_start_matches(delim).trim_end_matches(delim),
105 delim,
106 )
107}
108
109fn unescape(data: &str, delim: char) -> String {
110 let mut escaped = false;
111 let mut res = String::with_capacity(data.len());
112 for c in data.chars() {
113 if escaped {
114 escaped = false;
115 match c {
116 'r' => res.push('\r'),
117 'n' => res.push('\n'),
118 't' => res.push('\t'),
119 'b' => res.push('\x08'),
120 'f' => res.push('\x0C'),
121 '\\' => res.push('\\'),
122 '$' => res.push('$'),
123 c if c == delim => res.push(delim),
124 _ => {
125 res.push('\\');
126 res.push(c);
127 }
128 }
129 } else if c == '\\' {
130 escaped = true;
131 } else {
132 res.push(c);
133 }
134 }
135 res
136}
137
138fn parse_ident(source: &Pair<'_, Rule>) -> Result<String> {
139 match source.as_rule() {
140 Rule::plain_ident => Ok(source.as_str().to_string()),
141 Rule::escaped_ident => Ok(unescape_and_trim(source.as_str(), '`')),
142 rule => Err(ParseError::Unexpected {
143 span: pair_to_source_span(source),
144 rule,
145 expected: vec![Rule::plain_ident, Rule::escaped_ident],
146 }),
147 }
148}
149
150fn resolve_param<'p>(source: &Pair<'_, Rule>, state: &'p State) -> Result<&'p ParamDeclaration> {
151 let param = match source.as_rule() {
152 Rule::plain_ident => source.as_str().to_string(),
153 Rule::escaped_ident => unescape_and_trim(source.as_str(), '`'),
154 rule => {
155 return Err(ParseError::Unexpected {
156 span: pair_to_source_span(source),
157 rule,
158 expected: vec![Rule::plain_ident],
159 });
160 }
161 };
162
163 state
164 .params
165 .iter()
166 .find(|p| p.name == param)
167 .ok_or(ParseError::UndefinedParam {
168 span: pair_to_source_span(source),
169 param,
170 })
171}
172
173fn parse_source_ident(source: &Pair<'_, Rule>) -> Result<String> {
174 match source.as_rule() {
175 Rule::plain_ident => Ok(source.as_str().to_string()),
176 Rule::escaped_ident => Ok(unescape_and_trim(source.as_str(), '`').clone()),
177 rule => Err(ParseError::Unexpected {
178 span: pair_to_source_span(source),
179 rule,
180 expected: vec![Rule::ident],
181 }),
182 }
183}
184
185fn parse_source_ident_param(
186 source: Pair<'_, Rule>,
187 state: &State,
188) -> Result<Parameterized<String>> {
189 match source.as_rule() {
190 Rule::plain_ident => Ok(Parameterized::Concrete(source.as_str().to_string())),
191 Rule::escaped_ident => Ok(Parameterized::Concrete(
192 unescape_and_trim(source.as_str(), '`').clone(),
193 )),
194 Rule::param_ident => {
195 let span = pair_to_source_span(&source);
196 let mut inner = source.into_inner();
197 let next = inner.n()?;
198 let param = resolve_param(&next, state)?;
199 Ok(Parameterized::Param {
200 span,
201 param: param.clone(),
202 })
203 }
204 rule => Err(ParseError::Unexpected {
205 span: pair_to_source_span(&source),
206 rule,
207 expected: vec![Rule::ident, Rule::param_ident],
208 }),
209 }
210}
211
212fn parse_param_ident(source: Pair<'_, Rule>) -> Result<String> {
213 match source.as_rule() {
214 Rule::param_ident => {
215 let mut inner = source.into_inner();
216 let next = inner.n()?;
217 match next.as_rule() {
218 Rule::plain_ident => Ok(next.as_str().to_string()),
219 rule => Err(ParseError::Unexpected {
220 span: pair_to_source_span(&next),
221 rule,
222 expected: vec![Rule::plain_ident],
223 }),
224 }
225 }
226 rule => Err(ParseError::Unexpected {
227 span: pair_to_source_span(&source),
228 rule,
229 expected: vec![Rule::param_ident],
230 }),
231 }
232}
233
234fn parse_dataset(source: Pair<Rule>, state: &State) -> Result<Parameterized<Dataset>> {
235 source.assert_type(Rule::dataset)?;
236 let mut inner = source.into_inner();
237
238 let source = inner.n()?;
239 let dataset = parse_source_ident_param(source, state)?.map_concrete(Dataset::new);
240 Ok(dataset)
241}
242
243fn parse_metric_name(source: Pair<Rule>) -> Result<Metric> {
244 source.assert_type(Rule::metric_name)?;
245 let mut inner = source.into_inner();
246
247 let source = inner.n()?;
248 let metric = Metric::try_from(parse_source_ident(&source)?)?;
249 Ok(metric)
250}
251
252fn parse_metric_id(source: Pair<Rule>, state: &State) -> Result<MetricId> {
253 source.assert_type(Rule::metric_id)?;
254 let mut inner = source.into_inner();
255 let dataset = parse_dataset(inner.n()?, state)?;
256 let metric = parse_metric_name(inner.n()?)?;
257 inner.assert_empty()?;
258 Ok(MetricId { dataset, metric })
259}
260
261fn parse_parameterized_relative_time(
262 source: Pair<Rule>,
263 state: &State,
264) -> Result<Parameterized<RelativeTime>> {
265 source.assert_type(Rule::time_relative_parameterized)?;
266 let mut inner = source.into_inner();
267
268 let next = inner.n()?;
269
270 if matches!(next.as_rule(), Rule::param_ident) {
272 let span = pair_to_source_span(&next);
273 let mut inner = next.into_inner();
274 let next = inner.n()?;
275 let param = resolve_param(&next, state)?;
276 return Ok(Parameterized::Param {
277 span,
278 param: param.clone(),
279 });
280 }
281
282 parse_relative_time_inner(inner, &next).map(Parameterized::Concrete)
283}
284
285fn parse_relative_time(source: Pair<Rule>) -> Result<RelativeTime> {
286 source.assert_type(Rule::time_relative)?;
287 let mut inner = source.into_inner();
288 let next = inner.n()?;
289 parse_relative_time_inner(inner, &next)
290}
291
292fn parse_relative_time_inner(
293 mut inner: Pairs<'_, Rule>,
294 next: &Pair<Rule>,
295) -> Result<RelativeTime> {
296 let value = next.as_str().parse::<u64>()?;
297 let unit = inner.n()?;
298 let unit = match unit.as_rule() {
299 Rule::time_unit_ms => TimeUnit::Millisecond,
300 Rule::time_unit_second => TimeUnit::Second,
301 Rule::time_unit_minute => TimeUnit::Minute,
302 Rule::time_unit_hour => TimeUnit::Hour,
303 Rule::time_unit_day => TimeUnit::Day,
304 Rule::time_unit_week => TimeUnit::Week,
305 Rule::time_unit_month => TimeUnit::Month,
306 Rule::time_unit_year => TimeUnit::Year,
307 rule => {
308 return Err(ParseError::Unexpected {
309 span: pair_to_source_span(&unit),
310 rule,
311 expected: vec![
312 Rule::time_unit_ms,
313 Rule::time_unit_second,
314 Rule::time_unit_minute,
315 Rule::time_unit_hour,
316 Rule::time_unit_day,
317 Rule::time_unit_week,
318 Rule::time_unit_month,
319 Rule::time_unit_year,
320 ],
321 });
322 }
323 };
324
325 Ok(RelativeTime { value, unit })
326}
327
328fn parse_time(source: Pair<Rule>) -> Result<Time> {
329 match source.as_rule() {
330 Rule::time_relative => Ok(Time::Relative(parse_relative_time(source)?)),
331 Rule::time_timestamp => Ok(Time::Timestamp(source.as_str().parse()?)),
332 Rule::time_rfc_3339 => Ok(Time::RFC3339(DateTime::parse_from_rfc3339(
333 source.as_str(),
334 )?)),
335 Rule::time_modifier => Ok(Time::Modifier(source.as_str().to_string())),
336 rule => Err(ParseError::Unexpected {
337 span: pair_to_source_span(&source),
338 rule,
339 expected: vec![
340 Rule::time_relative,
341 Rule::time_timestamp,
342 Rule::time_rfc_3339,
343 Rule::time_modifier,
344 ],
345 }),
346 }
347}
348
349fn parse_time_range(source: Pair<Rule>) -> Result<TimeRange> {
350 source.assert_type(Rule::time_range)?;
351 let mut inner = source.into_inner();
352
353 let start = parse_time(inner.n()?)?;
354 let end = if inner.is_empty() {
355 None
356 } else {
357 Some(parse_time(inner.n()?)?)
358 };
359 inner.assert_empty()?;
360 Ok(TimeRange { start, end })
361}
362
363pub(crate) fn parse_source(source: Pair<Rule>, state: &State) -> Result<(Source, Option<As>)> {
364 source.assert_type(Rule::source)?;
365 let mut inner = source.into_inner();
366
367 let metric_id = parse_metric_id(inner.n()?, state)?;
368 let next = inner.next();
369
370 match next {
371 Some(next) if next.as_rule() == Rule::r#as => {
372 let as_ = parse_as(next)?;
373 inner.assert_empty()?;
374 Ok((
375 Source {
376 metric_id,
377 time: None,
378 },
379 Some(as_),
380 ))
381 }
382 Some(next) if next.as_rule() == Rule::time_range => {
383 let time = Some(parse_time_range(next)?);
384 if let Some(next) = inner.next() {
385 let as_ = parse_as(next)?;
386 inner.assert_empty()?;
387 Ok((Source { metric_id, time }, Some(as_)))
388 } else {
389 Ok((Source { metric_id, time }, None))
390 }
391 }
392 Some(next) => Err(ParseError::Unexpected {
393 span: pair_to_source_span(&next),
394 rule: next.as_rule(),
395 expected: vec![Rule::r#as, Rule::time_range],
396 }),
397 None => Ok((
398 Source {
399 metric_id,
400 time: None,
401 },
402 None,
403 )),
404 }
405}
406
407fn parse_cmp<'input>(source: &Pair<'input, Rule>) -> Result<&'input str> {
408 source.assert_type(Rule::cmp)?;
409 Ok(source.as_str())
410}
411fn parse_cmp_re<'input>(source: &Pair<'input, Rule>) -> Result<&'input str> {
412 source.assert_type(Rule::cmp_re)?;
413 Ok(source.as_str())
414}
415
416#[derive(Debug, Clone, PartialEq, Copy)]
417enum Number {
418 Int(i64),
419 Float(f64),
420}
421impl Number {
422 #[allow(clippy::cast_precision_loss)]
424 fn as_f64(self) -> f64 {
425 match self {
426 Number::Int(value) => value as f64,
427 Number::Float(value) => value,
428 }
429 }
430}
431
432fn parse_int(source: &Pair<Rule>) -> Result<i64> {
433 source.assert_type(Rule::int)?;
434 let res = source.as_str().trim().parse()?;
435 Ok(res)
436}
437
438fn parse_float(next: &Pair<Rule>) -> Result<f64> {
439 match next.as_rule() {
440 Rule::float => Ok(next.as_str().parse()?),
441 Rule::inf => match next.as_str() {
442 "inf" | "+inf" => Ok(f64::INFINITY),
443 "-inf" => Ok(f64::NEG_INFINITY),
444 _ => Err(ParseError::Unexpected {
445 span: pair_to_source_span(next),
446 rule: next.as_rule(),
447 expected: vec![],
448 }),
449 },
450 rule => Err(ParseError::Unexpected {
451 span: pair_to_source_span(next),
452 rule,
453 expected: vec![Rule::inf, Rule::float],
454 }),
455 }
456}
457
458fn parse_number(source: Pair<Rule>) -> Result<Number> {
459 source.assert_type(Rule::number)?;
460 let mut inner = source.into_inner();
461 let next = inner.n()?;
462 let res = match next.as_rule() {
463 Rule::int => Ok(Number::Int(parse_int(&next)?)),
464 Rule::float | Rule::inf => Ok(Number::Float(parse_float(&next)?)),
465 rule => Err(ParseError::Unexpected {
466 span: pair_to_source_span(&next),
467 rule,
468 expected: vec![Rule::int, Rule::inf, Rule::float],
469 }),
470 };
471 inner.assert_empty()?;
472 res
473}
474
475fn parse_directive_value(source: Pair<Rule>) -> Result<DirectiveValue> {
476 source.assert_type(Rule::r#const)?;
477 let mut inner = source.into_inner();
478 let next = inner.n()?;
479 match next.as_rule() {
480 Rule::string => Ok(DirectiveValue::String(unescape_and_trim(
481 next.as_str(),
482 '"',
483 ))),
484 Rule::int => Ok(DirectiveValue::Int(parse_int(&next)?)),
485 Rule::float | Rule::inf => Ok(DirectiveValue::Float(parse_float(&next)?)),
486 Rule::bool => Ok(DirectiveValue::Bool(next.as_str().to_string().parse()?)),
487 rule => Err(ParseError::Unexpected {
488 span: pair_to_source_span(&next),
489 rule,
490 expected: vec![Rule::string, Rule::int, Rule::float, Rule::inf, Rule::bool],
491 }),
492 }
493}
494fn parse_param_native_type(state: &mut State, source: &Pair<Rule>) -> Result<TerminalParamType> {
495 source.assert_type(Rule::param_native_type)?;
496 let span = pair_to_source_span(source);
497 match source.as_str() {
498 "Dataset" => Ok(TerminalParamType::Dataset),
499 "Duration" => Ok(TerminalParamType::Duration),
500 "duration" => {
501 state.warnings.push_span(span, WarningReason::OldDuration);
502 Ok(TerminalParamType::Duration)
503 }
504 "Regex" => Ok(TerminalParamType::Regex),
505 _ => Err(ParseError::Unexpected {
506 span: pair_to_source_span(source),
507 rule: Rule::param_type,
508 expected: vec![Rule::param_type],
509 }),
510 }
511}
512
513fn parse_param_type(state: &mut State, source: Pair<Rule>) -> Result<ParamType> {
514 source.assert_type(Rule::param_type)?;
515 let mut inner = source.into_inner();
516 let next = inner.n()?;
517 let r = match next.as_rule() {
518 Rule::tag_type => ParamType::Terminal(TerminalParamType::Tag(parse_tag_type(&next)?)),
519 Rule::param_native_type => ParamType::Terminal(parse_param_native_type(state, &next)?),
520 Rule::optional_type => {
521 let mut inner = next.into_inner();
522 let next = inner.n()?;
523 let r = match next.as_rule() {
524 Rule::tag_type => {
525 ParamType::Optional(TerminalParamType::Tag(parse_tag_type(&next)?))
526 }
527 Rule::param_native_type => match parse_param_native_type(state, &next)? {
528 TerminalParamType::Duration | TerminalParamType::Dataset => {
529 return Err(ParseError::Unexpected {
530 span: pair_to_source_span(&next),
531 rule: Rule::param_native_type,
532 expected: vec![Rule::tag_type],
533 });
534 }
535 TerminalParamType::Regex => ParamType::Optional(TerminalParamType::Regex),
536 TerminalParamType::Tag(tag_type) => {
537 ParamType::Optional(TerminalParamType::Tag(tag_type))
538 }
539 },
540 _ => {
541 return Err(ParseError::Unexpected {
542 span: pair_to_source_span(&next),
543 rule: Rule::param_type,
544 expected: vec![
545 Rule::tag_type,
546 Rule::param_native_type,
547 Rule::optional_type,
548 ],
549 });
550 }
551 };
552 inner.assert_empty()?;
553 r
554 }
555 _ => {
556 return Err(ParseError::Unexpected {
557 span: pair_to_source_span(&next),
558 rule: Rule::param_type,
559 expected: vec![Rule::tag_type, Rule::param_native_type, Rule::optional_type],
560 });
561 }
562 };
563 inner.assert_empty()?;
564 Ok(r)
565}
566
567fn parse_regex(source: &Pair<'_, Rule>) -> Result<Regex> {
568 source.assert_type(Rule::regex)?;
569 Ok(regex::Regex::new(&unescape_and_trim(
570 &source.as_str()[1..],
571 '/',
572 ))?)
573}
574
575fn parse_array(source: Pair<Rule>, state: &State) -> Result<Vec<Expr>> {
576 source.assert_type(Rule::array)?;
577 let inner = source.into_inner();
578 let mut res = Vec::new();
579 for next in inner {
580 res.push(parse_const(next, state)?);
581 }
582 Ok(res)
583}
584
585fn parse_const(source: Pair<Rule>, state: &State) -> Result<Expr> {
586 let mut inner = source.into_inner();
587 let next = inner.n()?;
588
589 match next.as_rule() {
591 Rule::string => parse_string(next, state),
592 Rule::float | Rule::inf => Ok(Expr::Const(TagValue::Float(parse_float(&next)?))),
593 Rule::int => Ok(Expr::Const(TagValue::Int(parse_int(&next)?))),
594 Rule::bool => Ok(Expr::Const(TagValue::Bool(
595 next.as_str().to_string().parse()?,
596 ))),
597 Rule::array => Ok(Expr::Array(parse_array(next, state)?)),
598 rule => Err(ParseError::Unexpected {
599 span: pair_to_source_span(&next),
600 rule,
601 expected: vec![Rule::string, Rule::float, Rule::inf, Rule::int, Rule::bool],
602 }),
603 }
604}
605
606fn parse_expr(source: Pair<Rule>, state: &State) -> Result<Expr> {
607 source.assert_type(Rule::expr)?;
608 let mut inner = source.into_inner();
609 let next = inner.n()?;
610
611 match next.as_rule() {
612 Rule::param_ident => {
613 let span = pair_to_source_span(&next);
615 let mut inner = next.into_inner();
616 let next = inner.n()?;
617 let param = resolve_param(&next, state)?;
618 Ok(Expr::Param {
619 span,
620 param: param.clone(),
621 })
622 }
623 Rule::r#const => parse_const(next, state),
624 Rule::plain_ident | Rule::escaped_ident => Ok(Expr::Tag(parse_ident(&next)?)),
625 _ => Err(ParseError::Unexpected {
626 span: pair_to_source_span(&next),
627 rule: next.as_rule(),
628 expected: vec![Rule::param_ident, Rule::r#const, Rule::ident],
629 }),
630 }
631}
632
633fn parse_string(source: Pair<Rule>, state: &State) -> Result<Expr> {
634 source.assert_type(Rule::string)?;
635 let inner = source.into_inner();
636
637 let mut parts = Vec::new();
638 for part in inner {
639 part.assert_type(Rule::string_inner)?;
640 let mut inner_part = part.into_inner();
641 let next = inner_part.n()?;
642 inner_part.assert_empty()?;
643 match next.as_rule() {
644 Rule::string_chars => parts.push(StringFragment::Text(unescape(next.as_str(), '"'))),
645 Rule::expr => parts.push(StringFragment::Expr(parse_expr(next, state)?)),
646 _ => {
647 return Err(ParseError::Unexpected {
648 span: pair_to_source_span(&next),
649 rule: next.as_rule(),
650 expected: vec![Rule::string, Rule::expr],
651 });
652 }
653 }
654 }
655 if parts
656 .iter()
657 .all(|part| matches!(part, StringFragment::Text(_)))
658 {
659 return Ok(Expr::Const(TagValue::String(
660 parts
661 .into_iter()
662 .map(|part| match part {
663 StringFragment::Text(text) => text,
664 StringFragment::Expr(_) => {
665 unreachable!("we tested that all fragments are Text")
666 }
667 })
668 .collect::<String>()
669 .try_into()?,
670 )));
671 }
672 Ok(Expr::String(parts))
673}
674
675fn parse_value_filter(field: String, source: Pair<Rule>, state: &State) -> Result<Filter> {
676 source.assert_type(Rule::value_filter)?;
677 let mut inner = source.into_inner();
678 let operator_pair = inner.n()?;
679 let operator = parse_cmp(&operator_pair)?;
680 let next = inner.n()?;
681 let value_span = pair_to_source_span(&next);
682
683 let value = parse_expr(next, state)?;
684
685 let rhs = match operator {
686 "==" => Cmp::Eq(value),
687 "!=" => Cmp::Ne(value),
688 ">" => Cmp::Gt(value),
689 ">=" => Cmp::Ge(value),
690 "<" => Cmp::Lt(value),
691 "<=" => Cmp::Le(value),
692 "in" => match value {
693 Expr::Const(TagValue::Array(_)) | Expr::Array(_) => Cmp::In(value),
694 Expr::Param { ref param, .. }
695 if param.typ() == TerminalParamType::Tag(TagType::Array) =>
696 {
697 Cmp::In(value)
698 }
699 _ => {
700 return Err(ParseError::InRequiresArray { span: value_span });
701 }
702 },
703 other => {
704 return Err(ParseError::UnsupportedTagComparison {
705 span: pair_to_source_span(&operator_pair),
706 op: other.to_string(),
707 });
708 }
709 };
710 Ok(Filter::Cmp { field, rhs })
711}
712
713#[derive(Debug, thiserror::Error)]
714pub enum ParseParamError {
715 #[error("Failed to parse: {0}")]
716 Parse(#[from] ParseError),
717 #[error("Failed to param as bool: {0}")]
718 ParseBool(<bool as FromStr>::Err),
719 #[error("Failed to parse as float: {0}")]
720 ParseFloat(#[from] ParseFloatError),
721 #[error("Failed to parse identifier: {0}")]
722 SharedStringError(#[from] strumbra::Error),
723 #[error(
724 "Param is declared as type {declared_typ}, but the provided type was parsed as `{rule:?}`"
725 )]
726 TypeMismatch { declared_typ: ParamType, rule: Rule },
727 #[error("None Type Params are not supported")]
728 NoneParam,
729 #[error("Unsupported Array element")]
730 UnsupportedArrayElement,
731}
732
733fn expr_to_array(e: Expr) -> result::Result<TagValue, ParseParamError> {
734 match e {
735 Expr::Const(tag_value) => Ok(tag_value),
736 Expr::Param { .. } | Expr::String(_) | Expr::Tag(_) => {
737 Err(ParseParamError::UnsupportedArrayElement)
738 }
739 Expr::Array(exprs) => exprs
740 .into_iter()
741 .map(expr_to_array)
742 .collect::<result::Result<_, ParseParamError>>()
743 .map(TagValue::Array),
744 }
745}
746
747pub(crate) fn parse_param_value(
748 param: &ParamDeclaration,
749 mut source: Pairs<'_, Rule>,
750) -> result::Result<ParamValue, ParseParamError> {
751 let next = source.n()?;
752 next.assert_type(Rule::param_value)?;
753 let mut inner = next.into_inner();
754 let next = inner.n()?;
755
756 match param.typ() {
757 TerminalParamType::Dataset => match next.as_rule() {
758 Rule::plain_ident | Rule::escaped_ident => {
759 Ok(ParamValue::Dataset(Dataset::new(parse_ident(&next)?)))
760 }
761 rule => Err(ParseParamError::TypeMismatch {
762 declared_typ: param.typ,
763 rule,
764 }),
765 },
766 TerminalParamType::Duration => match next.as_rule() {
767 Rule::time_relative => Ok(ParamValue::Duration(parse_relative_time(next)?)),
768 rule => Err(ParseParamError::TypeMismatch {
769 declared_typ: param.typ,
770 rule,
771 }),
772 },
773 TerminalParamType::Regex => match next.as_rule() {
774 Rule::regex => Ok(ParamValue::Regex(parse_regex(&next)?.into())),
775 rule => Err(ParseParamError::TypeMismatch {
776 declared_typ: param.typ,
777 rule,
778 }),
779 },
780 TerminalParamType::Tag(TagType::String) => Ok(ParamValue::String(unescape_and_trim(
782 const_type(next, Rule::string, param.typ)?.as_str(),
783 '"',
784 ))),
785 TerminalParamType::Tag(TagType::Int) => Ok(ParamValue::Int(parse_int(&const_type(
786 next,
787 Rule::int,
788 param.typ,
789 )?)?)),
790 TerminalParamType::Tag(TagType::Array) => {
791 let state = State {
792 params: Vec::new(),
793 directives: HashMap::new(),
794 warnings: Warnings::new(),
795 };
796 let a = parse_array(const_type(next, Rule::array, param.typ)?, &state)?;
797 let a = a
798 .into_iter()
799 .map(expr_to_array)
800 .collect::<result::Result<_, ParseParamError>>()?;
801 Ok(ParamValue::Array(a))
802 }
803 TerminalParamType::Tag(TagType::Float) => {
804 let declared_typ = param.typ;
805 if next.as_rule() != Rule::r#const {
806 return Err(ParseParamError::TypeMismatch {
807 declared_typ,
808 rule: next.as_rule(),
809 });
810 }
811 let mut inner = next.into_inner();
812 let next = inner.n()?;
813 match next.as_rule() {
814 Rule::float => Ok(ParamValue::Float(next.as_str().parse()?)),
815 Rule::inf if next.as_str() == "inf" || next.as_str() == "+inf" => {
816 Ok(ParamValue::Float(f64::INFINITY))
817 }
818 Rule::inf if next.as_str() == "-inf" => Ok(ParamValue::Float(f64::NEG_INFINITY)),
819 _ => Err(ParseParamError::TypeMismatch {
820 declared_typ,
821 rule: next.as_rule(),
822 }),
823 }
824 }
825 TerminalParamType::Tag(TagType::Bool) => Ok(ParamValue::Bool(
826 const_type(next, Rule::bool, param.typ)?
827 .as_str()
828 .parse()
829 .map_err(ParseParamError::ParseBool)?,
830 )),
831 TerminalParamType::Tag(TagType::Null) => Err(ParseParamError::NoneParam),
832 }
833}
834
835fn const_type(
836 src: Pair<Rule>,
837 rule_type: Rule,
838 declared_typ: ParamType,
839) -> result::Result<Pair<Rule>, ParseParamError> {
840 if src.as_rule() != Rule::r#const {
841 return Err(ParseParamError::TypeMismatch {
842 declared_typ,
843 rule: src.as_rule(),
844 });
845 }
846 let mut inner = src.into_inner();
847 let next = inner.n()?;
848 if next.as_rule() != rule_type {
849 return Err(ParseParamError::TypeMismatch {
850 declared_typ,
851 rule: next.as_rule(),
852 });
853 }
854 Ok(next)
855}
856
857fn parse_regex_filter(field: String, source: Pair<Rule>) -> Result<Filter> {
858 source.assert_type(Rule::regex_filter)?;
859 let mut inner = source.into_inner();
860 let operator_pair = inner.n()?;
861 let operator = parse_cmp_re(&operator_pair)?;
862 let rhs = match operator {
863 "==" => Cmp::RegEx(Parameterized::Concrete(parse_regex(&inner.n()?)?.into())),
865 "!=" => Cmp::RegExNot(Parameterized::Concrete(parse_regex(&inner.n()?)?.into())),
866 other => {
867 return Err(ParseError::UnsupportedRegexpComparison {
868 span: pair_to_source_span(&operator_pair),
869 op: other.to_string(),
870 });
871 }
872 };
873 inner.assert_empty()?;
874 Ok(Filter::Cmp { field, rhs })
875}
876
877fn parse_tag_type(source: &Pair<Rule>) -> Result<TagType> {
878 source.assert_type(Rule::tag_type)?;
879 let tpe = source.as_str();
880 match tpe {
881 "array" => Ok(TagType::Array),
882 "string" => Ok(TagType::String),
883 "int" => Ok(TagType::Int),
884 "float" => Ok(TagType::Float),
885 "bool" => Ok(TagType::Bool),
886 other => Err(ParseError::InvalidTagType {
887 span: pair_to_source_span(source),
888 tpe: other.to_string(),
889 }),
890 }
891}
892
893fn parse_is_filter(field: String, source: Pair<Rule>) -> Result<Filter> {
894 source.assert_type(Rule::is_filter)?;
895 let mut inner = source.into_inner();
896 let operator = inner.n()?;
897 operator.assert_type(Rule::kw_is)?;
898 let tpe = parse_tag_type(&inner.n()?)?;
899 let rhs = Cmp::Is(tpe);
900 inner.assert_empty()?;
901 Ok(Filter::Cmp { field, rhs })
902}
903
904fn parse_filter_atom(source: Pair<Rule>, state: &State) -> Result<Filter> {
905 source.assert_type(Rule::filter_atom)?;
906 let mut inner = source.into_inner();
907
908 let next = inner.n()?;
909 let field = parse_ident(&next)?;
910
911 let next = inner.n()?;
912 let res = match next.as_rule() {
913 Rule::regex_filter => parse_regex_filter(field, next),
914 Rule::value_filter => parse_value_filter(field, next, state),
915 Rule::is_filter => parse_is_filter(field, next),
916 rule => Err(ParseError::Unexpected {
917 span: pair_to_source_span(&next),
918 rule,
919 expected: vec![Rule::regex_filter, Rule::value_filter, Rule::is_filter],
920 }),
921 }?;
922
923 inner.assert_empty()?;
924 Ok(res)
925}
926
927fn parse_filter_clause(source: Pair<'_, Rule>, state: &State) -> Result<Filter> {
928 source.assert_type(Rule::filter_clause)?;
929 let mut inner = source.into_inner();
930 let next = inner.n()?;
931 let res = match next.as_rule() {
932 Rule::filter_atom => parse_filter_atom(next, state),
933 Rule::filter_or => parse_or(next, state),
934 rule => Err(ParseError::Unexpected {
935 span: pair_to_source_span(&next),
936 rule,
937 expected: vec![Rule::filter_atom, Rule::filter_or],
938 }),
939 }?;
940
941 inner.assert_empty()?;
942 Ok(res)
943}
944
945fn parse_filter_not(source: Pair<'_, Rule>, state: &State) -> Result<Filter> {
946 source.assert_type(Rule::filter_not)?;
947 let mut inner = source.into_inner();
948 let next = inner.n()?;
949 let res = if next.as_rule() == Rule::kw_not {
950 Filter::Not(Box::new(parse_filter_clause(inner.n()?, state)?))
951 } else {
952 parse_filter_clause(next, state)?
953 };
954 inner.assert_empty()?;
955 Ok(res)
956}
957fn parse_and(source: Pair<Rule>, state: &State) -> Result<Filter> {
958 source.assert_type(Rule::filter_and)?;
959 let inner = source.into_inner();
960 let mut res = inner
961 .into_iter()
962 .map(|source| parse_filter_not(source, state))
963 .collect::<Result<Vec<_>>>()?;
964 if res.len() == 1 {
965 res.pop().ok_or(ParseError::Unreachable(
966 "len 1 filter should never be empty",
967 ))
968 } else {
969 Ok(Filter::And(res))
970 }
971}
972fn parse_or(source: Pair<Rule>, state: &State) -> Result<Filter> {
973 source.assert_type(Rule::filter_or)?;
974 let inner = source.into_inner();
975 let mut res = inner
976 .into_iter()
977 .map(|source| parse_and(source, state))
978 .collect::<Result<Vec<_>>>()?;
979 if res.len() == 1 {
980 res.pop().ok_or(ParseError::Unreachable(
981 "len 1 filter should never be empty",
982 ))
983 } else {
984 Ok(Filter::Or(res))
985 }
986}
987
988pub(crate) fn parse_filter(source: Pair<Rule>, state: &State) -> Result<Filter> {
989 source.assert_type(Rule::filter_rule)?;
990 let mut inner = source.into_inner();
991
992 let keyword = inner.n()?;
993 keyword.assert_type(Rule::pipe_keyword)?;
994
995 parse_where_part(&mut inner, state)
996}
997
998fn parse_where_part(source: &mut Pairs<Rule>, state: &State) -> Result<Filter> {
999 let _filter_kw = source.n()?; let next = source.n()?;
1001 parse_or(next, state)
1002 }
1007
1008pub(crate) fn parse_ifdef(
1009 source: Pair<Rule>,
1010 state: &State,
1011) -> Result<(ParamDeclaration, Filter, Option<Filter>)> {
1012 source.assert_type(Rule::ifdef_rule)?;
1013 let mut inner = source.into_inner();
1014
1015 let keyword = inner.n()?;
1016 keyword.assert_type(Rule::pipe_keyword)?;
1017
1018 let kw_ifdef = inner.n()?;
1019 kw_ifdef.assert_type(Rule::kw_ifdef)?;
1020
1021 let param = inner.n()?;
1022 let span = pair_to_source_span(¶m);
1023 let param = if matches!(param.as_rule(), Rule::param_ident) {
1024 let mut inner = param.into_inner();
1025 let next = inner.n()?;
1026 let param = resolve_param(&next, state)?.clone();
1027 if !param.is_optional() {
1028 return Err(ParseError::IfdefNotOptional { span, param });
1029 }
1030 param
1031 } else {
1032 return Err(ParseError::Unexpected {
1033 span,
1034 rule: param.as_rule(),
1035 expected: vec![Rule::param_ident],
1036 });
1037 };
1038
1039 let filter = parse_where_part(&mut inner, state)?;
1040 let Ok(kw_else) = inner.n() else {
1041 return Ok((param, filter, None));
1042 };
1043 kw_else.assert_type(Rule::kw_else)?;
1044 let filter_else = parse_where_part(&mut inner, state)?;
1045 Ok((param, filter, Some(filter_else)))
1046}
1047
1048pub(crate) fn parse_sample(source: Pair<Rule>) -> Result<f64> {
1049 source.assert_type(Rule::sample_rule)?;
1050 let mut inner = source.into_inner();
1051
1052 let keyword = inner.n()?;
1053 keyword.assert_type(Rule::pipe_keyword)?;
1054
1055 let next = inner.n()?;
1056 next.assert_type(Rule::sample_expr)?;
1057 let mut inner = next.into_inner();
1058 let next = inner.n()?;
1059 next.assert_type(Rule::kw_sample)?;
1060 let next = inner.n()?;
1061 let res = parse_number(next)?;
1062 inner.assert_empty()?;
1063 Ok(res.as_f64())
1064}
1065
1066fn parse_as(source: Pair<Rule>) -> Result<As> {
1068 source.assert_type(Rule::r#as)?;
1069 let mut inner = source.into_inner();
1070 let name = parse_metric_name(inner.n()?)?;
1071 inner.assert_empty()?;
1072 Ok(As { name })
1073}
1074
1075fn parse_bucket_by_fn(source: &Pair<'_, Rule>) -> Result<BucketType> {
1076 source.assert_type(Rule::bucket_by_fn)?;
1077 match source.as_str() {
1078 "histogram" => Ok(BucketType::Histogram),
1079 "interpolate_delta_histogram" => Ok(BucketType::InterpolateDeltaHistogram),
1080 other => Err(ParseError::UnsupportedBucketFunction {
1081 span: pair_to_source_span(source),
1082 name: other.to_string(),
1083 }),
1084 }
1085}
1086
1087fn parse_bucket_conversion(source: &Pair<'_, Rule>) -> Result<ConversionMethod> {
1088 source.assert_type(Rule::bucket_conversion)?;
1089 match source.as_str() {
1090 "rate" => Ok(ConversionMethod::Rate),
1091 "increase" => Ok(ConversionMethod::Increase),
1092 other => Err(ParseError::UnsupportedBucketFunction {
1093 span: pair_to_source_span(source),
1094 name: other.to_string(),
1095 }),
1096 }
1097}
1098
1099fn parse_bucket_spec(source: Pair<Rule>) -> Result<BucketSpec> {
1100 source.assert_type(Rule::bucket_spec)?;
1101 Ok(match source.as_str() {
1102 "count" => BucketSpec::Count,
1103 "avg" => BucketSpec::Avg,
1104 "sum" => BucketSpec::Sum,
1105 "min" => BucketSpec::Min,
1106 "max" => BucketSpec::Max,
1107 _ => {
1108 let mut inner = source.into_inner();
1109 let next = inner.n()?;
1110 let perc = parse_number(next)?;
1111 BucketSpec::Percentile(perc.as_f64())
1112 }
1113 })
1114}
1115
1116fn parse_bucket_specs(source: Pair<Rule>) -> Result<Vec<BucketSpec>> {
1117 source.assert_type(Rule::bucket_specs)?;
1118 source
1119 .into_inner()
1120 .map(parse_bucket_spec)
1121 .collect::<Result<_>>()
1122}
1123
1124fn parse_bucket_fn_call_simple(source: Pair<Rule>) -> Result<(BucketType, Vec<BucketSpec>)> {
1125 source.assert_type(Rule::bucket_fn_call_simple)?;
1126 let mut inner = source.into_inner();
1127 let function = parse_bucket_by_fn(&inner.n()?)?;
1128 let specs = parse_bucket_specs(inner.n()?)?;
1129 inner.assert_empty()?;
1130 Ok((function, specs))
1131}
1132
1133fn parse_bucket_fn_call_with_conversion(
1134 source: Pair<Rule>,
1135) -> Result<(BucketType, Vec<BucketSpec>)> {
1136 source.assert_type(Rule::bucket_fn_call_with_conversion)?;
1137 let mut inner = source.into_inner();
1138 let _fn_name = inner.n()?;
1139 let mode = parse_bucket_conversion(&inner.n()?)?;
1140 let specs = parse_bucket_specs(inner.n()?)?;
1141 inner.assert_empty()?;
1142 Ok((BucketType::InterpolateCumulativeHistogram(mode), specs))
1143}
1144
1145fn parse_bucket_fn_call(source: Pair<Rule>) -> Result<(BucketType, Vec<BucketSpec>)> {
1146 source.assert_type(Rule::bucket_fn_call)?;
1147 let mut inner = source.into_inner();
1148 let next = inner.n()?;
1149 let result = match next.as_rule() {
1150 Rule::bucket_fn_call_simple => parse_bucket_fn_call_simple(next),
1151 Rule::bucket_fn_call_with_conversion => parse_bucket_fn_call_with_conversion(next),
1152 rule => Err(ParseError::Unexpected {
1153 span: pair_to_source_span(&next),
1154 rule,
1155 expected: vec![
1156 Rule::bucket_fn_call_simple,
1157 Rule::bucket_fn_call_with_conversion,
1158 ],
1159 }),
1160 };
1161 inner.assert_empty()?;
1162 result
1163}
1164
1165fn parse_bucket_by(source: Pair<Rule>, state: &State) -> Result<BucketBy> {
1166 source.assert_type(Rule::bucket_by)?;
1167 let span = pair_to_source_span(&source);
1168 let mut inner = source.into_inner();
1169 let next = inner.n()?;
1170
1171 let (tags, next) = if next.as_rule() == Rule::tags {
1172 let fields = next
1173 .into_inner()
1174 .map(|field| parse_ident(&field))
1175 .collect::<Result<_>>()?;
1176 (fields, inner.n()?)
1177 } else {
1178 (Vec::new(), next)
1179 };
1180
1181 if next.as_rule() == Rule::bucket_fn_call {
1182 let (function, spec) = parse_bucket_fn_call(next)?;
1183 inner.assert_empty()?;
1184
1185 Ok(BucketBy {
1186 span,
1187 function,
1188 time: None,
1189 tags,
1190 spec,
1191 })
1192 } else {
1193 let time = parse_parameterized_relative_time(next, state)?;
1194 let (function, spec) = parse_bucket_fn_call(inner.n()?)?;
1195
1196 inner.assert_empty()?;
1197 Ok(BucketBy {
1198 span,
1199 function,
1200 time: Some(time),
1201 tags,
1202 spec,
1203 })
1204 }
1205}
1206
1207fn parse_function_id(source: Pair<Rule>) -> Result<Function> {
1208 let mut inner = source.into_inner();
1209 let mut next = inner.n()?;
1210 let mut module = Vec::new();
1211 while next.as_rule() == Rule::module {
1212 let mut this = std::mem::replace(&mut next, inner.n()?).into_inner();
1213 let name = parse_ident(&this.n()?)?;
1214 this.assert_empty()?;
1215 module.push(ModuleId(name));
1216 }
1217 let name = parse_ident(&next)?;
1218 let name = FunctionId(name);
1219 inner.assert_empty()?;
1220 Ok(Function {
1221 name,
1222 module_path: module,
1223 })
1224}
1225
1226pub(crate) struct State {
1227 params: Params,
1228 directives: Directives,
1229 warnings: Warnings,
1230}
1231
1232impl Parser {
1233 pub(crate) fn parse_query<H: BuildHasher>(
1234 &self,
1235 pairs: &mut Pairs<Rule>,
1236 system_params: HashMap<String, ParamType, H>,
1237 ) -> Result<(Query, Warnings)> {
1238 let mut next = pairs.next().ok_or(ParseError::EOF {
1239 span: miette::SourceSpan::new(0.into(), 0),
1240 })?;
1241
1242 let mut params = Params::default();
1243
1244 for (name, typ) in system_params {
1246 if !name.starts_with(SYSTEM_PARAM_PREFIX) {
1247 return Err(ParseError::SystemParamMissingPrefix { param: name });
1248 }
1249 params.push(ParamDeclaration {
1250 span: SourceSpan::new(0.into(), 0),
1251 name,
1252 typ,
1253 });
1254 }
1255
1256 let mut state = State {
1257 params,
1258 directives: Directives::default(),
1259 warnings: Warnings::new(),
1260 };
1261
1262 loop {
1263 match next.as_rule() {
1264 Rule::directive => {
1265 let span = pair_to_source_span(&next);
1266 let (directive, value) = Parser::parse_directive(next)?;
1267 state.directives.insert(directive, value);
1268 next = pairs.next().ok_or(ParseError::EOF { span })?;
1269 }
1270 Rule::param => {
1271 let span = pair_to_source_span(&next);
1272 let param = Parser::parse_param(&mut state, next)?;
1273 state.params.push(param);
1274 next = pairs.next().ok_or(ParseError::EOF { span })?;
1275 }
1276 _ => break,
1277 }
1278 }
1279
1280 let r = self.parse_query_(&state, next)?;
1281 Ok((r, state.warnings))
1282 }
1283
1284 pub(crate) fn parse_directive(source: Pair<'_, Rule>) -> Result<(String, DirectiveValue)> {
1285 let mut inner = source.into_inner();
1286 let directive = parse_ident(&inner.n()?)?;
1287 let value = if let Some(v) = inner.next() {
1288 match v.as_rule() {
1289 Rule::plain_ident | Rule::escaped_ident => DirectiveValue::Ident(parse_ident(&v)?),
1290 Rule::r#const => parse_directive_value(v)?,
1291 rule => Err(ParseError::Unexpected {
1292 span: pair_to_source_span(&v),
1293 rule,
1294 expected: vec![Rule::escaped_ident, Rule::plain_ident, Rule::r#const],
1295 })?,
1296 }
1297 } else {
1298 DirectiveValue::None
1299 };
1300 Ok((directive, value))
1301 }
1302
1303 pub(crate) fn parse_param(
1304 state: &mut State,
1305 source: Pair<'_, Rule>,
1306 ) -> Result<ParamDeclaration> {
1307 let mut inner = source.into_inner();
1308 let next = inner.n()?;
1309 let span = pair_to_source_span(&next);
1310
1311 let name = parse_param_ident(next)?;
1312
1313 if name.starts_with(SYSTEM_PARAM_PREFIX) {
1314 state.warnings.push_span(
1315 span,
1316 WarningReason::ParamUsingSystemPrefix {
1317 param: name.clone(),
1318 },
1319 );
1320 } else if state.params.iter().any(|p| p.name == name) {
1321 return Err(ParseError::ParamDefinedMultipleTimes { span, param: name });
1322 }
1323
1324 let typ = parse_param_type(state, inner.n()?)?;
1325
1326 Ok(ParamDeclaration { span, name, typ })
1327 }
1328
1329 fn parse_query_(&self, state: &State, query: Pair<Rule>) -> Result<Query> {
1330 match query.as_rule() {
1331 Rule::simple_query => {
1332 let inner = query.into_inner();
1333 self.parse_simple_query(state, inner)
1334 }
1335 Rule::compute_query => {
1336 let inner = query.into_inner();
1337 self.parse_compute_query(state, inner)
1338 }
1339 rule => Err(ParseError::Unexpected {
1340 span: pair_to_source_span(&query),
1341 rule,
1342 expected: vec![Rule::simple_query, Rule::compute_query],
1343 }),
1344 }
1345 }
1346
1347 fn parse_compute_query(&self, state: &State, mut pairs: Pairs<Rule>) -> Result<Query> {
1348 let next = pairs.next().ok_or(ParseError::EOF {
1349 span: miette::SourceSpan::new(0.into(), 0),
1350 })?;
1351 let left = Box::new(self.parse_query_(state, next)?);
1352 let next = pairs.next().ok_or(ParseError::EOF {
1353 span: miette::SourceSpan::new(0.into(), 0),
1354 })?;
1355 let right = Box::new(self.parse_query_(state, next)?);
1356
1357 let next = pairs.next().ok_or(ParseError::EOF {
1358 span: miette::SourceSpan::new(0.into(), 0),
1359 })?;
1360 match next.as_rule() {
1361 Rule::compute_rule => {}
1362 Rule::time_range => {
1363 return Err(ParseError::NotSupported {
1364 span: pair_to_source_span(&next),
1365 rule: Rule::time_range,
1366 });
1367 }
1368 rule => {
1369 return Err(ParseError::Unexpected {
1370 span: pair_to_source_span(&next),
1371 rule,
1372 expected: vec![Rule::compute_rule, Rule::time_range],
1373 });
1374 }
1375 }
1376 let mut compute_rule = next.into_inner();
1377
1378 let keyword = compute_rule.n()?;
1379 keyword.assert_type(Rule::pipe_keyword)?;
1380
1381 let next = compute_rule.next().ok_or(ParseError::EOF {
1382 span: pair_to_source_span(&keyword),
1383 })?;
1384 let name = parse_metric_name(next)?;
1385
1386 let next = compute_rule.next().ok_or(ParseError::EOF {
1387 span: pair_to_source_span(&keyword),
1388 })?;
1389 let op = self.parse_compute_fn(next)?;
1390
1391 let mut aggregates = Vec::new();
1392 let mut extends = Vec::new();
1393
1394 for next in &mut pairs {
1396 match next.as_rule() {
1397 Rule::EOI => break,
1398 Rule::pipe_rule => aggregates.push(self.parse_pipe(next, state)?),
1399 Rule::extend_rule => extends.extend(self.parse_extend(next, state)?),
1400
1401 rule => {
1402 return Err(ParseError::Unexpected {
1403 span: pair_to_source_span(&next),
1404 rule,
1405 expected: vec![Rule::EOI, Rule::pipe_rule],
1406 });
1407 }
1408 }
1409 }
1410
1411 Ok(Query::Compute {
1412 left,
1413 right,
1414 name,
1415 op,
1416 aggregates,
1417 extends,
1418 directives: state.directives.clone(),
1419 params: state.params.clone(),
1420 })
1421 }
1422 fn parse_simple_query(&self, state: &State, mut pairs: Pairs<Rule>) -> Result<Query> {
1423 let (source, as_) = parse_source(pairs.n()?, state)?;
1424 let mut sample = None;
1425 let mut filters = Vec::new();
1426 let mut aggregates = Vec::new();
1427 let mut extends = Vec::new();
1428 if let Some(as_) = as_ {
1429 aggregates.push(Aggregate::As(as_));
1430 }
1431
1432 for next in &mut pairs {
1433 match next.as_rule() {
1434 Rule::EOI => break,
1435 Rule::sample_rule if sample.is_some() => {}
1437 Rule::sample_rule => sample = Some(parse_sample(next)?),
1438 Rule::ifdef_rule => {
1439 let (param, filter, else_filter) = parse_ifdef(next, state)?;
1440 filters.push(FilterOrIfDef::Ifdef {
1441 param,
1442 filter,
1443 else_filter,
1444 });
1445 }
1446 Rule::filter_rule => {
1447 filters.push(FilterOrIfDef::Filter(parse_filter(next, state)?));
1448 }
1449 Rule::pipe_rule => aggregates.push(self.parse_pipe(next, state)?),
1450 Rule::extend_rule => extends.extend(self.parse_extend(next, state)?),
1451 rule => {
1452 return Err(ParseError::Unexpected {
1453 span: pair_to_source_span(&next),
1454 rule,
1455 expected: vec![Rule::EOI, Rule::filter_rule, Rule::pipe_rule],
1456 });
1457 }
1458 }
1459 }
1460
1461 Ok(Query::Simple {
1462 sample,
1463 source,
1464 filters,
1465 aggregates,
1466 extends,
1467 directives: state.directives.clone(),
1468 params: state.params.clone(),
1469 })
1470 }
1471
1472 pub(crate) fn parse_pipe(&self, source: Pair<Rule>, state: &State) -> Result<Aggregate> {
1473 source.assert_type(Rule::pipe_rule)?;
1474 let mut inner = source.into_inner();
1475
1476 let keyword = inner.n()?;
1477 keyword.assert_type(Rule::pipe_keyword)?;
1478
1479 let next = inner.n()?;
1480 inner.assert_empty()?;
1481 match next.as_rule() {
1482 Rule::map => Ok(Aggregate::Map(self.parse_map(next)?)),
1483 Rule::align => Ok(Aggregate::Align(self.parse_align(next, state)?)),
1484 Rule::group_by => Ok(Aggregate::GroupBy(self.parse_group_by(next)?)),
1485 Rule::bucket_by => Ok(Aggregate::Bucket(parse_bucket_by(next, state)?)),
1486 rule @ (Rule::join | Rule::replace) => Err(ParseError::NotSupported {
1487 span: pair_to_source_span(&next),
1488 rule,
1489 }),
1490 Rule::r#as => Ok(Aggregate::As(parse_as(next)?)),
1491 rule => Err(ParseError::Unexpected {
1492 span: pair_to_source_span(&next),
1493 rule,
1494 expected: vec![
1495 Rule::map,
1496 Rule::align,
1497 Rule::group_by,
1498 Rule::bucket_by,
1499 Rule::join,
1500 Rule::replace,
1501 Rule::r#as,
1502 ],
1503 }),
1504 }
1505 }
1506
1507 #[allow(clippy::unused_self)] fn parse_extend_expr(&self, source: Pair<Rule>, state: &State) -> Result<TagExtend> {
1509 source.assert_type(Rule::extend_expr)?;
1510 let mut inner = source.into_inner();
1511
1512 let next = inner.n()?;
1513 let tag = parse_ident(&next)?;
1514 let next = inner.n()?;
1515 let value = parse_expr(next, state)?;
1516 Ok(TagExtend { tag, value })
1517 }
1518
1519 #[allow(clippy::unused_self)] fn parse_extend(&self, source: Pair<Rule>, state: &State) -> Result<Vec<TagExtend>> {
1521 source.assert_type(Rule::extend_rule)?;
1522 let mut inner = source.into_inner();
1523
1524 let keyword = inner.n()?;
1525 keyword.assert_type(Rule::pipe_keyword)?;
1526 let keyword = inner.n()?;
1527 keyword.assert_type(Rule::kw_extend)?;
1528
1529 let mut result = Vec::with_capacity(1);
1530
1531 let next = inner.n()?;
1532 result.push(self.parse_extend_expr(next, state)?);
1533 while let Ok(next) = inner.n() {
1534 result.push(self.parse_extend_expr(next, state)?);
1535 }
1536 Ok(result)
1537 }
1538
1539 fn parse_map(&self, source: Pair<Rule>) -> Result<Mapping> {
1540 source.assert_type(Rule::map)?;
1541 let mut inner = source.into_inner();
1542 let next = inner.n()?;
1543 let map = match next.as_rule() {
1544 Rule::map_fn => self.parse_map_fn(next),
1545 Rule::map_eval => self.parse_map_eval(next),
1546 rule => Err(ParseError::Unexpected {
1547 span: pair_to_source_span(&next),
1548 rule,
1549 expected: vec![Rule::map_fn, Rule::map_eval],
1550 }),
1551 }?;
1552 inner.assert_empty()?;
1553 Ok(map)
1554 }
1555 fn parse_map_fn(&self, source: Pair<Rule>) -> Result<Mapping> {
1556 source.assert_type(Rule::map_fn)?;
1557 let span = pair_to_source_span(&source);
1558 let mut inner = source.into_inner();
1559 let func_pair = inner.n()?;
1560 let func = parse_function_id(func_pair)?;
1561 let arg = inner
1562 .next()
1563 .map(|n| parse_number(n).map(Number::as_f64))
1564 .transpose()?;
1565 let Some(function) = self.stdlib.map_fn(&func) else {
1566 return Err(ParseError::UnsupportedMapFunction {
1567 span,
1568 name: func.to_string(),
1569 });
1570 };
1571
1572 inner.assert_empty()?;
1573
1574 Ok(Mapping {
1575 function: function.clone(),
1576 arg,
1577 })
1578 }
1579
1580 fn parse_map_eval(&self, source: Pair<Rule>) -> Result<Mapping> {
1581 source.assert_type(Rule::map_eval)?;
1582 let span = pair_to_source_span(&source);
1583 let mut inner = source.into_inner();
1584 let next = inner.n()?;
1585 let func = match next.as_rule() {
1586 Rule::func => parse_function_id(next)?,
1587 Rule::map_calc_op => Function {
1588 module_path: vec![],
1589 name: FunctionId::new(next.as_str()),
1590 },
1591 rule => {
1592 return Err(ParseError::Unexpected {
1593 span: pair_to_source_span(&next),
1594 rule,
1595 expected: vec![Rule::func, Rule::map_calc_op],
1596 });
1597 }
1598 };
1599 let Some(function) = self.stdlib.map_fn(&func) else {
1600 return Err(ParseError::UnsupportedMapEvaluation {
1601 span,
1602 name: func.to_string(),
1603 });
1604 };
1605 let arg = Some(parse_number(inner.n()?)?.as_f64());
1606 Ok(Mapping {
1607 function: function.clone(),
1608 arg,
1609 })
1610 }
1611
1612 fn parse_align(&self, source: Pair<Rule>, state: &State) -> Result<Align> {
1613 source.assert_type(Rule::align)?;
1614 let mut inner = source.into_inner();
1615
1616 let next = inner.n()?;
1617 next.assert_type(Rule::kw_align)?;
1618
1619 let next = inner.n()?;
1620 if next.as_rule() == Rule::kw_using {
1621 let next = inner.n()?;
1622 let function = self.parse_align_fn(next)?;
1623 inner.assert_empty()?;
1624 return Ok(Align {
1625 function,
1626 time: None,
1627 });
1628 }
1629 next.assert_type(Rule::kw_to)?;
1630 let next = inner.n()?;
1631 let time = parse_parameterized_relative_time(next, state)?;
1632 let next = inner.n()?;
1633 if next.as_rule() == Rule::kw_over {
1634 let next = inner.n()?;
1635 let _sliding_window = parse_parameterized_relative_time(next, state)?;
1636 let next = inner.n()?;
1637 next.assert_type(Rule::kw_using)?;
1638 let _function = self.parse_align_fn(inner.n()?)?;
1639 inner.assert_empty()?;
1640 Err(ParseError::NotImplemented("sliding windows"))
1641 } else if next.as_rule() == Rule::kw_using {
1642 let next = inner.n()?;
1643 let function = self.parse_align_fn(next)?;
1644 inner.assert_empty()?;
1645 Ok(Align {
1646 function,
1647 time: Some(time),
1648 })
1649 } else {
1650 Err(ParseError::Unexpected {
1651 span: pair_to_source_span(&next),
1652 rule: next.as_rule(),
1653 expected: vec![Rule::kw_using],
1654 })
1655 }
1656 }
1657
1658 fn parse_align_fn(&self, source: Pair<Rule>) -> Result<AlignFunction> {
1659 source.assert_type(Rule::func)?;
1660 let span = pair_to_source_span(&source);
1661 let f = parse_function_id(source)?;
1662 let Some(function) = self.stdlib.align_fn(&f) else {
1663 return Err(ParseError::UnsupportedAlignFunction {
1664 span,
1665 name: f.to_string(),
1666 });
1667 };
1668
1669 Ok(function.clone())
1670 }
1671
1672 fn parse_group_by_fn(&self, source: Pair<Rule>) -> Result<GroupFunction> {
1673 let span = pair_to_source_span(&source);
1674 let f = parse_function_id(source)?;
1675 let Some(function) = self.stdlib.group_fn(&f) else {
1676 return Err(ParseError::UnsupportedGroupFunction {
1677 span,
1678 name: f.to_string(),
1679 });
1680 };
1681
1682 Ok(function.clone())
1683 }
1684
1685 fn parse_group_by(&self, source: Pair<Rule>) -> Result<GroupBy> {
1686 source.assert_type(Rule::group_by)?;
1687 let span = pair_to_source_span(&source);
1688
1689 let mut inner = source.into_inner();
1690 let next = inner.n()?;
1691 next.assert_type(Rule::kw_group)?;
1692
1693 let next = inner.n()?;
1694 let (tags, function) = if next.as_rule() == Rule::kw_by {
1695 let next = inner.n()?;
1696 next.assert_type(Rule::tags)?;
1697 let fields = next
1698 .into_inner()
1699 .map(|field| parse_ident(&field))
1700 .collect::<Result<_>>()?;
1701 let next = inner.n()?;
1702 next.assert_type(Rule::kw_using)?;
1703 let function = self.parse_group_by_fn(inner.n()?)?;
1704 (fields, function)
1705 } else {
1706 next.assert_type(Rule::kw_using)?;
1707 let next = inner.n()?;
1708 (Vec::new(), self.parse_group_by_fn(next)?)
1709 };
1710 inner.assert_empty()?;
1711 Ok(GroupBy {
1712 span,
1713 function,
1714 tags,
1715 })
1716 }
1717
1718 pub(crate) fn parse_compute_fn(&self, source: Pair<Rule>) -> Result<ComputeFunction> {
1719 source.assert_type(Rule::compute_fn)?;
1720 let span = pair_to_source_span(&source);
1721 let mut inner = source.into_inner();
1722 let next = inner.n()?;
1723 let f = match next.as_rule() {
1724 Rule::func => parse_function_id(next)?,
1725 Rule::compute_op => Function {
1726 module_path: vec![],
1727 name: FunctionId::new(next.as_str()),
1728 },
1729 rule => {
1730 return Err(ParseError::Unexpected {
1731 span: pair_to_source_span(&next),
1732 rule,
1733 expected: vec![Rule::func, Rule::compute_op],
1734 });
1735 }
1736 };
1737 inner.assert_empty()?;
1738 let Some(function) = self.stdlib.compute_fn(&f) else {
1739 return Err(ParseError::UnsupportedComputeFunction {
1740 span,
1741 name: f.to_string(),
1742 });
1743 };
1744
1745 Ok(function.clone())
1746 }
1747}
1748
1749pub(crate) struct Parser {
1750 stdlib: &'static Module,
1751}
1752
1753impl Default for Parser {
1754 fn default() -> Self {
1755 Parser { stdlib: &STDLIB }
1756 }
1757}