{ module ParsePkgConf( loadPackageConfig ) where #include "HsVersions.h" import PackageConfig import Lexer import DynFlags import FastString import StringBuffer import ErrUtils ( mkLocMessage ) import SrcLoc import Outputable import Panic ( GhcException(..) ) import EXCEPTION ( throwDyn ) } %token '{' { L _ ITocurly } '}' { L _ ITccurly } '[' { L _ ITobrack } ']' { L _ ITcbrack } ',' { L _ ITcomma } '=' { L _ ITequal } VARID { L _ (ITvarid $$) } CONID { L _ (ITconid $$) } STRING { L _ (ITstring $$) } INT { L _ (ITinteger $$) } %monad { P } { >>= } { return } %lexer { lexer } { L _ ITeof } %name parse %tokentype { Located Token } %% pkgconf :: { [ PackageConfig ] } : '[' ']' { [] } | '[' pkgs ']' { reverse $2 } pkgs :: { [ PackageConfig ] } : pkg { [ $1 ] } | pkgs ',' pkg { $3 : $1 } pkg :: { PackageConfig } : CONID '{' fields '}' { $3 defaultPackageConfig } fields :: { PackageConfig -> PackageConfig } : field { \p -> $1 p } | fields ',' field { \p -> $1 ($3 p) } field :: { PackageConfig -> PackageConfig } : VARID '=' pkgid {% case unpackFS $1 of "package" -> return (\p -> p{package = $3}) _other -> happyError } | VARID '=' STRING { id } -- we aren't interested in the string fields, they're all -- boring (copyright, maintainer etc.) | VARID '=' CONID {% case unpackFS $1 of { "exposed" -> case unpackFS $3 of { "True" -> return (\p -> p{exposed=True}); "False" -> return (\p -> p{exposed=False}); _ -> happyError }; "license" -> return id; -- not interested _ -> happyError } } | VARID '=' CONID STRING { id } -- another case of license | VARID '=' strlist {\p -> case unpackFS $1 of "exposedModules" -> p{exposedModules = $3} "hiddenModules" -> p{hiddenModules = $3} "importDirs" -> p{importDirs = $3} "libraryDirs" -> p{libraryDirs = $3} "hsLibraries" -> p{hsLibraries = $3} "extraLibraries" -> p{extraLibraries = $3} "extraGHCiLibraries"-> p{extraGHCiLibraries= $3} "includeDirs" -> p{includeDirs = $3} "includes" -> p{includes = $3} "hugsOptions" -> p{hugsOptions = $3} "ccOptions" -> p{ccOptions = $3} "ldOptions" -> p{ldOptions = $3} "frameworkDirs" -> p{frameworkDirs = $3} "frameworks" -> p{frameworks = $3} "haddockInterfaces" -> p{haddockInterfaces = $3} "haddockHTMLs" -> p{haddockHTMLs = $3} "depends" -> p{depends = []} -- empty list only, non-empty handled below other -> p } | VARID '=' pkgidlist {% case unpackFS $1 of "depends" -> return (\p -> p{depends = $3}) _other -> happyError } pkgid :: { PackageIdentifier } : CONID '{' VARID '=' STRING ',' VARID '=' version '}' { PackageIdentifier{ pkgName = unpackFS $5, pkgVersion = $9 } } version :: { Version } : CONID '{' VARID '=' intlist ',' VARID '=' strlist '}' { Version{ versionBranch=$5, versionTags=$9 } } pkgidlist :: { [PackageIdentifier] } : '[' pkgids ']' { $2 } -- empty list case is covered by strlist, to avoid conflicts pkgids :: { [PackageIdentifier] } : pkgid { [ $1 ] } | pkgid ',' pkgids { $1 : $3 } intlist :: { [Int] } : '[' ']' { [] } | '[' ints ']' { $2 } ints :: { [Int] } : INT { [ fromIntegral $1 ] } | INT ',' ints { fromIntegral $1 : $3 } strlist :: { [String] } : '[' ']' { [] } | '[' strs ']' { $2 } strs :: { [String] } : STRING { [ unpackFS $1 ] } | STRING ',' strs { unpackFS $1 : $3 } { happyError :: P a happyError = srcParseFail loadPackageConfig :: FilePath -> IO [PackageConfig] loadPackageConfig conf_filename = do buf <- hGetStringBuffer conf_filename let loc = mkSrcLoc (mkFastString conf_filename) 1 0 case unP parse (mkPState buf loc defaultDynFlags) of PFailed span err -> throwDyn (InstallationError (showSDoc (mkLocMessage span err))) POk _ pkg_details -> do return pkg_details }