R7RS.hs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. {-# LANGUAGE StandaloneDeriving #-}
  2. {-# LANGUAGE OverloadedStrings #-}
  3. {-# LANGUAGE FlexibleContexts #-}
  4. {-# LANGUAGE UndecidableInstances #-}
  5. module Data.SCargot.Scheme.R7RS where
  6. import Data.Char (chr, isAlphaNum)
  7. import Data.Text (Text)
  8. import qualified Data.Text as T
  9. import Data.String (IsString(..))
  10. import Data.SCargot.Common
  11. import Data.SCargot.General
  12. import Data.SCargot.Repr.Basic
  13. import Data.Word (Word8)
  14. import Text.Parsec
  15. import Text.Parsec.Text (Parser)
  16. instance IsString (SchemeAtom c) where
  17. fromString = ScmIdent . fromString
  18. -- | A Scheme value type. This is strictly larger than just
  19. -- 'atoms', as they may include things like vectors or
  20. -- labeled data, which must be able to refer to yet other
  21. -- s-expressions. Thus, the SchemeAtom type must be able
  22. -- to itself refer to the carrier type in which it is
  23. -- contained.
  24. data SchemeAtom carrier
  25. = ScmIdent Text
  26. | ScmBool Bool
  27. | ScmString Text
  28. | ScmNum Integer
  29. | ScmChar Char
  30. | ScmVec [carrier (SchemeAtom carrier)]
  31. | ScmByteVec [Word8]
  32. | ScmLabeledDatum Int (carrier (SchemeAtom carrier))
  33. | ScmLabelReference Int
  34. -- | Scheme has a lot of numbers.
  35. data SchemeNumber
  36. = ScmNumber
  37. | ScmComplexNumber Double Double
  38. | ScmRealNumber Double
  39. | ScmRationalNumber Rational
  40. | ScmInteger Integer
  41. deriving (Eq, Show)
  42. deriving instance Show (c (SchemeAtom c)) => Show (SchemeAtom c)
  43. deriving instance Eq (c (SchemeAtom c)) => Eq (SchemeAtom c)
  44. badSpec :: SExprSpec (SchemeAtom SExpr) (SExpr (SchemeAtom SExpr))
  45. badSpec = mkSpec (ScmIdent . T.pack <$> many1 (satisfy isAlphaNum)) undefined
  46. withQuasiQuote :: SExprSpec (SchemeAtom SExpr) (SExpr (SchemeAtom SExpr))
  47. -> SExprSpec (SchemeAtom SExpr) (SExpr (SchemeAtom SExpr))
  48. withQuasiQuote spec = addReader '`' (fmap (go "quasiquote"))
  49. $ addReader ',' unquote
  50. $ addReader '\'' (fmap (go "quote"))
  51. $ spec
  52. where go name s = name ::: s ::: Nil
  53. unquote p = char '@' *> fmap (go "unquote-splicing") p
  54. <|> fmap (go "unquote") p
  55. octoReader :: Reader (SchemeAtom SExpr)
  56. octoReader pSexpr =
  57. string "true" *> pure (A (ScmBool True))
  58. <|> string "false" *> pure (A (ScmBool False))
  59. <|> char 't' *> pure (A (ScmBool True))
  60. <|> char 'f' *> pure (A (ScmBool False))
  61. <|> char '\\' *> fmap (A . ScmChar) characterConstant
  62. <|> char '(' *> fmap (A . ScmVec) (vector pSexpr)
  63. <|> string "u8(" *> fmap A bytevec
  64. <|> do n <- read <$> many1 digit
  65. (char '#' *> pure (A (ScmLabelReference n)) <|>
  66. char '=' *> fmap (A . ScmLabeledDatum n) pSexpr)
  67. vector :: Parser (SExpr (SchemeAtom SExpr)) -> Parser [SExpr (SchemeAtom SExpr)]
  68. vector pSExpr =
  69. (char ')' *> pure []) <|> ((:) <$> pSExpr <*> vector pSExpr)
  70. bytevec :: Parser (SchemeAtom SExpr)
  71. bytevec = undefined
  72. characterConstant :: Parser Char
  73. characterConstant = namedCharacter
  74. <|> (chr . fromInteger <$> (char 'x' *> hexNumber))
  75. <|> anyCharacter
  76. where namedCharacter = string "alarm" *> pure '\x07'
  77. <|> string "backspace" *> pure '\x08'
  78. <|> string "delete" *> pure '\x7f'
  79. <|> string "escape" *> pure '\x1b'
  80. <|> string "newline" *> pure '\x0a'
  81. <|> string "null" *> pure '\x00'
  82. <|> string "return" *> pure '\x0d'
  83. <|> string "space" *> pure ' '
  84. <|> string "tab" *> pure '\x09'
  85. anyCharacter = anyToken
  86. r7rsNum :: Int -> Parser Int
  87. r7rsNum radix = prefix <*> complex
  88. where prefix = radix <*> exactness <|> exactness <*> radix
  89. complex = real
  90. <|> real <* char '@' <*> real
  91. <|> real <* char '+' <*> ureal <* char 'i'
  92. <|> real <* char '-' <*> ureal <* char 'i'
  93. <|> real <* char '+' <* char 'i'
  94. <|> real <* char '-' <* char 'i'
  95. <|> real <*> infnan <* char 'i'
  96. <|> char '+' *> ureal <* char 'i'
  97. <|> char '-' *> ureal <* char 'i'
  98. <|> infnan <* char 'i'
  99. <|> string "+i"
  100. <|> string "-i"
  101. real = ($) <$> sign <*> ureal
  102. <|> infnan