packages feed

datafix-0.0.1.0: tests/FirstFollow.hs

{-# LANGUAGE FlexibleContexts #-}

module FirstFollow where

import           Prelude hiding (seq, exp)

import           SetRecurrences.FirstFollow
import qualified Data.Set as Set
import           Test.Tasty
import           Test.Tasty.HUnit

tests :: [TestTree]
tests =
  [ testGroup "Dyck"
      [ testFirst 3 dyck "S(S)" ["(((", "(()", "()", "()("]
      , testFollow 3 dyck 'S' ["###",")##",")((",")()","))#","))(",")))"]
      ]
  , testGroup "LL(1), not SLL(k)"
      [ testFirst 3 llsll "A" ["","a"]
      , testFollow 3 llsll 'A' ["ab#","b##"]
      ]
  , testGroup "empty"
      [ testFirst 3 emptyL "A" []
      , testFollow 3 emptyL 'A' ["###"]
      ]
  , testGroup "Left recursion"
      [ testFirst 3 leftrec "A" ["c","cab"]
      , testFollow 3 leftrec 'A' ["a##","aba"]
      ]
  ] where
      testFirst :: Int -> Grammar Char Char -> String -> [String] -> TestTree
      testFirst k gr seq exp =
        testCase ("First_" ++ show k ++ "('" ++ seq ++ "')") $
          first k gr (map (mkV gr) seq) @?= Set.fromList exp
      testFollow :: Int -> Grammar Char Char -> Char -> [String] -> TestTree
      testFollow k gr nt exp =
        testCase ("Follow_" ++ show k ++ "(" ++ show nt ++ ")") $
          follow k gr nt @?= Set.fromList (map (map mkWithEOF) exp)
      mkV gr v
        | elem v (terminals gr)    = T v
        | elem v (nonterminals gr) = NT v
        | otherwise                = error "not part of vocabulary"
      mkWithEOF '#' = EOF
      mkWithEOF c   = NoEOF c