Parse.hs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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. tKnownTypeName :: Parser ParseEnv TypeName
  73. tKnownTypeName = do
  74. s <- tSymbol
  75. te <- getTypeEnv
  76. case lookupTypeName s te of
  77. Just _ -> return s
  78. Nothing -> fail ("expected a known type name, got " ++ s)
  79. tStructRow :: Parser ParseEnv (Identifier, TypeName)
  80. tStructRow = tPair tSymbol tKnownTypeName
  81. <?> "struct row"
  82. tStructBody :: Parser ParseEnv [(Identifier, TypeName)]
  83. tStructBody = tList (many1 (tWhiteSpace >> tStructRow))
  84. <?> "struct body"
  85. tStructDecl :: Parser ParseEnv (TypeName, TypeDescr)
  86. tStructDecl = tList $ do
  87. tIdentifier "def-struct"
  88. tWhiteSpace
  89. n <- tSymbol
  90. b <- tStructBody
  91. return (n, StructType (Struct b))
  92. defineType :: (TypeName, TypeDescr) -> Parser ParseEnv ()
  93. defineType (tn, t) = do
  94. te <- getTypeEnv
  95. case lookupTypeName tn te of
  96. Just _ -> fail ("type named '" ++ tn ++ "' already exists")
  97. Nothing -> setTypeEnv (insertType tn t te)
  98. defineInterface :: (InterfaceName, InterfaceDescr) -> Parser ParseEnv ()
  99. defineInterface (ina, i) = do
  100. ie <- getInterfaceEnv
  101. case lookupInterface ina ie of
  102. Just _ -> fail ("interface named '" ++ ina ++ "' already exists")
  103. Nothing -> setInterfaceEnv (insertInterface ina i ie)
  104. tNewtypeDecl :: Parser ParseEnv (TypeName, TypeDescr)
  105. tNewtypeDecl = tList $ do
  106. tIdentifier "def-newtype"
  107. tWhiteSpace
  108. n <- tSymbol
  109. tWhiteSpace
  110. c <- tKnownTypeName
  111. return (n, NewtypeType (Newtype c))
  112. tEnumDecl :: Parser ParseEnv (TypeName, TypeDescr)
  113. tEnumDecl = tList $ do
  114. tIdentifier "def-enum"
  115. tWhiteSpace
  116. n <- tSymbol
  117. w <- optionMaybe (try tInteger)
  118. width <- case w of
  119. Nothing -> return Bits32
  120. Just 8 -> return Bits8
  121. Just 16 -> return Bits16
  122. Just 32 -> return Bits32
  123. Just 64 -> return Bits64
  124. _ -> fail "Expected enum bit size to be 8, 16, 32, or 64"
  125. vs <- tList $ many1 $ tPair tSymbol tNatural
  126. when (not_unique (map fst vs)) $
  127. fail "enum keys were not unique"
  128. when (not_unique (map snd vs)) $
  129. fail "enum values were not unique"
  130. -- XXX make it possible to implicitly assign numbers
  131. return (n, EnumType (EnumT width vs))
  132. not_unique :: (Eq a) => [a] -> Bool
  133. not_unique l = nub l /= l
  134. tPermission :: Parser a Perm
  135. tPermission = do
  136. s <- tSymbol
  137. case s of
  138. "read" -> return Read
  139. "r" -> return Read
  140. "write" -> return Write
  141. "w" -> return Write
  142. "readwrite" -> return ReadWrite
  143. "rw" -> return ReadWrite
  144. _ -> fail "expected permission"
  145. tInterfaceMethod :: Parser ParseEnv (MethodName, Method TypeName)
  146. tInterfaceMethod = tList $ do
  147. n <- tSymbol
  148. m <- choice [ try tAttr, try tStream ]
  149. return (n, m)
  150. where
  151. tAttr = tList $ do
  152. tIdentifier "attr"
  153. tWhiteSpace
  154. p <- tPermission
  155. tWhiteSpace
  156. tn <- tKnownTypeName
  157. return (AttrMethod p tn)
  158. tStream = tList $ do
  159. tIdentifier "stream"
  160. tWhiteSpace
  161. r <- tInteger
  162. tWhiteSpace
  163. tn <- tKnownTypeName
  164. return (StreamMethod r tn)
  165. tKnownInterfaceName :: Parser ParseEnv InterfaceName
  166. tKnownInterfaceName = do
  167. n <- tSymbol
  168. ie <- getInterfaceEnv
  169. case lookupInterface n ie of
  170. Just _ -> return n
  171. Nothing -> fail ("expected a known interface name, got " ++ n)
  172. tInterfaceDecl :: Parser ParseEnv (InterfaceName, InterfaceDescr)
  173. tInterfaceDecl = tList $ do
  174. tIdentifier "def-interface"
  175. tWhiteSpace
  176. n <- tSymbol
  177. tWhiteSpace
  178. ms <- tList (many1 tInterfaceMethod)
  179. when (not_unique (map fst ms)) $
  180. fail "expected unique interface method names"
  181. tWhiteSpace
  182. ps <- optionMaybe (tList (many1 tKnownInterfaceName))
  183. -- XXX require the ms not shadow names in inherited interfaces
  184. case ps of
  185. Just p -> return (n, Interface p ms)
  186. Nothing -> return (n, Interface [] ms)
  187. tDecls :: Parser ParseEnv ParseEnv
  188. tDecls = do
  189. _ <- many (choice [ try tStructDecl >>= defineType
  190. , try tNewtypeDecl >>= defineType
  191. , try tEnumDecl >>= defineType
  192. , try tInterfaceDecl >>= defineInterface
  193. ])
  194. tWhiteSpace >> eof
  195. getState
  196. parseDecls :: String -> Either ParseError ParseEnv
  197. parseDecls s = runP tDecls emptyParseEnv "" s