{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NoMonomorphismRestriction #-} -- | Test suite for ACE. module Main where import ACE.Combinators import ACE.Parsers import ACE.Pretty import ACE.Tokenizer (tokenize) import ACE.Types.Syntax import ACE.Types.Tokens import Data.Text.Lazy.Builder (fromText) import Control.Applicative import Control.Monad hiding (ap) import Control.Monad.Identity hiding (ap) import Data.Bifunctor import Data.Text (Text) import Test.HUnit import Test.Hspec import Text.Parsec (Stream,ParsecT,runP,try,Parsec,ParseError) import Text.Parsec.Prim -- | Test suite entry point, returns exit failure if any test fails. main :: IO () main = hspec spec -- | Test suite. spec :: Spec spec = do describe "tokenizer" tokenizer describe "parser" parser describe "printer" printer -- | Tests for the tokenizer. tokenizer :: Spec tokenizer = do it "empty string" (tokenize "" == Right []) it "word" (tokenize "word" == Right [Word (1,0) "word"]) it "period" (tokenize "." == Right [Period (1,0)]) it "comma" (tokenize "," == Right [Comma (1,0)]) it "number" (tokenize "55" == Right [Number (1,0) 55]) it "question mark" (tokenize "?" == Right [QuestionMark (1,0)]) it "quotation" (tokenize "\"foo\"" == Right [QuotedString (1,0) "foo"]) it "empty-quotation" (isLeft (tokenize "\"\"")) it "words" (tokenize "foo bar" == Right [Word (1,0) "foo",Word (1,4) "bar"]) it "genitive '" (tokenize "foo'" == Right [Word (1,0) "foo",Genitive (1,3) False]) it "genitive 's" (tokenize "foo's" == Right [Word (1,0) "foo",Genitive (1,3) True]) it "newline" (tokenize "foo\nbar" == Right [Word (1,0) "foo",Word (2,0) "bar"]) -- | Parser tests. parser :: Spec parser = do simple adjective ap' copulae complVs genitiveNP possessives specifiers verbs adverbs verbModifiers nouns relatives noun sentences sentences = do it "existentialTopic" (parsed existentialTopic "there is a " == Right (ExistentialTopic (ExistentialGlobalQuantor Is) (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)))) it "sentence" (parsed sentence "a " == Right (Sentence (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)) (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) []))))) it "sentence" (parsed sentence "a that " == Right (Sentence (NPCoordUnmarked (UnmarkedNPCoord (NP (SpecifyDeterminer A) (N' Nothing (N "") Nothing Nothing (Just (RelativeClauseCoord (RelativeClauseThat (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) [])))) Nothing)))) Nothing)) (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) []))))) it "conditionalSentence" (parsed conditionalSentence "if a then some " == Right (ConditionalSentence (SentenceCoord (SentenceCoord_1 (SentenceCoord_2 (SentenceCoord_3 (TopicalizedSentenceComposite (CompositeSentence (Sentence (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)) (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) [])))))) Nothing) Nothing) Nothing) Nothing) (SentenceCoord (SentenceCoord_1 (SentenceCoord_2 (SentenceCoord_3 (TopicalizedSentenceComposite (CompositeSentence (Sentence (NPCoordUnmarked (UnmarkedNPCoord (NP (SpecifyDeterminer Some) (N' Nothing (N "") Nothing Nothing Nothing)) Nothing)) (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) [])))))) Nothing) Nothing) Nothing) Nothing))) it "universalTopic" (parsed universalTopic "for all " == Right (UniversalTopic ForAll (N' Nothing (N "") Nothing Nothing Nothing))) it "negatedSentence" (parsed negatedSentence "it is not the case that a " == Right (NegatedSentence (SentenceCoord (SentenceCoord_1 (SentenceCoord_2 (SentenceCoord_3 (TopicalizedSentenceComposite (CompositeSentence (Sentence (NPCoordUnmarked (UnmarkedNPCoord (NP (SpecifyDeterminer A) (N' Nothing (N "") Nothing Nothing Nothing)) Nothing)) (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) [])))))) Nothing) Nothing) Nothing) Nothing))) it "specification" (parsed specification "it is not the case that a ." == Right (Specification (SentenceCoord (SentenceCoord_1 (SentenceCoord_2 (SentenceCoord_3 (TopicalizedSentenceComposite (CompositeSentenceNeg (NegatedSentence (SentenceCoord (SentenceCoord_1 (SentenceCoord_2 (SentenceCoord_3 (TopicalizedSentenceComposite (CompositeSentence (Sentence (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)) (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) [])))))) Nothing) Nothing) Nothing) Nothing)))) Nothing) Nothing) Nothing) Nothing) Nothing)) noun = do it "pp" (parsed pp " a " == Right (PP (Preposition "") (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)))) it "n'" (parsed (n' False) "" == Right (N' Nothing (N "") Nothing Nothing Nothing) ) it "n'" (parsed (n' False) " " == Right (N' (Just (AdjectiveCoord (IntransitiveAdjective "") Nothing)) (N "") Nothing Nothing Nothing)) it "n'" (parsed (n' False) " " == Right (N' (Just (AdjectiveCoord (IntransitiveAdjective "") Nothing)) (N "") (Just (ApposCoord (AppositionVar (Variable "")) Nothing)) Nothing Nothing)) it "n'" (parsed (n' False) " of a a " == Right (N' (Just (AdjectiveCoord (IntransitiveAdjective "") Nothing)) (N "") (Just (ApposCoord (AppositionVar (Variable "")) Nothing)) (Just (NPCoordUnmarked (UnmarkedNPCoord (NP (SpecifyDeterminer A) (N' Nothing (N "") Nothing Nothing (Just (RelativeClauseCoord (RelativeClauseNP (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)) (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) [])))) Nothing)))) Nothing))) Nothing)) relatives = do it "relativeClauseCoord" (parsed relativeClauseCoord "that and a " == Right (RelativeClauseCoord (RelativeClauseThat (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) [])))) (Just (And ,RelativeClauseCoord (RelativeClauseNP (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)) (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) [])))) Nothing)))) it "relativeClause" (parsed relativeClause "that " == Right (RelativeClauseThat (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) []))))) it "relativeClause" (parsed relativeClause "a " == Right (RelativeClauseNP (NPCoordUnmarked (UnmarkedNPCoord (NP (SpecifyDeterminer A) (N' Nothing (N "") Nothing Nothing Nothing)) Nothing)) (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) []))))) it "relativeClause" (parsed relativeClause "that a " == Right (RelativeClauseThatNPVP (NPCoordUnmarked (UnmarkedNPCoord (NP (SpecifyDeterminer A) (N' Nothing (N "") Nothing Nothing Nothing)) Nothing)) (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) []))))) it "relativeClause" (parsed relativeClause "a a " == Right (RelativeClauseNPVP (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)) (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)) (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) []))))) it "relativeClause" (parsed relativeClause " a a " == Right (RelativeClausePP (PP (Preposition "") (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing))) (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)) (VPCoordVP (VP (V' Nothing (ComplVIV (IntransitiveV "")) []))))) nouns = do it "genitiveN'" (parsed genitiveN' " " == Right (GenitiveN' Nothing (N "") (Just (ApposCoord (AppositionVar (Variable "")) Nothing)))) it "genitiveN'" (parsed genitiveN' " and " == Right (GenitiveN' (Just (AdjectiveCoord (IntransitiveAdjective "") (Just (AdjectiveCoord (IntransitiveAdjective "") Nothing)))) (N "") (Just (ApposCoord (AppositionVar (Variable "")) Nothing)))) it "npCoord" (parsed npCoord "each of some " == Right (NPCoordDistributed EachOf (UnmarkedNPCoord (NP (SpecifyDeterminer Some) (N' Nothing (N "") Nothing Nothing Nothing)) Nothing))) it "npCoord" (parsed npCoord "some " == Right (NPCoordUnmarked (UnmarkedNPCoord (NP (SpecifyDeterminer Some) (N' Nothing (N "") Nothing Nothing Nothing)) Nothing))) verbModifiers = do it "vModifier" (parsed vModifier " and " == Right (VModifierVC (AdverbCoord (Adverb "") (Just (AdverbCoord (Adverb "") Nothing))))) it "vModifier" (parsed vModifier " a " == Right (VModifierPP (PP (Preposition "") (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing))))) it "vModifier" (parsed vModifier " and " == Right (VModifierAVPP (AdverbialPP (Preposition "") (AdverbCoord (Adverb "") (Just (AdverbCoord (Adverb "") Nothing)))))) adverbs = do it "adverbialPP" (parsed adverbialPP " and " == Right (AdverbialPP (Preposition "") (AdverbCoord (Adverb "") (Just (AdverbCoord (Adverb "") Nothing))))) verbs = do -- An intransitive verb is OK: walks it "v'" (parsed v' "" == Right (V' Nothing (ComplVIV (IntransitiveV "")) [])) -- A transitive verb must take a preposition and a noun phrase. it "v'" (parsed v' " a " == Right (V' Nothing (ComplVTV (TransitiveV "") (ComplPP (PP (Preposition "") (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing))))) [])) -- A phrasal transitive verb with adverbs on both sides, e.g. -- quickly walks up to a chair hastily it "v'" (parsed v' " a " == Right (V' (Just (AdverbCoord (Adverb "") Nothing)) (ComplVPV (PhrasalTransitiveV "") (PhrasalParticle "") (ComplPP (PP (Preposition "") (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing))))) [VModifierVC (AdverbCoord (Adverb "") Nothing)])) it "vp" (parsed vp "" == Right (VP (V' Nothing (ComplVIV (IntransitiveV "")) []))) it "vp" (parsed vp "is not " == Right (VPNeg Is (V' Nothing (ComplVIV (IntransitiveV "")) []))) it "vpCoord" (parsed vpCoord " and is not " == Right (VPCoord' (VP (V' Nothing (ComplVIV (IntransitiveV "")) [])) And (VPCoordVP (VPNeg Is (V' Nothing (ComplVIV (IntransitiveV "")) []))))) specifiers = do it "specifier" (parsed specifier "'s" == Right (SpecifyPossessive (PossessiveNPCoordGen (GenitiveNPCoordName (ProperName "") (GenitiveTailSaxonTail (SaxonGenitiveTail ApostropheS Nothing)))))) it "specifier" (parsed specifier "1" == Right (SpecifyNumberP (NumberP Nothing 1))) it "specifier" (parsed specifier "a" == Right (SpecifyDeterminer A)) it "genitiveSpecifier" (parsed genitiveSpecifier "1" == Right (GenitiveSpecifierN 1)) it "genitiveSpecifier" (parsed genitiveSpecifier "a" == Right (GenitiveSpecifierD A)) it "genitiveSpecifier" (parsed genitiveSpecifier "some" == Right (GenitiveSpecifierD Some)) it "genitiveSpecifier" (parsed genitiveSpecifier "his" == Right (GenitiveSpecifierPPC (PossessivePronounCoord His Nothing))) possessives = do it "possessivePronounCoord" (parsed possessivePronounCoord "his and her" == Right (PossessivePronounCoord His (Just (PossessivePronounCoord Her Nothing)))) it "possessivePronounCoord" (parsed possessivePronounCoord "its" == Right (PossessivePronounCoord Its Nothing)) it "possessiveNPCoord" (parsed possessiveNPCoord "his and her" == Right (PossessiveNPCoordPronoun (PossessivePronounCoord His (Just (PossessivePronounCoord Her Nothing))))) it "possessiveNPCoord" (parsed possessiveNPCoord "a 's" == Right (PossessiveNPCoordGen (GenitiveNPCoord (GenitiveSpecifierD A) (GenitiveN' Nothing (N "") Nothing) (GenitiveTailSaxonTail (SaxonGenitiveTail ApostropheS Nothing))))) genitiveNP = do it "genitiveNPCoord" (parsed genitiveNPCoord "'s" == Right (GenitiveNPCoordName (ProperName "") (GenitiveTailSaxonTail (SaxonGenitiveTail ApostropheS Nothing)))) it "genitiveNPCoord" (parsed genitiveNPCoord "some 's" == Right (GenitiveNPCoord (GenitiveSpecifierD Some) (GenitiveN' Nothing (N "") Nothing) (GenitiveTailSaxonTail (SaxonGenitiveTail ApostropheS Nothing)))) it "genitiveNPCoord" (parsed genitiveNPCoord "some and a 's" == Right (GenitiveNPCoord (GenitiveSpecifierD Some) (GenitiveN' Nothing (N "") Nothing) (GenitiveTailCoordtail (GenitiveCoordTail (GenitiveNPCoord (GenitiveSpecifierD A) (GenitiveN' Nothing (N "") Nothing) (GenitiveTailSaxonTail (SaxonGenitiveTail ApostropheS Nothing))))))) adjective = do it "adjectiveCoord" (parsed adjectiveCoord "" == Right (AdjectiveCoord intransAdj Nothing)) it "adjectiveCoord" (parsed adjectiveCoord " and " == Right (AdjectiveCoord intransAdj (Just (AdjectiveCoord intransAdj Nothing)))) it "adverbCoord" (parsed adverbCoord " and " == Right (AdverbCoord adverb' (Just (AdverbCoord adverb' Nothing)))) ap' = do it "ap" (parsed ap "" == Right (APIntrans intransAdj)) it "ap" (parsed ap " a " == Right (APTrans (TransitiveAdjective "") (PP (Preposition "") (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing))))) it "apGrad" (parsed apGrad " than a " == Right (APgradAPThan (APIntrans intransAdj) (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)))) it "apCoord" (parsed apCoord " than a and than a " == Right (APCoordAnd (APgradAPThan (APIntrans intransAdj) (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing))) (APCoord (APgradAPThan (APIntrans intransAdj) (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)))))) copulae = do it "copulaCompl" (parsed copulaCompl " a " == Right (CopulaComplPP (PP (Preposition "") (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing))))) it "copulaCompl" (parsed copulaCompl "a and a " == Right (CopulaComplNPC (NPCoordUnmarked (UnmarkedNPCoord anoun (Just (UnmarkedNPCoord anoun Nothing)))))) it "copulaCompl" (parsed copulaCompl " than a and a " == Right (CopulaComplAPC (APCoord (APgradAPThan (APIntrans intransAdj) (NPCoordUnmarked (UnmarkedNPCoord anoun (Just (UnmarkedNPCoord anoun Nothing)))))))) simple = do it "universalGlobalQuantor" (parsed universalGlobalQuantor "for every" == Right ForEvery) it "possessivePronoun" (parsed possessivePronoun "his" == Right His) it "generalizedQuantor" (parsed generalizedQuantor "not more than" == Right NotMoreThan) it "distributiveMarker" (parsed distributiveMarker "each of" == Right EachOf) it "distributiveGlobalQuantor" (parsed distributiveGlobalQuantor "for each of" == Right ForEachOf) it "existentialGlobalQuestionQuantor" (parsed existentialGlobalQuestionQuantor "is there" == Right (ExistentialGlobalQuestionQuantor Is)) it "existentialGlobalQuantor" (parsed existentialGlobalQuantor "there is" == Right (ExistentialGlobalQuantor Is)) it "numberP" (parsed numberP "not more than 5" == Right (NumberP (Just NotMoreThan) 5)) it "numberP" (parsed numberP "5" == Right (NumberP Nothing 5)) it "determiner" (parsed determiner "the" == Right The) it "determiner" (parsed determiner "not every" == Right NotEvery) complVs = do it "complVPI" (parsed complV " " == Right (ComplVPI (PhrasalIntransitiveV "") (PhrasalParticle ""))) it "complVIV" (parsed complV "" == Right (ComplVIV (IntransitiveV ""))) it "complVTV" (parsed complV " a " == Right (ComplVTV (TransitiveV "") (ComplPP (PP (Preposition "") (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)))))) it "complVPV" (parsed complV " a " == Right (ComplVPV (PhrasalTransitiveV "") (PhrasalParticle "") (ComplNP (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing))))) it "complVDisV" (parsed complV " a a " == Right (ComplVDisV (DistransitiveV "") (ComplNP (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing))) (ComplPP (PP (Preposition "") (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing)))))) it "complVPDV" (parsed complV " a a " == Right (ComplVPDV (PhrasalDistransitiveV "") (ComplNP (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing))) (PhrasalParticle "") (ComplNP (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing))))) it "complCopula" (parsed complV "is a " == Right (ComplVCopula Is (CopulaComplNPC (NPCoordUnmarked (UnmarkedNPCoord anoun Nothing))))) intransAdj = IntransitiveAdjective "" adverb' = Adverb "" anoun = (NP (SpecifyDeterminer A) (N' Nothing (N "") Nothing Nothing Nothing)) printer = do isomorphic "existentialTopic" existentialTopic "there is a " isomorphic "sentence" sentence "a " isomorphic "sentence" sentence "a that " isomorphic "conditionalSentence" conditionalSentence "if a then some " isomorphic "universalTopic" universalTopic "for all " isomorphic "negatedSentence" negatedSentence "it is not the case that a " isomorphic "specification" specification "it is not the case that a ." isomorphic "pp" pp " a " isomorphic "(n' False)" (n' False) "" isomorphic "(n' False)" (n' False) " " isomorphic "(n' False)" (n' False) " " isomorphic "(n' False)" (n' False) " of a a " isomorphic "relativeClauseCoord" relativeClauseCoord "that and a " isomorphic "relativeClause" relativeClause "that " isomorphic "relativeClause" relativeClause "a " isomorphic "relativeClause" relativeClause "that a " isomorphic "relativeClause" relativeClause "a a " isomorphic "relativeClause" relativeClause " a a " isomorphic "genitiveN'" genitiveN' " " isomorphic "genitiveN'" genitiveN' " and " isomorphic "npCoord" npCoord "each of some " isomorphic "npCoord" npCoord "some " isomorphic "vModifier" vModifier " and " isomorphic "vModifier" vModifier " a " isomorphic "vModifier" vModifier " and " isomorphic "adverbialPP" adverbialPP " and " isomorphic "v'" v' "" isomorphic "v'" v' " a " isomorphic "v'" v' " a " isomorphic "vp" vp "" isomorphic "vp" vp "is not " isomorphic "vpCoord" vpCoord " and is not " isomorphic "specifier" specifier "'s" isomorphic "specifier" specifier "1" isomorphic "specifier" specifier "a" isomorphic "genitiveSpecifier" genitiveSpecifier "1" isomorphic "genitiveSpecifier" genitiveSpecifier "a" isomorphic "genitiveSpecifier" genitiveSpecifier "some" isomorphic "genitiveSpecifier" genitiveSpecifier "his" isomorphic "possessivePronounCoord" possessivePronounCoord "his and her" isomorphic "possessivePronounCoord" possessivePronounCoord "its" isomorphic "possessiveNPCoord" possessiveNPCoord "his and her" isomorphic "possessiveNPCoord" possessiveNPCoord "a 's" isomorphic "genitiveNPCoord" genitiveNPCoord "'s" isomorphic "genitiveNPCoord" genitiveNPCoord "some 's" isomorphic "genitiveNPCoord" genitiveNPCoord "some and a 's" isomorphic "adjectiveCoord" adjectiveCoord "" isomorphic "adjectiveCoord" adjectiveCoord " and " isomorphic "adverbCoord" adverbCoord " and " isomorphic "ap" ap "" isomorphic "ap" ap " a " isomorphic "apGrad" apGrad " than a " isomorphic "apCoord" apCoord " than a and than a " isomorphic "copulaCompl" copulaCompl " a " isomorphic "copulaCompl" copulaCompl "a and a " isomorphic "copulaCompl" copulaCompl " than a and a " isomorphic "universalGlobalQuantor" universalGlobalQuantor "for every" isomorphic "possessivePronoun" possessivePronoun "his" isomorphic "generalizedQuantor" generalizedQuantor "not more than" isomorphic "distributiveMarker" distributiveMarker "each of" isomorphic "distributiveGlobalQuantor" distributiveGlobalQuantor "for each of" isomorphic "existentialGlobalQuestionQuantor" existentialGlobalQuestionQuantor "is there" isomorphic "existentialGlobalQuantor" existentialGlobalQuantor "there is" isomorphic "numberP" numberP "not more than 5" isomorphic "numberP" numberP "5" isomorphic "determiner" determiner "the" isomorphic "determiner" determiner "not every" isomorphic "complV" complV " " isomorphic "complV" complV "" isomorphic "complV" complV " a " isomorphic "complV" complV " a " isomorphic "complV" complV " a a " isomorphic "complV" complV " a a " isomorphic "complV" complV "is a " where isomorphic name parser text = it name (printed parser text == Right (fromText text)) -- | Is that left? isLeft :: Either a b -> Bool isLeft = either (const True) (const False) -- | Get the parsed result after tokenizing. parsed :: Parsec [Token] (ACEParser [Token] Identity) c -> Text -> Either String c parsed p = tokenize >=> bimap show id . runP (p <* eof) defaultACEParser "" printed p = fmap pretty . parsed p -- | Test a parser. testp :: Show a => Parsec [Token] (ACEParser [Token] Identity) a -> Text -> IO () testp p i = case parsed p i of Left e -> putStrLn e Right p -> print p