Parse.hs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. module Gidl.Parse where
  2. import Data.List
  3. import Data.Functor.Identity
  4. import Control.Monad
  5. import Text.Parsec.Prim
  6. import Text.Parsec.Char
  7. import Text.Parsec.Token
  8. import Text.Parsec.Combinator
  9. import Text.Parsec.Language
  10. import Text.Parsec.Error
  11. import Gidl.Types
  12. import Gidl.Interface
  13. type Parser u a = ParsecT String u Identity a
  14. type ParseEnv = (TypeEnv, InterfaceEnv)
  15. emptyParseEnv :: ParseEnv
  16. emptyParseEnv = (emptyTypeEnv, emptyInterfaceEnv)
  17. getTypeEnv :: Parser ParseEnv TypeEnv
  18. getTypeEnv = fmap fst getState
  19. getInterfaceEnv :: Parser ParseEnv InterfaceEnv
  20. getInterfaceEnv = fmap snd getState
  21. setTypeEnv :: TypeEnv -> Parser ParseEnv ()
  22. setTypeEnv te = do
  23. (_, ie) <- getState
  24. setState (te, ie)
  25. setInterfaceEnv :: InterfaceEnv -> Parser ParseEnv ()
  26. setInterfaceEnv ie = do
  27. (te, _) <- getState
  28. setState (te, ie)
  29. ---
  30. lexer :: GenTokenParser String u Identity
  31. lexer = makeTokenParser haskellDef
  32. tWhiteSpace :: Parser u ()
  33. tWhiteSpace = whiteSpace lexer
  34. tInteger :: Parser u Integer
  35. tInteger = (integer lexer) <?> "integer"
  36. tNatural :: Parser u Integer
  37. tNatural = do
  38. i <- tInteger
  39. case i < 0 of
  40. True -> fail "expected positive integer"
  41. False -> return i
  42. tFloat :: Parser u Double
  43. tFloat = (float lexer) <?> "floating point number"
  44. tString :: Parser u String
  45. tString = (stringLiteral lexer) <?> "string"
  46. tSymbol :: Parser u String
  47. tSymbol = (many1 $ noneOf "()\" \t\n\r") <?> "symbol"
  48. tIdentifier :: String -> Parser u ()
  49. tIdentifier i = do
  50. s <- tSymbol
  51. case s == i of
  52. True -> return ()
  53. False -> fail ("expected identifier " ++ i)
  54. tList :: Parser u a -> Parser u a
  55. tList c = do
  56. tWhiteSpace
  57. void $ char '('
  58. tWhiteSpace
  59. r <- c
  60. tWhiteSpace
  61. void $ char ')'
  62. return r
  63. <?> "list"
  64. tPair :: Parser u a
  65. -> Parser u b
  66. -> Parser u (a, b)
  67. tPair a b = tList $ do
  68. ra <- a
  69. tWhiteSpace
  70. rb <- b
  71. return (ra, rb)
  72. tKnownPrimType :: Parser ParseEnv PrimType
  73. tKnownPrimType = do
  74. t <- tKnownType
  75. case t of
  76. PrimType p -> return p
  77. StructType n _ -> fail ("expected a known primitive type name, got " ++ n)
  78. tKnownType :: Parser ParseEnv Type
  79. tKnownType = do
  80. s <- tSymbol
  81. te <- getTypeEnv
  82. case lookupTypeName s te of
  83. Just t -> return t
  84. Nothing -> fail ("expected a known type name, got " ++ s)
  85. tStructRow :: Parser ParseEnv (Identifier, PrimType)
  86. tStructRow = tPair tSymbol tKnownPrimType
  87. <?> "struct row"
  88. tStructBody :: Parser ParseEnv [(Identifier, PrimType)]
  89. tStructBody = tList (many1 (tWhiteSpace >> tStructRow))
  90. <?> "struct body"
  91. tStructDecl :: Parser ParseEnv (TypeName, Type)
  92. tStructDecl = tList $ do
  93. tIdentifier "def-struct"
  94. tWhiteSpace
  95. n <- tSymbol
  96. b <- tStructBody
  97. return (n, StructType n b)
  98. defineType :: (TypeName, Type) -> Parser ParseEnv ()
  99. defineType (tn, t) = do
  100. te <- getTypeEnv
  101. case lookupTypeName tn te of
  102. Just _ -> fail ("type named '" ++ tn ++ "' already exists")
  103. Nothing -> setTypeEnv (insertType tn t te)
  104. defineInterface :: Interface -> Parser ParseEnv ()
  105. defineInterface i = do
  106. ie <- getInterfaceEnv
  107. case lookupInterface ina ie of
  108. Just _ -> fail ("interface named '" ++ ina ++ "' already exists")
  109. Nothing -> setInterfaceEnv (insertInterface i ie)
  110. where (Interface ina _ _) = i
  111. tNewtypeDecl :: Parser ParseEnv (TypeName, Type)
  112. tNewtypeDecl = tList $ do
  113. tIdentifier "def-newtype"
  114. tWhiteSpace
  115. n <- tSymbol
  116. tWhiteSpace
  117. c <- tKnownPrimType
  118. return (n, PrimType (Newtype n c))
  119. tEnumDecl :: Parser ParseEnv (TypeName, Type)
  120. tEnumDecl = tList $ do
  121. tIdentifier "def-enum"
  122. tWhiteSpace
  123. n <- tSymbol
  124. w <- optionMaybe (try tInteger)
  125. width <- case w of
  126. Nothing -> return Bits32
  127. Just 8 -> return Bits8
  128. Just 16 -> return Bits16
  129. Just 32 -> return Bits32
  130. Just 64 -> return Bits64
  131. _ -> fail "Expected enum bit size to be 8, 16, 32, or 64"
  132. vs <- tList $ many1 $ tPair tSymbol tNatural
  133. when (not_unique (map fst vs)) $
  134. fail "enum keys were not unique"
  135. when (not_unique (map snd vs)) $
  136. fail "enum values were not unique"
  137. -- XXX make it possible to implicitly assign numbers
  138. return (n, PrimType (EnumType n width vs))
  139. not_unique :: (Eq a) => [a] -> Bool
  140. not_unique l = nub l /= l
  141. tPermission :: Parser a Perm
  142. tPermission = do
  143. s <- tSymbol
  144. case s of
  145. "read" -> return Read
  146. "r" -> return Read
  147. "write" -> return Write
  148. "w" -> return Write
  149. "readwrite" -> return ReadWrite
  150. "rw" -> return ReadWrite
  151. _ -> fail "expected permission"
  152. tInterfaceMethod :: Parser ParseEnv (MethodName, Method)
  153. tInterfaceMethod = tList $ do
  154. n <- tSymbol
  155. m <- choice [ try tAttr, try tStream ]
  156. return (n, m)
  157. where
  158. tAttr = tList $ do
  159. tIdentifier "attr"
  160. tWhiteSpace
  161. p <- tPermission
  162. tWhiteSpace
  163. tn <- tKnownType
  164. return (AttrMethod p tn)
  165. tStream = tList $ do
  166. tIdentifier "stream"
  167. tWhiteSpace
  168. r <- tInteger
  169. tWhiteSpace
  170. tn <- tKnownType
  171. return (StreamMethod r tn)
  172. tKnownInterface :: Parser ParseEnv Interface
  173. tKnownInterface = do
  174. n <- tSymbol
  175. ie <- getInterfaceEnv
  176. case lookupInterface n ie of
  177. Just i -> return i
  178. Nothing -> fail ("expected a known interface name, got " ++ n)
  179. tInterfaceDecl :: Parser ParseEnv Interface
  180. tInterfaceDecl = tList $ do
  181. tIdentifier "def-interface"
  182. tWhiteSpace
  183. n <- tSymbol
  184. tWhiteSpace
  185. ms <- tList (many1 tInterfaceMethod)
  186. when (not_unique (map fst ms)) $
  187. fail "expected unique interface method names"
  188. tWhiteSpace
  189. ps <- optionMaybe (tList (many1 tKnownInterface))
  190. -- XXX require the ms not shadow names in inherited interfaces
  191. case ps of
  192. Just p -> return (Interface n p ms)
  193. Nothing -> return (Interface n [] ms)
  194. tDecls :: Parser ParseEnv ParseEnv
  195. tDecls = do
  196. _ <- many (choice [ try tStructDecl >>= defineType
  197. , try tNewtypeDecl >>= defineType
  198. , try tEnumDecl >>= defineType
  199. , try tInterfaceDecl >>= defineInterface
  200. ])
  201. tWhiteSpace >> eof
  202. getState
  203. parseDecls :: String -> Either ParseError ParseEnv
  204. parseDecls s = runP tDecls emptyParseEnv "" s