-- | -- This module provides an implementation of the relapse validation language. -- -- Relapse is intended to be used for validation of trees or filtering of lists of trees. -- -- Katydid currently provides two types of trees out of the box: Json and XML, -- but relapse supports any type of tree as long the type -- is of the Tree typeclass provided by the Parsers module. -- -- The validate and filter functions expects a Tree to be a list of trees, -- since not all serialization formats have a single root. -- For example, valid json like "[1, 2]" does not have a single root. -- Relapse can also validate these types of trees. -- If your tree has a single root, simply provide a singleton list as input. module Relapse ( parse, parseWithUDFs, Grammar , validate, filter ) where import Prelude hiding (filter) import Control.Monad.State (runState) import Control.Monad (filterM) import qualified Parser import qualified Ast import qualified MemDerive import qualified Smart import Parsers import qualified Exprs -- | Grammar represents a compiled relapse grammar. newtype Grammar = Grammar Smart.Grammar -- | -- parse parses the relapse grammar and returns either a parsed grammar or an error string. parse :: String -> Either String Grammar parse grammarString = do { parsed <- Parser.parseGrammar grammarString; Grammar <$> Smart.compile parsed; } -- | -- parseWithUDFs parses the relapse grammar with extra user defined functions -- and returns either a parsed grammar or an error string. parseWithUDFs :: Exprs.MkFunc -> String -> Either String Grammar parseWithUDFs userLib grammarString = do { parsed <- Parser.parseGrammarWithUDFs userLib grammarString; Grammar <$> Smart.compile parsed; } -- | -- validate returns whether a tree is valid, given the grammar. validate :: Tree t => Grammar -> [t] -> Bool validate g tree = case filter g [tree] of [] -> False _ -> True -- | -- filter returns a filtered list of trees, given the grammar. filter :: Tree t => Grammar -> [[t]] -> [[t]] filter (Grammar g) trees = let start = Smart.lookupMain g f = filterM (MemDerive.validate g start) trees (r, _) = runState f MemDerive.newMem in r