@precedence { logic @left }

@top Program { Query }

Query {
    Name ( WhereClause | OrderClause  | LimitClause | SelectClause | RenderClause )*
}

commaSep<content> { content ("," content)* }

WhereClause { "where" LogicalExpr }
OrderClause { "order" "by" Name Order? }
LimitClause { "limit" Number }
SelectClause { "select" commaSep<Name> }
RenderClause { "render" String }

Order {
  "desc" | "asc"
}

Value { Number | String | Bool | Regex | Null | List }

LogicalExpr { AndExpr | FilterExpr }

AndExpr { FilterExpr !logic "and" FilterExpr }

FilterExpr {
  Name "<" Value
| Name "<=" Value
| Name "=" Value
| Name "!=" Value
| Name ">=" Value
| Name ">" Value
| Name "=~" Value
| Name "!=~" Value
| Name "in" Value
}

List { "[" commaSep<Value> "]" }

@skip { space }



Bool {
  "true" | "false"
}

Null {
  "null"
}

@tokens {
  space { std.whitespace+ }
  Name { (std.asciiLetter | "-" | "_")+ }
  String {
    ("\"" | "“" | "”") ![\"”“]* ("\"" | "“" | "”")
  }
  Regex { "/" ( ![/\\\n\r] | "\\" _ )* "/"? }

  Number { std.digit+ }
}
