rest-rewrite-0.1: src/Language/REST/OpOrdering.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Language.REST.OpOrdering (
empty
, merge
, OpOrdering
, opInsert
, opGT
, opEQ
, (=.)
, (>.)
, parseOO
) where
import Prelude hiding (GT, EQ)
import GHC.Generics (Generic)
import Data.Hashable
import Data.Maybe
import qualified Data.Text as T
import qualified Data.HashSet as S
import Text.ParserCombinators.Parsec.Char
import Text.ParserCombinators.Parsec
import Text.Parsec (parserTrace)
import qualified Language.REST.PartialOrder as PO
import Language.REST.Op
import Language.REST.Types
import Language.REST.WQO as WQO
type PartialOrder = PO.PartialOrder
type OpOrdering = WQO Op
opGT :: OpOrdering -> Op -> Op -> Bool
opGT s f g = getRelation s f g == Just QGT
opEQ :: OpOrdering -> Op -> Op -> Bool
opEQ s f g = getRelation s f g == Just QEQ
opInsert :: OpOrdering -> Op -> Op -> QORelation -> Maybe OpOrdering
opInsert o f g r =
case WQO.insert o (f, g, r) of
ValidExtension o' -> Just o'
_ -> Nothing
-- The following only are valid if f /= g.
-- precondition : f /= g
(>.) :: Op -> Op -> OpOrdering
(>.) f g = fromJust $ WQO.singleton (f, g, QGT)
-- precondition : f /= g
(=.) :: Op -> Op -> OpOrdering
(=.) f g = fromJust $ WQO.singleton (f, g, QEQ)
-- precondition : f /= g
(<.) :: Op -> Op -> OpOrdering
(<.) f g = g >. f
parseOO :: String -> Maybe OpOrdering
parseOO str =
case parse parser "" str of
Left err -> error (show err)
Right t -> t
parser = fmap mergeAll' (sepBy1 atom conj) where
mergeAll' :: [Maybe OpOrdering] -> Maybe OpOrdering
mergeAll' [x] = x
mergeAll' (Just x : Just x' : xs) =
do
x'' <- merge x x'
mergeAll' (Just x'' : xs)
mergeAll' _ = Nothing
conj = spaces >> (char '\8743' <|> char '^') >> spaces
eq = spaces >> char '=' >> spaces
gt = spaces >> char '>' >> spaces
atom = try gtAtom <|> try eqAtom
eqAtom = fmap allEQ (sepBy1 sym (try eq))
where
mkEQ f g = WQO.singleton (f, g, QEQ)
allEQ syms =
let
pairs = zipWith mkEQ syms (tail syms)
in
mergeAll' pairs
gtAtom = do
left <- sym
_ <- gt
right <- sym
return $ WQO.singleton (left, right, QGT)
sym = fmap (Op . T.pack) (many (alphaNum <|> char '+' <|> char '*'))