Advertisement
Guest User

Untitled

a guest
Sep 30th, 2013
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 3.30 KB | None | 0 0
  1. module AcceptsParser
  2.  
  3. open FParsec
  4.  
  5. type Param =
  6.   | Q of float
  7.   | Mxb of int64
  8.   | Other of string * string
  9.  
  10. type MediaRange =
  11.   | Qualified
  12.   | SubtypesOf
  13.   | Any
  14.  
  15. type AcceptItem = {
  16.     qualification: MediaRange
  17.     mtype: string
  18.     msubtype: string
  19.     q: float
  20.     mxb: int64 option
  21.     parameters: Param list
  22.     } with
  23.   static member Default = {
  24.     qualification = Any
  25.     mtype = "*"
  26.     msubtype = "*"
  27.     q = 1.0
  28.     mxb = None
  29.     parameters = []
  30.     }
  31.  
  32. module Parse =
  33.   let concat (s:'a seq) = System.String.Concat(s)
  34.  let rstrip (s:string) = s.TrimEnd()
  35.  
  36.  let rec scanPs state = function
  37.    | [] -> state
  38.    | p::ps -> match p with
  39.                | Mxb count -> scanPs {state with mxb=Some count} ps
  40.                | Q q -> scanPs {state with q=q} ps
  41.                | _ -> scanPs {state with parameters=p::state.parameters} ps
  42.  
  43.  let unpackAcceptItem = function
  44.    | (("*","*"), ps) -> scanPs {AcceptItem.Default with mtype="*"; msubtype="*"; qualification=Any} ps
  45.    | ((t,"*"), ps) -> scanPs {AcceptItem.Default with mtype=t; msubtype="*"; qualification=SubtypesOf} ps
  46.    | ((t,st) as fulltype, ps) -> scanPs {AcceptItem.Default with mtype=t; msubtype=st; qualification=Qualified} ps
  47.  
  48.  let separators = "()<>@,;:\\\"/[]?={} \t"
  49.  let controls =  [| for n = 0 to 31 do yield char n |] |> concat
  50.  
  51.  let TOKEN = many1 (noneOf (separators + controls)) |>> concat
  52.  
  53.  let QUOTEDPAIR = skipString "\\" >>. anyChar |>> function
  54.    | 'r' -> '\r'  | 'n' -> '\n'  | 't' -> '\t'  | 'b' -> '\b'
  55.    | 'a' -> '\a'  | 'f' -> '\f'  | 'v' -> '\v'  | _ as qc -> qc
  56.  
  57.  let QDTEXT = noneOf "\""
  58.  let QUOTEDSTRING = skipString "\""  >>. many (QUOTEDPAIR <|> QDTEXT) .>> skipString "\"" |>> concat
  59.  
  60.  let ATTRIBUTE = TOKEN
  61.  let VALUE = TOKEN <|> QUOTEDSTRING
  62.  
  63.  let PARAMETER = ATTRIBUTE .>> skipString "=" .>>. VALUE |>> Param.Other
  64.  let QPARAM = skipString "q=" >>. pfloat |>> Q
  65.  let MXBPARAM = skipString "mxb=" >>. pint64 |>> Mxb
  66.  let PARAMETERS = many (skipString ";" >>. (QPARAM <|> MXBPARAM <|> PARAMETER))
  67.  
  68.  let MTYPE = TOKEN
  69.  let MSUBTYPE = TOKEN
  70.  let MEDIATYPE = MTYPE .>> skipString "/" .>>. MSUBTYPE .>>. PARAMETERS
  71.  
  72.  let ACCEPTS = parse {
  73.    do! spaces
  74.    let! mt = MEDIATYPE |>> unpackAcceptItem
  75.    let! mts = many (parse {
  76.      do! skipString ","
  77.      do! spaces
  78.      return!  MEDIATYPE |>> unpackAcceptItem
  79.      })
  80.    return mt :: mts
  81.    }
  82.  
  83.  
  84. open Parse
  85.  
  86. let findSortableMatches (accept:string)  (mt:string)  = [
  87.  match (run ACCEPTS accept, run MEDIATYPE mt) with
  88.  | Success (ais, _, _), Success (((t,st),ps),_,_) ->
  89.    for item in ais do
  90.      let matchingParams = Set item.parameters |> Set.intersect (Set ps) |> Set.toList
  91.      match item.qualification with
  92.      | Any -> yield ((0,0), List.length matchingParams, item.q), item, matchingParams
  93.      | SubtypesOf when item.mtype = t -> yield ((1,0), List.length matchingParams, item.q), item, matchingParams
  94.      | Qualified when item.mtype=t && item.msubtype=st -> yield ((1,1), List.length matchingParams, item.q), item, matchingParams
  95.      | _ -> ()
  96.  | _ -> ()
  97.  ]
  98.  
  99. let FindMatches accept mt =
  100.  let found = findSortableMatches accept mt |> List.sort |> List.rev
  101.  [for (sortKey, ai, matchedParams) in found -> (ai.mtype, ai.msubtype, ai.q, matchedParams)]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement