// Grammar for the FilterBar query language. // // Supports: // - regex("...") raw-text regex search over log lines // - metric_name[param] value metric comparisons // - json[field] value JSON field comparisons (line parsed as JSON) // - sequence value reserved metric name (no [param]) // - timestamp value reserved metric name (no [param]) // - `and` / `or` boolean combinators, with `and` binding tighter than `or` // - parenthesized sub-expressions WHITESPACE = _{ " " | "\t" | "\n" | "\r" } file = { SOI ~ or_expr ~ EOI } or_expr = { and_expr ~ (or_kw ~ and_expr)* } and_expr = { term ~ (and_kw ~ term)* } term = _{ regex_expr | comparison | "(" ~ or_expr ~ ")" } // These must be atomic (`@`): a non-atomic rule would let pest's implicit // whitespace insertion slip in between the keyword and its own boundary // check below, which breaks the lookahead (it would see the first // non-whitespace character *after* skipping the separating space, instead // of the character immediately following the keyword). and_kw = @{ "and" ~ !(ASCII_ALPHANUMERIC | "_") } or_kw = @{ "or" ~ !(ASCII_ALPHANUMERIC | "_") } regex_expr = { "regex" ~ "(" ~ string_literal ~ ")" } string_literal = ${ "\"" ~ inner_str ~ "\"" } inner_str = @{ (escaped_char | !("\"" | "\\") ~ ANY)* } escaped_char = @{ "\\" ~ ANY } comparison = _{ json_comparison | metric_comparison } // `json[field] value` must be tried before `metric_comparison` since "json" is // otherwise a syntactically valid (if never declared) metric name. json_comparison = { "json" ~ "[" ~ param ~ "]" ~ op ~ value } metric_comparison = { metric ~ ("[" ~ param ~ "]")? ~ op ~ value } metric = @{ ident } param = @{ ident } ident = @{ (ASCII_ALPHANUMERIC | "_")+ } op = { "<=" | ">=" | "==" | "!=" | "<" | ">" } value = @{ (!(WHITESPACE | ")") ~ ANY)+ }