Basic.hs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. {-# LANGUAGE OverloadedStrings #-}
  2. module Data.SCargot.Language.Basic
  3. ( -- * Spec
  4. -- $descr
  5. basicParser
  6. , basicPrinter
  7. , locatedBasicParser
  8. ) where
  9. import Control.Applicative ((<$>))
  10. import Data.Char (isAlphaNum)
  11. import Text.Parsec (many1, satisfy)
  12. import Data.Text (Text, pack)
  13. import Data.Functor.Identity (Identity)
  14. import Text.Parsec.Prim (ParsecT)
  15. import Data.SCargot.Common (Located, located)
  16. import Data.SCargot.Repr.Basic (SExpr)
  17. import Data.SCargot ( SExprParser
  18. , SExprPrinter
  19. , mkParser
  20. , flatPrint
  21. )
  22. isAtomChar :: Char -> Bool
  23. isAtomChar c = isAlphaNum c
  24. || c == '-' || c == '*' || c == '/'
  25. || c == '+' || c == '<' || c == '>'
  26. || c == '=' || c == '!' || c == '?'
  27. pToken :: ParsecT Text a Identity Text
  28. pToken = pack <$> many1 (satisfy isAtomChar)
  29. -- $descr
  30. -- The 'basicSpec' describes S-expressions whose atoms are simply
  31. -- text strings that contain alphanumeric characters and a small
  32. -- set of punctuation. It does no parsing of numbers or other data
  33. -- types, and will accept tokens that typical Lisp implementations
  34. -- would find nonsensical (like @77foo@).
  35. --
  36. -- Atoms recognized by the 'basicSpec' are any string matching the
  37. -- regular expression @[A-Za-z0-9+*<>/=!?-]+@.
  38. -- | A 'SExprParser' that understands atoms to be sequences of
  39. -- alphanumeric characters as well as the punctuation
  40. -- characters @[-*/+<>=!?]@, and does no processing of them.
  41. --
  42. -- >>> decode basicParser "(1 elephant)"
  43. -- Right [SCons (SAtom "1") (SCons (SAtom "elephant") SNil)]
  44. basicParser :: SExprParser Text (SExpr Text)
  45. basicParser = mkParser pToken
  46. -- | A 'basicParser' which produces 'Located' values
  47. --
  48. -- >>> decode locatedBasicParser $ pack "(1 elephant)"
  49. -- Right [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 3)) "1")) (SCons (SAtom (At (Span (line 1, column 4) (line 1, column 12)) "elephant")) SNil)]
  50. --
  51. -- >>> decode locatedBasicParser $ pack "(let ((x 1))\n x)"
  52. -- Right [SCons (SAtom (At (Span (line 1, column 2) (line 1, column 5)) "let")) (SCons (SCons (SCons (SAtom (At (Span (line 1, column 8) (line 1, column 9)) "x")) (SCons (SAtom (At (Span (line 1, column 10) (line 1, column 11)) "1")) SNil)) SNil) (SCons (SAtom (At (Span (line 2, column 3) (line 2, column 4)) "x")) SNil))]
  53. locatedBasicParser :: SExprParser (Located Text) (SExpr (Located Text))
  54. locatedBasicParser = mkParser $ located pToken
  55. -- | A 'SExprPrinter' that prints textual atoms directly (without quoting
  56. -- or any other processing) onto a single line.
  57. --
  58. -- >>> encode basicPrinter [L [A "1", A "elephant"]]
  59. -- "(1 elephant)"
  60. basicPrinter :: SExprPrinter Text (SExpr Text)
  61. basicPrinter = flatPrint id