2 -- This parser is based on ParsedPkgConf.y in compiler/main/
3 -- It's supposed to do the same thing, but without depending on other GHC modules.
4 -- The disadvantage is the less sophisticated error reporting, and it's probably
5 -- slower because it doesn't use FastStrings.
7 module ParsePkgConfLite{- ( parsePackageConfig, parseOnePackageConfig ) -}where
9 import Package ( PackageConfig(..), defaultPackageConfig )
10 import Char(isSpace, isAlpha, isAlphaNum, isUpper)
23 STRING { ITstring $$ }
30 pkgconf :: { [ PackageConfig ] }
32 | '[' pkgs ']' { reverse $2 }
34 pkgs :: { [ PackageConfig ] }
36 | pkgs ',' pkg { $3 : $1 }
38 pkg :: { PackageConfig }
39 : CONID '{' fields '}' { $3 defaultPackageConfig }
41 fields :: { PackageConfig -> PackageConfig }
42 : field { \p -> $1 p }
43 | fields ',' field { \p -> $1 ($3 p) }
45 field :: { PackageConfig -> PackageConfig }
48 "name" -> p{name = $3}
49 _ -> error "unknown key in config file" }
53 "auto" -> p{auto = $3};
58 "import_dirs" -> p{import_dirs = $3}
59 "library_dirs" -> p{library_dirs = $3}
60 "hs_libraries" -> p{hs_libraries = $3}
61 "extra_libraries" -> p{extra_libraries = $3}
62 "include_dirs" -> p{include_dirs = $3}
63 "c_includes" -> p{c_includes = $3}
64 "package_deps" -> p{package_deps = $3}
65 "extra_ghc_opts" -> p{extra_ghc_opts = $3}
66 "extra_cc_opts" -> p{extra_cc_opts = $3}
67 "extra_ld_opts" -> p{extra_ld_opts = $3}
68 "framework_dirs" -> p{framework_dirs = $3}
69 "extra_frameworks"-> p{extra_frameworks= $3}
73 strlist :: { [String] }
75 | '[' strs ']' { reverse $2 }
79 | strs ',' STRING { $3 : $1 }
82 : CONID {% case $1 of {
85 _ -> error ("unknown constructor in config file: " ++ $1) } }
98 lexer :: String -> [Token]
101 lexer ('{':cs) = ITocurly : lexer cs
102 lexer ('}':cs) = ITccurly : lexer cs
103 lexer ('[':cs) = ITobrack : lexer cs
104 lexer (']':cs) = ITcbrack : lexer cs
105 lexer (',':cs) = ITcomma : lexer cs
106 lexer ('=':cs) = ITequal : lexer cs
107 lexer ('"':cs) = lexString cs ""
109 | isSpace c = lexer cs
110 | isAlpha c = lexID (c:cs) where
111 lexer _ = error "Unexpected token"
113 lexID cs = (if isUpper (head cs) then ITconid else ITvarid) id : lexer rest
115 (id,rest) = break (\c -> c /= '_' && not (isAlphaNum c)) cs
117 lexString ('"':cs) s = ITstring (reverse s) : lexer cs
118 lexString ('\\':c:cs) s = lexString cs (c:s)
119 lexString (c:cs) s = lexString cs (c:s)
121 happyError _ = error "Couldn't parse package configuration."
123 parsePackageConfig :: String -> [PackageConfig]
124 parsePackageConfig = parse . lexer
126 parseOnePackageConfig :: String -> PackageConfig
127 parseOnePackageConfig = parseOne . lexer