packages feed

parsley-2.0.0.0: test/Parsley/Precedence/Parsers.hs

{-# LANGUAGE TemplateHaskellQuotes, MultiParamTypeClasses #-}
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)

data Expr = Add Expr Expr | Mul Expr Expr | Negate Expr | Num Int deriving (Eq, Show)

number :: Parser Int
number = somel [| \x d -> x * 10 + digitToInt d |] [|0|] (oneOf ['0'..'9'])

expr :: Parser Expr
expr = precHomo ([|Num|] <$> number)
                [ ops Prefix [string "negate" $> [|Negate|]]
                , ops InfixL [char '*' $> [|Mul|]]
                , ops InfixR [char '+' $> [|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 '|' $> [|Or|]] [|OfTerm|] +<
  sops InfixR [char '&' $> [|And|]]           +<
  sops Prefix [char '!' $> [|Not|]]           +<
  Atom (char 'T' $> [|T|] <|> char 'F' $> [|F|] <|> char '(' *> ([|Parens|] <$> pred) <* char ')')