HTTPQL = { SOI ~ Query? ~ EOI }
// Tokens
// Delimiters
LeftParen = _{ "(" }
RightParen = _{ ")" }
Dot = _{ "." }
Colon = _{ ":" }
// Logical operators
And = { "AND" | "and" }
Or = { "OR" | "or" }
// Namespaces
RowNamespace = _{ "row" }
RequestNamespace = _{ "req" }
ResponseNamespace = _{ "resp" }
PresetNamespace = _{ "preset" }
SourceNamespace = _{ "source" }
// Row field names
RowIntFieldName = { "id" }
// Request field names
RequestStringFieldName = { "ext" | "host" | "method" | "path" | "query" | "raw" }
RequestIntFieldName = { "len" | "port" }
RequestDateFieldName = { "created_at" }
RequestBoolFieldName = { "tls" }
// Response field names
ResponseStringFieldName = { "raw" }
ResponseIntFieldName = { "code" | "len" | "roundtrip" }
// Operators for string and integer types
StringOperator = { "cont" | "ncont" | "eq" | "ne" | "like" | "nlike" }
RegexOperator = { "regex" | "nregex" }
IntOperator = { "eq" | "gte" | "gt" | "lte" | "lt" | "ne" }
DateOperator = { "lt" | "gt" }
BoolOperator = { "eq" | "ne" }
// Value types
SymbolValue = @{ ('a'..'z' | '0'..'9' | "-" | "_")+ }
IntValue = @{ ASCII_DIGIT+ }
StringValue = @{ "\"" ~ StringContent ~ "\"" }
StringContent = { StringChar* }
StringChar = {
!("\"" | "\\") ~ ANY
| "\\" ~ ("\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t")
| "\\" ~ ("u" ~ ASCII_HEX_DIGIT{4})
}
RegexValue = ${ "/" ~ RegexContent ~ "/" }
RegexContent = @{ RegexChar* }
RegexChar = {
"\\" ~ ANY
| !"/" ~ ANY
}
BoolValue = { "true" | "false" }
// Define non-token rules for constructing expressions
WHITESPACE = _{ " " | "\t" | LineTerminator }
COMMENT = _{ LineComment | BlockComment }
BlockComment = _{ "/*" ~ (!"*/" ~ ANY)* ~ "*/" }
LineComment = _{ "//" ~ (!LineTerminator ~ ANY)* }
LineTerminator = @{ "\r\n" | "\r" | "\n" }
// Expression
IntExpression = ${ IntOperator ~ Colon ~ IntValue }
StringExpression = ${ StringOperator ~ Colon ~ StringValue | RegexOperator ~ Colon ~ (RegexValue | StringValue) }
DateExpression = ${ DateOperator ~ Colon ~ StringValue }
BoolExpression = ${ BoolOperator ~ Colon ~ BoolValue }
PresetNameExpression = { StringValue }
PresetAliasExpression = { SymbolValue }
SourceNameExpression = { StringValue }
// Clause
StringClause = { StringValue }
RowClause = ${ RowNamespace ~ Dot ~ RowIntFieldName ~ Dot ~ IntExpression }
RequestClause = ${
RequestNamespace ~ Dot ~ RequestIntFieldName ~ Dot ~ IntExpression
| RequestNamespace ~ Dot ~ RequestStringFieldName ~ Dot ~ StringExpression
| RequestNamespace ~ Dot ~ RequestDateFieldName ~ Dot ~ DateExpression
| RequestNamespace ~ Dot ~ RequestBoolFieldName ~ Dot ~ BoolExpression
}
ResponseClause = ${
ResponseNamespace ~ Dot ~ ResponseIntFieldName ~ Dot ~ IntExpression
| ResponseNamespace ~ Dot ~ ResponseStringFieldName ~ Dot ~ StringExpression
}
PresetClause = ${
PresetNamespace ~ Colon ~ (PresetNameExpression | PresetAliasExpression)
}
SourceClause = ${
SourceNamespace ~ Colon ~ SourceNameExpression
}
// Query
Clause = _{ StringClause | RowClause | RequestClause | ResponseClause | PresetClause | SourceClause | LeftParen ~ Query ~ RightParen }
LogicalOperator = _{ And | Or }
Query = { (Clause ~ (LogicalOperator ~ Clause)*)? }