Packages

A library that allows for building predicates to query an in-memory data structure in Elixir

Current section

Files

Jump to
predicated lib predicated query parser.ex
Raw

lib/predicated/query/parser.ex

defmodule Predicated.Query.Parser do
import NimbleParsec
lparen = ascii_char([?(]) |> label("(")
rparen = ascii_char([?)]) |> label(")")
whitespace = ascii_char([32, ?\t, ?\n]) |> times(min: 1) |> label("whitespace")
indentifier =
utf8_string([?a..?z, ?A..?Z, ?0..?9, ?_, ?.], min: 1)
|> reduce({Enum, :join, [""]})
|> unwrap_and_tag(:identifier)
boolean_expression =
ignore(whitespace)
|> choice([
string("true"),
string("TRUE"),
string("false"),
string("FALSE")
])
|> reduce({Enum, :join, [""]})
|> unwrap_and_tag(:boolean_expression)
cast =
empty()
|> string("::")
|> utf8_string([?a..?z, ?A..?Z], min: 1)
string_expression =
ignore(whitespace)
|> ignore(string("'"))
|> utf8_string([?a..?z, ?A..?Z, ?0..?9, ?_, ?=, ?>, ?<, ?\s, ?-, ?:, ?.], min: 1)
|> ignore(string("'"))
|> optional(cast)
|> reduce({Enum, :join, [""]})
|> unwrap_and_tag(:string_expression)
number_expression =
ignore(whitespace)
|> optional(string("-"))
|> choice([utf8_string([?0..?9, ?.], min: 1), integer(min: 1)])
|> reduce({Enum, :join, [""]})
|> unwrap_and_tag(:number_expression)
list_expression =
ignore(whitespace)
|> string("[")
|> utf8_string([?a..?z, ?A..?Z, ?0..?9, ?_, ?=, ?>, ?<, ?\s, ?-, ?:, ?., ?\,, ?'], min: 1)
|> string("]")
|> reduce({Enum, :join, [""]})
|> unwrap_and_tag(:list_expression)
expression =
choice([list_expression, boolean_expression, string_expression, number_expression])
comparison_operator =
ignore(whitespace)
|> choice([
string("=="),
string("!="),
string(">="),
string("<="),
string(">"),
string("<"),
string("IN"),
string("in"),
string("CONTAINS"),
string("contains")
])
|> reduce({Enum, :join, [""]})
|> unwrap_and_tag(:comparison_operator)
comparison =
ignore(optional(whitespace))
|> concat(indentifier)
|> concat(comparison_operator)
|> concat(expression)
|> ignore(optional(whitespace))
grouping =
empty()
|> choice([
ignore(lparen)
|> concat(parsec(:expr))
|> ignore(rparen)
|> tag(:grouping),
comparison
])
defcombinatorp(
:term,
empty()
|> choice([
grouping
|> ignore(optional(whitespace))
|> choice([string("AND"), string("and")])
|> ignore(optional(whitespace))
|> concat(parsec(:term)),
grouping
])
)
defcombinatorp(
:expr,
empty()
|> choice([
parsec(:term)
|> ignore(optional(whitespace))
|> choice([string("OR"), string("or")])
|> ignore(optional(whitespace))
|> concat(parsec(:expr)),
parsec(:term)
])
)
defparsec(:parse, parsec(:expr), export_metadata: true)
end