packages feed

distributors-0.4.0.0: test/Examples/Arithmetic.hs

module Examples.Arithmetic
  ( Arith (..)
  , arithGrammar
  , arithExamples
  ) where

import Control.Applicative
import Control.Lens
import Control.Lens.Grammar
import Numeric.Natural

data Arith
  = Num Natural
  | Add Arith Arith
  | Mul Arith Arith
  deriving stock (Eq, Ord, Show, Read)

makePrisms ''Arith

arithGrammar :: Grammar Char Arith
arithGrammar = ruleRec "arith" sumG
  where
    sumG arith = rule "sum" $
      chain1 Left _Add (sepWith "+") (prodG arith)
    prodG arith = rule "product" $
      chain1 Left _Mul (sepWith "*") (factorG arith)
    factorG arith = rule "factor" $
      number <|> terminal "(" >* arith *< terminal ")"
    number = rule "number" $
      _Num . iso show read >? someP (asIn @Char DecimalNumber)

arithExamples :: [(Arith, String)]
arithExamples =
  [ (Num 42, "42")
  , (Add (Num 1) (Num 2), "1+2")
  , (Add (Mul (Num 2) (Num 3)) (Num 4), "2*3+4")
  , (Mul (Num 2) (Add (Num 3) (Num 4)), "2*(3+4)")
  , (Add (Add (Num 1) (Mul (Num 2) (Num 3))) (Num 4), "1+2*3+4")
  ]