parsley-2.0.0.1: test/Parsley/Precedence/Parsers.hs
{-# LANGUAGE CPP, TemplateHaskellQuotes, MultiParamTypeClasses #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
{-# HLINT ignore "Redundant bracket" #-}
module Parsley.Precedence.Parsers where
import Prelude hiding (pure, (<*>), (*>), (<*), (<$>), ($>), pred)
import Parsley
import Parsley.Precedence
import Parsley.Fold (somel)
import Parsley.Char (oneOf)
import Data.Char (digitToInt)
import Parsley.Defunctionalized
#define QQ(x) (makeQ (x) [|| x ||])
data Expr = Add Expr Expr | Mul Expr Expr | Negate Expr | Num Int deriving (Eq, Show)
number :: Parser Int
number = somel QQ(\x d -> x * 10 + digitToInt d) (LIFTED 0) (oneOf ['0'..'9'])
expr :: Parser Expr
expr = precHomo (QQ(Num) <$> number)
[ ops Prefix [string "negate" $> QQ(Negate)]
, ops InfixL [char '*' $> QQ(Mul)]
, ops InfixR [char '+' $> QQ(Add)]
]
data Pred = Or Term Pred | OfTerm Term deriving (Eq, Show)
data Term = And Not Term | OfNot Not deriving (Eq, Show)
data Not = Not Not | OfAtom Atom deriving (Eq, Show)
data Atom = T | F | Parens Pred deriving (Eq, Show)
instance Subtype Atom Not where
upcast = OfAtom
downcast (OfAtom x) = Just x
downcast _ = Nothing
instance Subtype Not Term where
upcast = OfNot
downcast (OfNot x) = Just x
downcast _ = Nothing
pred = precedence $
gops InfixR [char '|' $> QQ(Or)] QQ(OfTerm) +<
sops InfixR [char '&' $> QQ(And)] +<
sops Prefix [char '!' $> QQ(Not)] +<
Atom (char 'T' $> QQ(T) <|> char 'F' $> QQ(F) <|> char '(' *> (QQ(Parens) <$> pred) <* char ')')