{-# LANGUAGE RecursiveDo #-}
module Issue11 where
import Control.Applicative
import Test.Tasty
import Test.Tasty.HUnit as HU

import Text.Earley
import Text.Earley.Mixfix

tests :: TestTree
tests = testGroup "Issue 11"
  [ let x = words "+ + 5 6 7" in
    HU.testCase "1" $
    fullParses (parser $ grammar LeftAssoc) x
    @?= (,) [] Report {position = 1, expected = [], unconsumed = drop 1 x}
  , let x = words "+ 5 + 6 7" in
    HU.testCase "2" $
    fullParses (parser $ grammar LeftAssoc) x
    @?= (,) [] Report {position = 2, expected = [], unconsumed = drop 2 x}
  , let x = words "+ 5 6" in
    HU.testCase "3" $
    fullParses (parser $ grammar LeftAssoc) x
    @?= (,) [Plus (Var "5") (Var "6")]
            Report {position = 3, expected = [], unconsumed = []}
  , let x = words "+ + 5 6 7" in
    HU.testCase "4" $
    fullParses (parser $ grammar RightAssoc) x
    @?= (,) [Plus (Plus (Var "5") (Var "6")) (Var "7")]
            Report {position = 5, expected = [], unconsumed = []}
  , let x = words "+ 5 + 6 7" in
    HU.testCase "5" $
    fullParses (parser $ grammar RightAssoc) x
    @?= (,) [Plus (Var "5") (Plus (Var "6") (Var "7"))]
            Report {position = 5, expected = [], unconsumed = []}
  , let x = words "+ 5 6" in
    HU.testCase "6" $
    fullParses (parser $ grammar RightAssoc) x
    @?= (,) [Plus (Var "5") (Var "6")]
            Report {position = 3, expected = [], unconsumed = []}
  , let x = words "+ + 5 6 7" in
    HU.testCase "7" $
    fullParses (parser $ grammar NonAssoc) x
    @?= (,) [Plus (Plus (Var "5") (Var "6")) (Var "7")]
            Report {position = 5, expected = [], unconsumed = []}
  , let x = words "+ 5 + 6 7" in
    HU.testCase "8" $
    fullParses (parser $ grammar NonAssoc) x
    @?= (,) [Plus (Var "5") (Plus (Var "6") (Var "7"))]
            Report {position = 5, expected = [], unconsumed = []}
  , let x = words "+ 5 6" in
    HU.testCase "9" $
    fullParses (parser $ grammar NonAssoc) x
    @?= (,) [Plus (Var "5") (Var "6")]
            Report {position = 3, expected = [], unconsumed = []}
  ]

data AST
  = Var String
  | Plus AST AST
  deriving (Eq, Ord, Show)

grammar :: Associativity -> Grammar r (Prod r String String AST)
grammar a = mdo
    atomicExpr <- rule $ Var <$> satisfy (/= "+")

    expr <- mixfixExpression
               [[([Just (token "+"), Nothing, Nothing], a)]]
               atomicExpr
               (\x y -> case (x,y) of
                  ([Just "+", Nothing, Nothing], [e1,e2]) -> Plus e1 e2
                  _ -> undefined)

    return expr
