{-# LANGUAGE CPP #-} {-# LANGUAGE Arrows #-} {-# OPTIONS_GHC -Wall #-} ----------------------------------------------------------------------------- -- | -- Copyright : (C) 2014 Edward Kmett and Gabríel Arthúr Pétursson -- License : BSD-style (see the file LICENSE) -- Maintainer : Edward Kmett -- Stability : experimental -- Portability : portable -- ---------------------------------------------------------------------------- module Parser ( parseFile ) where import Registry import Text.XML.HXT.Core #ifdef HLINT {-# ANN module "HLint: ignore Reduce duplication" #-} #endif to :: ArrowXml a => String -> a XmlTree XmlTree to name = hasName name <<< isElem <<< getChildren perhaps :: ArrowIf a => a b c -> a b (Maybe c) perhaps x = (arr Just <<< x) `orElse` arr (const Nothing) parseCommand :: ArrowXml a => a XmlTree Command parseCommand = proc x -> do command <- to "command" -< x name <- getText <<< getChildren <<< to "name" <<< to "proto" -< command typ <- parseType <<< to "proto" -< command params <- listA $ to "param" >>> parseType &&& (getText <<< getChildren <<< to "name") -< command returnA -< Command name typ params parseEnum :: ArrowXml a => a XmlTree Enumeratee parseEnum = proc x -> do enum <- to "enum" -< x name <- getAttrValue0 "name" -< enum value <- getAttrValue0 "value" -< enum returnA -< Enumeratee name value parseExtension :: ArrowXml a => a XmlTree Extension parseExtension = proc x -> do extension <- to "extension" -< x name <- getAttrValue0 "name" -< extension supported <- getAttrValue "supported" -< extension require <- listA $ parseRequire <<< to "require" -< extension returnA -< Extension name supported require parseFeature :: ArrowXml a => a XmlTree Feature parseFeature = proc x -> do name <- getAttrValue0 "name" -< x require <- listA $ parseRequire <<< to "require" -< x remove <- listA $ parseRemove <<< to "remove" -< x returnA -< Feature name require remove parseGroup :: ArrowXml a => a XmlTree Group parseGroup = proc x -> do group <- to "group" -< x name <- getAttrValue0 "name" -< group enum <- listA $ getAttrValue0 "name" <<< to "enum" -< group returnA -< Group name enum parseRemove :: ArrowXml a => a XmlTree Remove parseRemove = proc x -> do profile <- getAttrValue "profile" -< x comment <- getAttrValue "comment" -< x enums <- listA $ getAttrValue0 "name" <<< to "enum" -< x commands <- listA $ getAttrValue0 "name" <<< to "command" -< x returnA -< Remove profile comment enums commands parseRequire :: ArrowXml a => a XmlTree Require parseRequire = proc x -> do comment <- getAttrValue "comment" -< x enums <- listA $ getAttrValue0 "name" <<< to "enum" -< x commands <- listA $ getAttrValue0 "name" <<< to "command" -< x profile <- getAttrValue "profile" -< x returnA -< Require enums commands comment profile parseType :: ArrowXml a => a XmlTree Type parseType = proc x -> do ptype <- perhaps $ getText <<< getChildren <<< to "ptype" -< x pointer <- (getText <<< getChildren) >. elem '*' . concat -< x returnA -< Type { typeName = ptype , typePointer = pointer } parse :: IOSLA (XIOState ()) XmlTree Registry parse = proc x -> do registry <- to "registry" -< x groups <- listA $ parseGroup <<< to "groups" -< registry enums <- listA $ parseEnum <<< to "enums" -< registry extensions <- listA $ parseExtension <<< to "extensions" -< registry commands <- listA $ parseCommand <<< to "commands" -< registry features <- listA $ parseFeature <<< to "feature" -< registry returnA -< Registry { registryCommands = commands , registryEnums = enums , registryExtensions = extensions , registryFeatures = features , registryGroups = groups } parseFile :: String -> IO Registry parseFile file = return . head =<< runX (readDocument [withRemoveWS yes] file >>> parse)