# HG changeset patch # User Adam Chlipala # Date 1270566439 14400 # Node ID 775357041e483f658c63117bb1afb83e244ec57e # Parent b5a4c5407ae0d0fa0989bf39bcd2a3edbf9379f2 Parsing float and string SQL literals diff -r b5a4c5407ae0 -r 775357041e48 src/iflow.sml --- a/src/iflow.sml Tue Apr 06 10:39:15 2010 -0400 +++ b/src/iflow.sml Tue Apr 06 11:07:19 2010 -0400 @@ -585,6 +585,14 @@ NONE => NONE | SOME (v, chs) => SOME (f v, chs) +fun wrapP p f chs = + case p chs of + NONE => NONE + | SOME (v, chs) => + case f v of + NONE => NONE + | SOME r => SOME (r, chs) + fun alt p1 p2 chs = case p1 chs of NONE => p2 chs @@ -679,24 +687,42 @@ datatype ('a, 'b) sum = inl of 'a | inr of 'b -fun int chs = +fun string chs = case chs of - String s :: chs' => - let - val (befor, after) = Substring.splitl Char.isDigit (Substring.full s) - in - if Substring.isEmpty befor then - NONE - else case Int64.fromString (Substring.string befor) of - NONE => NONE - | SOME n => SOME (n, if Substring.isEmpty after then - chs' - else - String (Substring.string after) :: chs') - end - | _ => NONE + String s :: chs => + if size s >= 2 andalso String.sub (s, 0) = #"'" then + let + fun loop (cs, acc) = + case cs of + [] => NONE + | c :: cs => + if c = #"'" then + SOME (String.implode (rev acc), cs) + else if c = #"\\" then + case cs of + c :: cs => loop (cs, c :: acc) + | _ => raise Fail "Iflow.string: Unmatched backslash escape" + else + loop (cs, c :: acc) + in + case loop (String.explode (String.extract (s, 1, NONE)), []) of + NONE => NONE + | SOME (s, []) => SOME (s, chs) + | SOME (s, cs) => SOME (s, String (String.implode cs) :: chs) + end + else + NONE + | _ => NONE -val prim = wrap (follow (wrap int Prim.Int) (opt (const "::int8"))) #1 +val prim = + altL [wrap (follow (wrapP (follow (keep Char.isDigit) (follow (const ".") (keep Char.isDigit))) + (fn (x, ((), y)) => Option.map Prim.Float (Real64.fromString (x ^ "." ^ y)))) + (opt (const "::float8"))) #1, + wrap (follow (wrapP (keep Char.isDigit) + (Option.map Prim.Int o Int64.fromString)) + (opt (const "::int8"))) #1, + wrap (follow (opt (const "E")) (follow string (opt (const "::text")))) + (Prim.String o #1 o #2)] fun known' chs = case chs of diff -r b5a4c5407ae0 -r 775357041e48 tests/policy.ur --- a/tests/policy.ur Tue Apr 06 10:39:15 2010 -0400 +++ b/tests/policy.ur Tue Apr 06 11:07:19 2010 -0400 @@ -35,7 +35,9 @@ fun main () = x1 <- queryX (SELECT fruit.Id, fruit.Nam - FROM fruit) + FROM fruit + WHERE fruit.Nam = "apple" + AND fruit.Weight = 1.23) (fn x =>
  • {[x.Fruit.Id]}: {[x.Fruit.Nam]}
  • ); x2 <- queryX (SELECT fruit.Nam, order.Qty