Advertisement
Stephan_

http://stackoverflow.com/questions/9215975/differentiating-l

Feb 10th, 2012
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 3.66 KB | None | 0 0
  1. module SqlAst =
  2.  
  3.     open System
  4.  
  5.     type BinaryOp =
  6.         | Add
  7.         | Sub
  8.         | Mul
  9.         | Div
  10.         | Mod
  11.         | BitAnd
  12.         | BitOr
  13.         | BitXor
  14.  
  15.     type UnaryOp =
  16.         | Neg
  17.         | BitNot
  18.    
  19.     type Comparison =
  20.         | Eq
  21.         | Ne
  22.  
  23.     type Constant =
  24.         | Int32 of int
  25.         | Float of float
  26.         | DateTime of DateTime
  27.         | Bool of bool
  28.         | String of string
  29.         | Null
  30.      
  31.     type ScalarExpr =
  32.         | Identifier of string list
  33.         | Constant of Constant
  34.         | Binary of BinaryOp * ScalarExpr * ScalarExpr
  35.         | Unary of UnaryOp * ScalarExpr
  36.  
  37.     type SearchCondition =
  38.         | Comparison of Comparison * ScalarExpr * ScalarExpr
  39.         | Or of SearchCondition * SearchCondition
  40.         | And of SearchCondition * SearchCondition
  41.  
  42. module (*private*) SqlParserImpl =
  43.  
  44.     open FParsec
  45.     open FParsec.Primitives
  46.     open FParsec.CharParsers
  47.     open SqlAst
  48.  
  49.     type Assoc = Associativity
  50.  
  51.     let ws = spaces
  52.  
  53.     let nameStartChar = pchar '_' <|> asciiLetter
  54.     let nameChar = nameStartChar <|> digit
  55.     let name = many1Chars2 nameStartChar nameChar
  56.     let id = sepBy1 name (pstring ".") .>> ws |>> Identifier
  57.     let trueLiteral = stringCIReturn "true" (Bool true) .>> ws
  58.     let falseLiteral = stringCIReturn "false" (Bool false) .>> ws
  59.     let boolLiteral = (trueLiteral <|> falseLiteral)
  60.     let nullLiteral = stringCIReturn "null" Null .>> ws
  61.     let quoteChar = pstring "'"
  62.     let pChar = satisfy ((<>) '\'')
  63.     let stringLiteral = (quoteChar >>. (manyCharsTill pChar quoteChar)) |>> String .>> ws
  64.     let floatLiteral = pfloat |>> Float .>> ws
  65.     let int32Literal = pint32 |>> Int32 .>> ws
  66.     let constant =
  67.         [ boolLiteral; nullLiteral; int32Literal; floatLiteral; stringLiteral ]
  68.         |> choice
  69.         |>> Constant
  70.     let strOrSymOp str sym x = ((stringCIReturn str x) <|> (stringCIReturn sym x)) .>> ws
  71.          
  72.     let lparen = pstring "(" >>. ws
  73.     let rparen = pstring ")" >>. ws
  74.     let tryBetweenParens p = lparen >>? (p .>>? rparen)
  75.  
  76.     let opp = OperatorPrecedenceParser<_,_,_>()
  77.     let scalarExpr = opp.ExpressionParser
  78.     opp.TermParser <- constant <|> id <|> tryBetweenParens scalarExpr
  79.    
  80.     let addInfixOp (str, prec, op) = opp.AddOperator(InfixOperator(str, ws, prec, Assoc.Left, fun l r -> Binary(op, l, r)))
  81.     let addPrefixOp (str, prec, op) = opp.AddOperator(PrefixOperator(str, ws, prec, false, fun x -> Unary(op, x)))
  82.     [ "|", 1, BitOr
  83.       "^", 2, BitXor
  84.       "&", 3, BitAnd
  85.       "+", 4, Add
  86.       "-", 4, Sub
  87.       "*", 5, Mul
  88.       "/", 5, Div
  89.       "%", 5, Mod ]
  90.     |> List.iter addInfixOp
  91.     [ "-", 6, Neg
  92.       "~", 6, BitNot ]
  93.     |> List.iter addPrefixOp
  94.    
  95.     let eqOp = strOrSymOp "eq" "=" Eq    
  96.     let neOp = strOrSymOp "ne" "<>" Ne    
  97.     let compareOp = [ eqOp; neOp ] |> choice  
  98.     let comparison = // doesn't currently allow chained comparisons ( e.g. 1 = 2 = 3)
  99.         let compareExpr = pipe3 scalarExpr compareOp scalarExpr (fun l op r -> Comparison(op, l, r))
  100.         compareExpr <|> tryBetweenParens compareExpr
  101.    
  102.     let andTerm = stringCIReturn "and" (fun l r -> And(l, r)) .>> ws
  103.     let orTerm = stringCIReturn "or" (fun l r -> Or(l, r)) .>> ws
  104.     let searchCondition, searchConditionRef = createParserForwardedToRef()
  105.     do searchConditionRef:=
  106.         chainl1 (comparison <|> between lparen rparen searchCondition)
  107.                 (andTerm <|> orTerm)
  108.  
  109.     let filter : Parser<_,unit> = ws >>. searchCondition .>> eof
  110.  
  111. open FParsec
  112. do printf "%A" (run SqlParserImpl.filter "((((((1) = ((1 + (2)))))) or ((2 + ((3))) = 2)) or (3 = 3))")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement