Skip to content

Instantly share code, notes, and snippets.

@aisamanra
Created September 4, 2023 01:45
Show Gist options
  • Save aisamanra/ddbee6b259b6db9380441f580a6fd91d to your computer and use it in GitHub Desktop.
Save aisamanra/ddbee6b259b6db9380441f580a6fd91d to your computer and use it in GitHub Desktop.
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Control.Applicative ((<|>))
import qualified Data.SCargot as SCargot
import qualified Data.SCargot.Language.Basic as SCargot
import Data.SCargot.Repr.Basic
import Data.Text (Text)
import qualified Text.Parsec as Parsec
-- This takes an S-expression `x` and turns it into `(quote x)`
quoteExpression :: SExpr Text -> SExpr Text
quoteExpression expr = L ["quote", expr]
-- A reader macro is actually a `parsec` parser: this takes `parse`, a
-- parser which parses a single s-expression, and can do whatever it
-- wants with it. In this case, our "reader macro" just parses one
-- expression and wraps it in `(quote ...)`.
quoteReaderMacro :: SCargot.Reader Text
quoteReaderMacro parse = fmap quoteExpression parse
-- This reader macro is slightly more involved: this will parse zero
-- or more s-expressions, terminating when it sees the character ']'.
vecReaderMacro :: SCargot.Reader Text
vecReaderMacro parse =
(Parsec.char ']' *> pure SNil) <|>
(SCons <$> parse <*> vecReaderMacro parse)
parser :: SCargot.SExprParser Text (SExpr Text)
parser =
-- install the quote reader to be invoked if we see a single quote
SCargot.addReader '\'' quoteReaderMacro $
-- install the vec reader to be invoked if we see a square bracket
SCargot.addReader '[' vecReaderMacro $
-- use the "basic" parser which just interprets aphanumeric
-- sequences as atoms
SCargot.basicParser
main :: IO ()
main =
-- we can see this parses successfully, producing the same parse
-- tree we'd get if we supplied the string
-- "(let (x (quote foo)) x)"
print (SCargot.decode parser "(let [x 'foo] x)")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment