packages feed

egison-pattern-src-0.2.0.0: test/Language/Egison/Parser/PatternSpec.hs

module Language.Egison.Parser.PatternSpec
  ( test_atom_patterns
  , test_primitive_pattern_operators
  , test_user_defined_pattern_operators
  , test_user_defined_comments
  , test_non_greedy
  )
where

import           TestImport

import           Test.Tasty
import           Test.Tasty.HUnit


assertParseExpr :: String -> Expr Name Name ValueExpr -> Assertion
assertParseExpr content expected = case parse testParseMode content of
  Left  err -> fail $ show err
  Right got -> assertEqual ("while parsing \"" ++ content ++ "\"") expected got

assertParseExprNonGreedy
  :: String -> Expr Name Name ValueExpr -> String -> Assertion
assertParseExprNonGreedy content expectedExpr expectedRest =
  case parseNonGreedy testParseMode content of
    Left  err         -> fail $ show err
    Right (got, rest) -> do
      assertEqual ("while parsing \"" ++ content ++ "\"") expectedExpr got
      assertEqual ("while taking the parsed rest of \"" ++ content ++ "\"")
                  expectedRest
                  rest

test_atom_patterns :: [TestTree]
test_atom_patterns =
  [ testCase "wildcard pattern" $ assertParseExpr "_" Wildcard
  , testCase "variable pattern" $ assertParseExpr "$x" (Variable $ Name "x")
  , testCase "value pattern" $ assertParseExpr "#10" (Value $ ValueExprInt 10)
  , testCase "value pattern between parentheses"
    $ assertParseExpr "#(-10)" (Value . ValueExprInt $ -10)
  , testCase "predicate pattern"
    $ assertParseExpr "?10" (Predicate $ ValueExprInt 10)
  , testCase "constructor pattern" $ assertParseExpr
    "ctor _ _ _"
    (Pattern (Name "ctor") [Wildcard, Wildcard, Wildcard])
  , testCase "constructor pattern between parentheses" $ assertParseExpr
    "(ctor _ _ _)"
    (Pattern (Name "ctor") [Wildcard, Wildcard, Wildcard])
  , testCase "constructor pattern that the name is between parentheses"
    $ assertParseExpr "(++) _ _" (Pattern (Name "++") [Wildcard, Wildcard])
  , testCase
      "constructor pattern that the name and pattern itself is between parentheses"
    $ assertParseExpr "((++) _ _)" (Pattern (Name "++") [Wildcard, Wildcard])
  , testCase "constructor pattern without arguments"
    $ assertParseExpr "nil" (Pattern (Name "nil") [])
  , testCase "constructor pattern between parentheses"
    $ assertParseExpr "((c _))" (Pattern (Name "c") [Wildcard])
  , testCase "wildcard pattern between parentheses"
    $ assertParseExpr "((_))" Wildcard
  , testCase "constructor pattern without arguments between parentheses"
    $ assertParseExpr "((c))" (Pattern (Name "c") [])
  , testCase "nested constructor pattern" $ assertParseExpr
    "ctorA (ctorB _) (ctorC _ (ctorD _)) _ ctorE"
    (Pattern
      (Name "ctorA")
      [ Pattern (Name "ctorB") [Wildcard]
      , Pattern (Name "ctorC") [Wildcard, Pattern (Name "ctorD") [Wildcard]]
      , Wildcard
      , Pattern (Name "ctorE") []
      ]
    )
  , testCase "collection pattern"
    $ assertParseExpr "[_, _, _]" (Collection [Wildcard, Wildcard, Wildcard])
  , testCase "nested collection pattern" $ assertParseExpr
    "[_, [_, _], _]"
    (Collection [Wildcard, Collection [Wildcard, Wildcard], Wildcard])
  , testCase "nil collection pattern" $ assertParseExpr "[]" (Collection [])
  , testCase "tuple pattern"
    $ assertParseExpr "(_, _, _)" (Tuple [Wildcard, Wildcard, Wildcard])
  , testCase "tuple pattern between parentheses"
    $ assertParseExpr "((_, _, _))" (Tuple [Wildcard, Wildcard, Wildcard])
  , testCase "nested tuple pattern" $ assertParseExpr
    "(_, (_, _), _)"
    (Tuple [Wildcard, Tuple [Wildcard, Wildcard], Wildcard])
  , testCase "nil tuple pattern" $ assertParseExpr "()" (Tuple [])
  , testCase "not pattern" $ assertParseExpr "!_" (Not Wildcard)
  , testCase "not pattern in constructor arguments" $ assertParseExpr
    "ctor !_ !_"
    (Pattern (Name "ctor") [Not Wildcard, Not Wildcard])
  , testCase "not pattern on constructor pattern" $ assertParseExpr
    "!ctor _ _"
    (Not (Pattern (Name "ctor") [Wildcard, Wildcard]))
  , testCase "nested not patterns" $ assertParseExpr "!!_" (Not (Not Wildcard))
  ]

test_primitive_pattern_operators :: [TestTree]
test_primitive_pattern_operators =
  [ testCase "and pattern" $ assertParseExpr "_ & _" (And Wildcard Wildcard)
  , testCase "or pattern" $ assertParseExpr "_ | _" (Or Wildcard Wildcard)
  -- associativity
  , testCase "nested and pattern"
    $ assertParseExpr "_ & _ & _" (And Wildcard (And Wildcard Wildcard))
  , testCase "nested or pattern"
    $ assertParseExpr "_ | _ | _" (Or Wildcard (Or Wildcard Wildcard))
  -- precedence
  , testCase "nested and, or pattern" $ assertParseExpr
    "_ & _ | _ & _"
    (Or (And Wildcard Wildcard) (And Wildcard Wildcard))
  , testCase "nested not, or pattern"
    $ assertParseExpr "! _ | _" (Or (Not Wildcard) Wildcard)
  , testCase "nested not, and pattern"
    $ assertParseExpr "! _ & _" (And (Not Wildcard) Wildcard)
  , testCase "constructor pattern in infix operands" $ assertParseExpr
    "_ & ctor _ _ | ctor _ _"
    (Or (And Wildcard (Pattern (Name "ctor") [Wildcard, Wildcard]))
        (Pattern (Name "ctor") [Wildcard, Wildcard])
    )
  ]

test_user_defined_pattern_operators :: [TestTree]
test_user_defined_pattern_operators =
  [ testCase "cons pattern"
    $ assertParseExpr "_ : _" (Infix (Name ":") Wildcard Wildcard)
  , testCase "join pattern"
    $ assertParseExpr "_ ++ _" (Infix (Name "++") Wildcard Wildcard)
  -- associativity
  , testCase "nested cons pattern" $ assertParseExpr
    "_ : _ : _"
    (Infix (Name ":") Wildcard (Infix (Name ":") Wildcard Wildcard))
  , testCase "nested join pattern" $ assertParseExpr
    "_ ++ _ ++ _"
    (Infix (Name "++") Wildcard (Infix (Name "++") Wildcard Wildcard))
  , testCase "nested join, cons pattern" $ assertParseExpr
    "_ ++ _ : _"
    (Infix (Name "++") Wildcard (Infix (Name ":") Wildcard Wildcard))
  , testCase "nested cons, join pattern" $ assertParseExpr
    "_ : _ ++ _"
    (Infix (Name ":") Wildcard (Infix (Name "++") Wildcard Wildcard))
  -- and more
  , testCase "precedence" $ assertParseExpr
    "_ : _ <| _"
    (Infix (Name "<|") (Infix (Name ":") Wildcard Wildcard) Wildcard)
  , testCase "associativity" $ assertParseExpr
    "_ |> _ |> _"
    (Infix (Name "|>") (Infix (Name "|>") Wildcard Wildcard) Wildcard)
  ]

test_user_defined_comments :: [TestTree]
test_user_defined_comments =
  [ testCase "ignore a block comment"
    $ assertParseExpr "_ {- comment -} & _" (And Wildcard Wildcard)
  , testCase "ignore block comments" $ assertParseExpr
    "_ {- comment1 -}{- comment2 -} & (_ &{- comment3 -}_)"
    (And Wildcard (And Wildcard Wildcard))
  , testCase "ignore a block comment at beginning of line"
    $ assertParseExpr "{- comment -}_" Wildcard
  , testCase "ignore a line comment"
    $ assertParseExpr "_-- comment -- yeah" Wildcard
  , testCase "ignore a line comment at beginning of line"
    $ assertParseExpr "-- comment -- yeah \n_-- comment" Wildcard
  ]

test_non_greedy :: [TestTree]
test_non_greedy =
  [ testCase "preserve the rest of input stream" $ assertParseExprNonGreedy
      "$x : _ -> x"
      (Infix (Name ":") (Variable (Name "x")) Wildcard)
      "-> x"
  ]