OpenGLRaw-2.0.0.0: RegistryProcessor/src/DeclarationParser.hs
-- A very simple-minded parser for C declarations of the following syntax:
-- "const"? type-specifier ("*" "const"?)* identifier ("[" number "]")?
module DeclarationParser ( parse ) where
import Control.Monad
import Data.Char
import Text.ParserCombinators.ReadP
parse :: String -> Either String (String, Int)
parse s =
case readP_to_S parseDeclaration s of
[(x, "")] -> Right x
_ -> Left $ "could not parse \"" ++ s ++ "\""
parseDeclaration :: ReadP (String, Int)
parseDeclaration = do
optionalConst
typeSpec <- parseTypeSpecifier
pointers <- many' (token "*" >> optionalConst)
_ <- parseIdentifier
a <- parseArray
skipSpaces
return (typeSpec, length pointers + a)
optionalConst :: ReadP ()
optionalConst = option' () (token "const" >> return ())
parseTypeSpecifier :: ReadP String
parseTypeSpecifier = choice' [
token "void" >> return "()",
token "float" >> return "CFloat",
token "double" >> return "CDouble",
token "int32_t" >> return "Int32",
token "int64_t" >> return "Int64",
do c <- option' "CChar" (token "signed" >> return "CSChar")
choice' [
token "char" >> return c,
token "short" >> return "CShort",
token "int" >> return "CInt",
token "long" >> choice' [token "long" >> return "CLLong",
return "CLong"]],
do _ <- token "unsigned"
choice' [
token "char" >> return "CUChar",
token "short" >> return "CUShort",
token "int" >> return "CUInt",
token "long" >> choice' [token "long" >> return "CULLong",
return "CULong"]],
token "struct" >> parseIdentifier >> return "()", -- Hmmm...
token "GLvoid" >> return "()", -- glGetPerfQueryDataINTEL still mentions this
parseIdentifier ]
parseIdentifier :: ReadP String
parseIdentifier = do
skipSpaces
x <- satisfy (\c -> isAlpha c || c == '_')
xs <- munch (\c ->isAlphaNum c || c == '_')
return (x:xs)
parseArray :: ReadP Int
parseArray = choice' [
do _ <- token "["
skipSpaces
_ <- munch1 isDigit
_ <- token "]"
return 1,
return 0 ]
token :: String -> ReadP String
token s = skipSpaces >> string s
-- deterministic versions
choice' :: [ReadP a] -> ReadP a
choice' = foldr (<++) pfail
option' :: a -> ReadP a -> ReadP a
option' x p = choice' [p, return x]
many' :: ReadP a -> ReadP [a]
many' = option' [] . many1'
many1' :: ReadP a -> ReadP [a]
many1' p = liftM2 (:) p (many' p)