philomena/lib/philomena_query/parse/literal_parser.ex

63 lines
1.3 KiB
Elixir
Raw Normal View History

defmodule PhilomenaQuery.Parse.LiteralParser do
@moduledoc false
2019-11-02 19:34:25 +01:00
import NimbleParsec
2020-08-08 02:23:36 +02:00
@dialyzer [:no_match, :no_unused]
defp to_number(input), do: PhilomenaQuery.Parse.Helpers.to_number(input)
2019-11-02 19:34:25 +01:00
2019-11-02 22:02:46 +01:00
float =
ascii_string([?0..?9], min: 1)
2023-09-27 20:16:59 +02:00
|> optional(ascii_char(~c".") |> ascii_string([?0..?9], min: 1))
2019-11-02 22:02:46 +01:00
|> reduce({List, :to_string, []})
|> reduce(:to_number)
2019-11-02 21:31:55 +01:00
2019-11-02 19:34:25 +01:00
edit_distance =
ignore(string("~"))
2019-11-02 22:02:46 +01:00
|> concat(float)
2019-11-02 19:34:25 +01:00
|> unwrap_and_tag(:fuzz)
|> eos()
stopwords =
choice([
string("*"),
string("?"),
edit_distance
])
normal =
lookahead_not(stopwords)
|> choice([
ignore(string("\\")) |> utf8_char([]),
utf8_char([])
])
|> repeat()
|> reduce({List, :to_string, []})
|> unwrap_and_tag(:literal)
|> optional(edit_distance)
|> eos()
# Runs of Kleene stars are coalesced.
# Fuzzy search has no meaning in wildcard mode, so we ignore it.
wildcard =
lookahead_not(edit_distance)
|> choice([
ignore(string("\\")) |> utf8_char([]),
string("*") |> ignore(repeat(string("*"))),
utf8_char([])
])
|> repeat()
|> reduce({List, :to_string, []})
|> unwrap_and_tag(:wildcard)
|> ignore(optional(edit_distance))
|> eos()
literal =
choice([
normal,
wildcard
])
2020-01-11 05:20:19 +01:00
defparsec(:parse, literal)
end