Parse.hs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. module Gidl.Parse where
  2. import Data.Functor.Identity
  3. import Data.Monoid
  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. type Parser u a = ParsecT String u Identity a
  13. lexer :: GenTokenParser String u Identity
  14. lexer = makeTokenParser haskellDef
  15. tWhiteSpace :: Parser u ()
  16. tWhiteSpace = whiteSpace lexer
  17. tInteger :: Parser u Integer
  18. tInteger = (integer lexer) <?> "integer"
  19. tNatural :: Parser u Integer
  20. tNatural = do
  21. i <- tInteger
  22. case i < 0 of
  23. True -> fail "expected positive integer"
  24. False -> return i
  25. tFloat :: Parser u Double
  26. tFloat = (float lexer) <?> "floating point number"
  27. tString :: Parser u String
  28. tString = (stringLiteral lexer) <?> "string"
  29. tSymbol :: Parser u String
  30. tSymbol = (many1 $ noneOf "()\" \t\n\r") <?> "symbol"
  31. tIdentifier :: String -> Parser u ()
  32. tIdentifier i = do
  33. s <- tSymbol
  34. case s == i of
  35. True -> return ()
  36. False -> fail ("expected identifier " ++ i)
  37. tList :: Parser u a -> Parser u a
  38. tList c = do
  39. tWhiteSpace
  40. void $ char '('
  41. tWhiteSpace
  42. r <- c
  43. tWhiteSpace
  44. void $ char ')'
  45. return r
  46. <?> "list"
  47. tPair :: Parser u a
  48. -> Parser u b
  49. -> Parser u (a, b)
  50. tPair a b = tList $ do
  51. ra <- a
  52. tWhiteSpace
  53. rb <- b
  54. return (ra, rb)
  55. tTypeName :: Parser TypeEnv TypeName
  56. tTypeName = do
  57. s <- tSymbol
  58. te <- getState
  59. case lookupTypeName s te of
  60. Just _ -> return s
  61. Nothing -> fail ("expected a known type name, got " ++ s)
  62. tStructRow :: Parser TypeEnv (Identifier, TypeName)
  63. tStructRow = tPair tSymbol tTypeName
  64. <?> "struct row"
  65. tStructBody :: Parser TypeEnv [(Identifier, TypeName)]
  66. tStructBody = tList (many1 (tWhiteSpace >> tStructRow))
  67. <?> "struct body"
  68. tStructDecl :: Parser TypeEnv (TypeName, Type)
  69. tStructDecl = tList $ do
  70. tIdentifier "def-struct"
  71. tWhiteSpace
  72. n <- tSymbol
  73. b <- tStructBody
  74. return (n, StructType (Struct b))
  75. defineType :: (TypeName, Type) -> Parser TypeEnv ()
  76. defineType (tn, t) = do
  77. te <- getState
  78. case lookupTypeName tn te of
  79. Just _ -> fail ("type named '" ++ tn ++ "' already exists")
  80. Nothing -> setState (insertType tn t te)
  81. tNewtypeDecl :: Parser TypeEnv (TypeName, Type)
  82. tNewtypeDecl = tList $ do
  83. tIdentifier "def-newtype"
  84. tWhiteSpace
  85. n <- tSymbol
  86. tWhiteSpace
  87. c <- tTypeName
  88. return (n, NewtypeType (Newtype c))
  89. tEnumDecl :: Parser TypeEnv (TypeName, Type)
  90. tEnumDecl = tList $ do
  91. tIdentifier "def-enum"
  92. tWhiteSpace
  93. n <- tSymbol
  94. -- XXX specify bit width, optionally
  95. vs <- tList $ many1 $ tPair tSymbol tNatural
  96. -- XXX check that symbols are unique, numbers are unique, numbers are
  97. -- ascending
  98. -- XXX make it possible to implicitly assign numbers
  99. return (n, EnumType (EnumT Bits32 vs))
  100. tDecls :: Parser TypeEnv TypeEnv
  101. tDecls = do
  102. _ <- many ((choice [try tStructDecl, try tNewtypeDecl, try tEnumDecl]) >>= defineType)
  103. getState
  104. parseDecls :: String -> Either ParseError TypeEnv
  105. parseDecls s = runP tDecls mempty "" s