219 lines
6.2 KiB
Plaintext
219 lines
6.2 KiB
Plaintext
--
|
|
-- Copyright (C) 2005 Sean Seefried - http://www.cse.unsw.edu.au/~sseefried
|
|
--
|
|
-- This library is free software; you can redistribute it and/or
|
|
-- modify it under the terms of the GNU Lesser General Public
|
|
-- License as published by the Free Software Foundation; either
|
|
-- version 2.1 of the License, or (at your option) any later version.
|
|
--
|
|
-- This library is distributed in the hope that it will be useful,
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
-- Lesser General Public License for more details.
|
|
--
|
|
-- You should have received a copy of the GNU Lesser General Public
|
|
-- License along with this library; if not, write to the Free Software
|
|
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
-- USA
|
|
--
|
|
|
|
--
|
|
-- Taken (apart from the most minor of alterations) from
|
|
-- ghc/utils/ghc-pkg/ParsePkgConfLite.hs from GHC 6.2.2 source tree
|
|
-- and then modified to mimic the behaviour of the parser within
|
|
-- ghc/compiler/main/ParsePkgConf.y in GHC 6.4, without importing
|
|
-- heavy-weight infrastructure from the GHC source tree such as module
|
|
-- FastString, Lexer, etc.
|
|
--
|
|
-- (c) Copyright 2002, The University Court of the University of Glasgow.
|
|
--
|
|
|
|
{
|
|
{-# OPTIONS -w #-}
|
|
|
|
module System.Plugins.ParsePkgConfCabal (
|
|
parsePkgConf, parseOnePkgConf
|
|
) where
|
|
|
|
import Distribution.InstalledPackageInfo
|
|
import Distribution.Package
|
|
import Distribution.Version
|
|
|
|
import Data.Char ( isSpace, isAlpha, isAlphaNum, isUpper, isDigit )
|
|
import Data.List ( break )
|
|
|
|
}
|
|
|
|
%token
|
|
'{' { ITocurly }
|
|
'}' { ITccurly }
|
|
'[' { ITobrack }
|
|
']' { ITcbrack }
|
|
',' { ITcomma }
|
|
'=' { ITequal }
|
|
VARID { ITvarid $$ }
|
|
CONID { ITconid $$ }
|
|
STRING { ITstring $$ }
|
|
INT { ITinteger $$ }
|
|
|
|
%name parse pkgconf
|
|
%name parseOne pkg
|
|
%tokentype { 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
|
|
{\p -> case $1 of
|
|
"package" -> p {package = $3}
|
|
_ -> error "unknown key in config file" }
|
|
|
|
| VARID '=' STRING { id }
|
|
-- we aren't interested in the string fields, they're all
|
|
-- boring (copyright, maintainer etc.)
|
|
|
|
| VARID '=' CONID
|
|
{ case $1 of {
|
|
"exposed" ->
|
|
case $3 of {
|
|
"True" -> (\p -> p {exposed=True});
|
|
"False" -> (\p -> p {exposed=False});
|
|
_ -> error "exposed must be either True or False" };
|
|
"license" -> id; -- not interested
|
|
_ -> error "unknown constructor" }
|
|
}
|
|
|
|
| VARID '=' CONID STRING { id }
|
|
-- another case of license
|
|
|
|
| VARID '=' strlist
|
|
{\p -> case $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}
|
|
"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 $1 of
|
|
"depends" -> (\p -> p{depends = $3})
|
|
_other -> error "unknown key in config file"
|
|
}
|
|
|
|
|
|
pkgid :: { PackageIdentifier }
|
|
: CONID '{' VARID '=' STRING ',' VARID '=' version '}'
|
|
{ PackageIdentifier{ pkgName = $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 ']' { reverse $2 }
|
|
|
|
strs :: { [String] }
|
|
: STRING { [ $1 ] }
|
|
| strs ',' STRING { $3 : $1 }
|
|
|
|
{
|
|
|
|
type PackageConfig = InstalledPackageInfo
|
|
|
|
defaultPackageConfig = emptyInstalledPackageInfo
|
|
|
|
data Token
|
|
= ITocurly
|
|
| ITccurly
|
|
| ITobrack
|
|
| ITcbrack
|
|
| ITcomma
|
|
| ITequal
|
|
| ITvarid String
|
|
| ITconid String
|
|
| ITstring String
|
|
| ITinteger Int
|
|
|
|
lexer :: String -> [Token]
|
|
|
|
lexer [] = []
|
|
lexer ('{':cs) = ITocurly : lexer cs
|
|
lexer ('}':cs) = ITccurly : lexer cs
|
|
lexer ('[':cs) = ITobrack : lexer cs
|
|
lexer (']':cs) = ITcbrack : lexer cs
|
|
lexer (',':cs) = ITcomma : lexer cs
|
|
lexer ('=':cs) = ITequal : lexer cs
|
|
lexer ('"':cs) = lexString cs ""
|
|
lexer (c:cs)
|
|
| isSpace c = lexer cs
|
|
| isAlpha c = lexID (c:cs)
|
|
| isDigit c = lexInt (c:cs)
|
|
lexer _ = error ( "Unexpected token")
|
|
|
|
lexID cs = (if isUpper (head cs) then ITconid else ITvarid) id : lexer rest
|
|
where
|
|
(id,rest) = break (\c -> c /= '_' && not (isAlphaNum c)) cs
|
|
|
|
lexInt cs = let (intStr, rest) = span isDigit cs
|
|
in ITinteger (read intStr) : lexer rest
|
|
|
|
|
|
lexString ('"':cs) s = ITstring (reverse s) : lexer cs
|
|
lexString ('\\':c:cs) s = lexString cs (c:s)
|
|
lexString (c:cs) s = lexString cs (c:s)
|
|
|
|
happyError _ = error "Couldn't parse package configuration."
|
|
|
|
parsePkgConf :: String -> [PackageConfig]
|
|
parsePkgConf = parse . lexer
|
|
|
|
parseOnePkgConf :: String -> PackageConfig
|
|
parseOnePkgConf = parseOne . lexer
|
|
|
|
}
|