{-# LANGUAGE OverloadedStrings #-} -- | Example parsers module Looksee.Examples ( Json (..) , jsonParser , Arith (..) , arithParser , Atom (..) , Sexp (..) , sexpParser ) where import Control.Applicative ((<|>)) import Data.Char (isAlpha) import Data.Scientific (Scientific) import Data.Sequence (Seq) import Data.Text (Text) import Data.Void (Void) import Looksee ( Parser , altP , betweenP , decP , doubleStrP , infixRP , intP , labelP , sciP , sepByP , space1P , stripEndP , stripP , stripStartP , takeWhile1P , textP_ ) -- | A JSON value data Json = JsonNull | JsonString !Text | JsonArray !(Seq Json) | JsonObject !(Seq (Text, Json)) | JsonNum !Scientific | JsonBool !Bool deriving stock (Eq, Ord, Show) -- | A JSON parser (modulo some differences in numeric parsing) jsonParser :: Parser Void Json jsonParser = stripP valP where valP = altP [ labelP "null" nullP , labelP "bool" boolP , labelP "str" strP , labelP "array" arrayP , labelP "object" objectP , labelP "num" numP ] boolP = JsonBool <$> (False <$ textP_ "false" <|> True <$ textP_ "true") numP = JsonNum <$> sciP nullP = JsonNull <$ textP_ "null" strP = JsonString <$> doubleStrP arrayP = JsonArray <$> betweenP (stripEndP (textP_ "[")) (textP_ "]") (sepByP (stripEndP (textP_ ",")) (stripEndP valP)) pairP = do s <- doubleStrP stripP (textP_ ":") v <- valP pure (s, v) objectP = JsonObject <$> betweenP (stripEndP (textP_ "{")) (textP_ "}") (sepByP (stripEndP (textP_ ",")) (stripEndP pairP)) -- | An arithmetic expression data Arith = ArithNum !Rational | ArithVar !Text | ArithNeg Arith | ArithMul Arith Arith | ArithAdd Arith Arith | ArithSub Arith Arith deriving stock (Eq, Ord, Show) -- | A parser for arithmetic expressions arithParser :: Parser Void Arith arithParser = stripP rootP where identP = takeWhile1P isAlpha binaryP op f = fmap (uncurry f) (infixRP op (stripEndP rootP) (stripStartP rootP)) unaryP op f = textP_ op *> fmap f rootP rootP = altP [ labelP "add" (binaryP "+" ArithAdd) , labelP "sub" (binaryP "-" ArithSub) , labelP "mul" (binaryP "*" ArithMul) , labelP "neg" (unaryP "-" ArithNeg) , labelP "paren" (betweenP (stripEndP (textP_ "(")) (textP_ ")") (stripEndP rootP)) , labelP "num" (ArithNum <$> decP) , labelP "var" (ArithVar <$> identP) ] -- | Leaves of S-expression trees data Atom = AtomIdent !Text | AtomString !Text | AtomInt !Integer | AtomSci !Scientific deriving stock (Eq, Ord, Show) -- | An S-expression data Sexp = SexpAtom !Atom | SexpList !(Seq Sexp) deriving stock (Eq, Ord, Show) -- | A parser for S-expressions sexpParser :: Parser Void Sexp sexpParser = stripP rootP where identP = takeWhile1P isAlpha atomP = altP [ labelP "ident" (AtomIdent <$> identP) , labelP "string" (AtomString <$> doubleStrP) , labelP "int" (AtomInt <$> intP) , labelP "sci" (AtomSci <$> sciP) ] listP = betweenP (stripEndP (textP_ "(")) (textP_ ")") (stripEndP (sepByP space1P rootP)) rootP = altP [ labelP "atom" (SexpAtom <$> atomP) , labelP "list" (SexpList <$> listP) ]