Created
October 19, 2020 16:52
-
-
Save CraftyFella/d6ee592a650dcd0fd42ce9b6cd2dd035 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open FParsec | |
[<RequireQualifiedAccess>] | |
type QueryComparison = | |
| Equal | |
| NotEqual | |
[<RequireQualifiedAccess>] | |
type TableOperators = | |
| And | |
| Or | |
[<RequireQualifiedAccess>] | |
type Filter = | |
| Property of name: string * QueryComparison * value: string | |
| Combined of Filter * TableOperators * Filter | |
let letterOrNumber = asciiLetter <|> digit | |
let manyLettersOrNumbers = many1Chars letterOrNumber | |
let manyCharsNotSingleQuote = (many1Chars (noneOf [ '\'' ])) | |
let stringParser = | |
let quote = pchar '\'' | |
between quote quote manyCharsNotSingleQuote |>> (string) | |
let fieldValueParser = stringParser | |
let queryComparisonParser = | |
[ ("eq", QueryComparison.Equal); ("ne", QueryComparison.NotEqual) ] | |
|> List.map (fun (toMatch, qc) -> stringReturn toMatch qc <?> (sprintf "%O" qc)) | |
|> choice | |
let propertyParser = | |
let name = manyLettersOrNumbers .>> spaces <?> "Name" | |
let queryComparison = queryComparisonParser .>> spaces <?> "QueryComparison" | |
let filterValue = fieldValueParser <?> "FilterValue" | |
name .>>. queryComparison .>>. filterValue |>> (fun ((n, qc), fv) -> Filter.Property(n, qc, fv)) | |
let opp = new OperatorPrecedenceParser<Filter, unit, unit>() | |
let expr = opp.ExpressionParser | |
opp.AddOperator(InfixOperator("and", spaces, 1, Associativity.Left, fun left right -> Filter.Combined(left, TableOperators.And, right))) | |
opp.AddOperator(InfixOperator("or", spaces, 2, Associativity.Left, fun left right -> Filter.Combined(left, TableOperators.Or, right))) | |
opp.TermParser <- choice [propertyParser; expr] | |
let filter = spaces >>. expr .>> spaces .>> eof | |
let parse query = run filter query | |
[<EntryPoint>] | |
let main argv = | |
parse "Name eq 'Dave' and Colour ne 'red'" |> printfn "%A" | |
(* | |
Failure: | |
Error in Ln: 1 Col: 16 | |
Name eq 'Dave' and Colour ne 'red' | |
^ | |
Expecting: end of input | |
*) | |
0 // return an integer exit code |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment