module Language.Drasil.NaturalLanguage.English.NounPhrase (
  -- * Types
  NounPhrase(..), NP,
  -- * Phrase Accessors
  atStartNP, atStartNP', titleizeNP, titleizeNP',
  -- * Constructors
  -- ** Common Noun Constructors
  cn, cn', cn'', cn''', cnICES, cnIES, cnIP, cnIS, cnIrr, cnUM,
  -- ** Proper Noun Constructors
  pn, pn', pn'', pn''', pnIrr,
  -- ** Noun Phrase Constructors
  nounPhrase, nounPhrase', nounPhrase'', nounPhraseSP, nounPhraseSent,
  -- * Combinators
  compoundPhrase,
  compoundPhrase', compoundPhrase'', compoundPhrase''', compoundPhraseP1,
  surroundNPStruct,
  -- * Re-exported Types
  CapitalizationRuleG(..), CapitalizationRule, PluralRule(..), NPStruct,
  -- * Re-exported Smart Constructors
  npS, npP, (.-.), (.+.)
  ) where

import Data.Char (isLatin1, isLetter, toLower, toUpper)

import Language.Drasil.NaturalLanguage.English.NounPhrase.Core -- uses whole module

--Linguistically, nounphrase might not be the best name (yet!), but once
-- it is fleshed out and/or we do more with it, it will likely be a good fit

class NounPhrase n where
  -- | Retrieves singular form of term. Ex. "the quick brown fox".
  phraseNP :: n -> NPStruct
  -- | Retrieves plural form of term. Ex. "the quick brown foxes".
  pluralNP :: n -> PluralForm
    --Could replace plural string with a function.
  -- | Retrieves the singular form and applies a captalization
  -- rule (usually capitalizes the first word) to produce a 'NPStruct.
  -- Ex. "The quick brown fox".
  sentenceCase :: n -> (NP -> NPStruct) -> Capitalization
    --Should this be replaced with a data type instead?
    --Data types should use functions to determine capitalization based
    -- on rules.
  -- | Retrieves the singular form and applies a captalization
  -- rule (usually capitalizes all words) to produce a 'NPStruct.
  -- Ex. "The Quick Brown Fox".
  titleCase :: n -> (NP -> NPStruct) -> Capitalization

-- | Type synonym for 'NPStruct.
type Capitalization = NPStruct
-- | Type synonym for 'String'.
type PluralString   = String

-- | Defines NP as a NounPhrase.
-- Default capitalization rules for proper and common nouns
-- are 'CapFirst' for sentence case and 'CapWords' for title case.
-- Also accepts a 'Phrase' where the capitalization case may be specified.
instance NounPhrase NP where
  phraseNP :: NP -> PluralForm
phraseNP (ProperNoun String
n PluralRule
_)           = String -> PluralForm
forall a. String -> NPStructG a
SC String
n
  phraseNP (CommonNoun String
n PluralRule
_ CapitalizationRuleG Symbol
_)         = String -> PluralForm
forall a. String -> NPStructG a
SC String
n
  phraseNP (Phrase PluralForm
n PluralForm
_ CapitalizationRuleG Symbol
_ CapitalizationRuleG Symbol
_)           = PluralForm
n
  pluralNP :: NP -> PluralForm
pluralNP n :: NP
n@(ProperNoun String
_ PluralRule
p)         = PluralForm -> PluralRule -> PluralForm
sPlur (NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP NP
n) PluralRule
p
  pluralNP n :: NP
n@(CommonNoun String
_ PluralRule
p CapitalizationRuleG Symbol
_)       = PluralForm -> PluralRule -> PluralForm
sPlur (NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP NP
n) PluralRule
p
  pluralNP (Phrase PluralForm
_ PluralForm
p CapitalizationRuleG Symbol
_ CapitalizationRuleG Symbol
_)           = PluralForm
p
  sentenceCase :: NP -> (NP -> PluralForm) -> PluralForm
sentenceCase   (ProperNoun String
n PluralRule
_)   NP -> PluralForm
_ = String -> PluralForm
forall a. String -> NPStructG a
SC String
n
  sentenceCase n :: NP
n@(CommonNoun String
_ PluralRule
_ CapitalizationRuleG Symbol
r) NP -> PluralForm
f = PluralForm -> CapitalizationRuleG Symbol -> PluralForm
cap (NP -> PluralForm
f NP
n) CapitalizationRuleG Symbol
r
  sentenceCase n :: NP
n@(Phrase PluralForm
_ PluralForm
_ CapitalizationRuleG Symbol
r CapitalizationRuleG Symbol
_)   NP -> PluralForm
f = PluralForm -> CapitalizationRuleG Symbol -> PluralForm
cap (NP -> PluralForm
f NP
n) CapitalizationRuleG Symbol
r
  titleCase :: NP -> (NP -> PluralForm) -> PluralForm
titleCase n :: NP
n@ProperNoun {}         NP -> PluralForm
_ = NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP NP
n
  titleCase n :: NP
n@CommonNoun {}         NP -> PluralForm
f = PluralForm -> CapitalizationRuleG Symbol -> PluralForm
cap (NP -> PluralForm
f NP
n) CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapWords
  titleCase n :: NP
n@(Phrase PluralForm
_ PluralForm
_ CapitalizationRuleG Symbol
_ CapitalizationRuleG Symbol
r)      NP -> PluralForm
f = PluralForm -> CapitalizationRuleG Symbol -> PluralForm
cap (NP -> PluralForm
f NP
n) CapitalizationRuleG Symbol
r

-- ===Constructors=== --
-- | Constructs a Proper Noun, it is always capitalized as written.
pn, pn', pn'', pn''' :: String -> NP
-- | Self plural.
pn :: String -> NP
pn    String
n = String -> PluralRule -> NP
forall a. String -> PluralRule -> NPG a
ProperNoun String
n PluralRule
SelfPlur
-- | Plural form simply adds "s" (ex. Henderson -> Hendersons).
pn' :: String -> NP
pn'   String
n = String -> PluralRule -> NP
forall a. String -> PluralRule -> NPG a
ProperNoun String
n PluralRule
AddS
-- | Plural form adds "e".
pn'' :: String -> NP
pn''  String
n = String -> PluralRule -> NP
forall a. String -> PluralRule -> NPG a
ProperNoun String
n PluralRule
AddE
-- | Plural form adds "es" (ex. Bush -> Bushes).
pn''' :: String -> NP
pn''' String
n = String -> PluralRule -> NP
forall a. String -> PluralRule -> NPG a
ProperNoun String
n PluralRule
AddES

-- | Constructs a 'ProperNoun' with a custom plural rule (using 'IrregPlur' from 'PluralRule').
-- First argument is the String representing the noun, second is the rule.
pnIrr :: String -> PluralRule -> NP
pnIrr :: String -> PluralRule -> NP
pnIrr = String -> PluralRule -> NP
forall a. String -> PluralRule -> NPG a
ProperNoun

-- | Constructs a common noun which capitalizes the first letter of the first word
-- at the beginning of a sentence.
cn, cn', cn'', cn''' :: String -> NP
-- | Self plural.
cn :: String -> NP
cn    String
n = String -> PluralRule -> CapitalizationRuleG Symbol -> NP
forall a. String -> PluralRule -> CapitalizationRuleG a -> NPG a
CommonNoun String
n PluralRule
SelfPlur CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst
-- | Plural form simply adds "s" (ex. dog -> dogs).
cn' :: String -> NP
cn'   String
n = String -> PluralRule -> CapitalizationRuleG Symbol -> NP
forall a. String -> PluralRule -> CapitalizationRuleG a -> NPG a
CommonNoun String
n PluralRule
AddS CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst
-- | Plural form adds "e" (ex. formula -> formulae).
cn'' :: String -> NP
cn''  String
n = String -> PluralRule -> CapitalizationRuleG Symbol -> NP
forall a. String -> PluralRule -> CapitalizationRuleG a -> NPG a
CommonNoun String
n PluralRule
AddE CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst
-- | Plural form adds "es" (ex. bush -> bushes).
cn''' :: String -> NP
cn''' String
n = String -> PluralRule -> CapitalizationRuleG Symbol -> NP
forall a. String -> PluralRule -> CapitalizationRuleG a -> NPG a
CommonNoun String
n PluralRule
AddES CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst

-- | Constructs a common noun that pluralizes by dropping the last letter and adding an "ies"
-- ending (ex. body -> bodies).
cnIES :: String -> NP
cnIES :: String -> NP
cnIES String
n = String -> PluralRule -> CapitalizationRuleG Symbol -> NP
forall a. String -> PluralRule -> CapitalizationRuleG a -> NPG a
CommonNoun String
n ((String -> String) -> PluralRule
IrregPlur (\String
x -> String -> String
forall a. HasCallStack => [a] -> [a]
init String
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"ies")) CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst

--FIXME: Shouldn't this just be drop one and add "ces"?
-- | Construct a common noun that pluralizes by dropping the last two letters and adding an
-- "ices" ending (ex. matrix -> matrices).
cnICES :: String -> NP
cnICES :: String -> NP
cnICES String
n = String -> PluralRule -> CapitalizationRuleG Symbol -> NP
forall a. String -> PluralRule -> CapitalizationRuleG a -> NPG a
CommonNoun String
n ((String -> String) -> PluralRule
IrregPlur (\String
x -> String -> String
forall a. HasCallStack => [a] -> [a]
init (String -> String
forall a. HasCallStack => [a] -> [a]
init String
x) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"ices")) CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst

-- | Constructs a common noun that pluralizes by dropping the last two letters and adding
-- "es" (ex. analysis -> analyses).
cnIS :: String -> NP
cnIS :: String -> NP
cnIS String
n = String -> PluralRule -> CapitalizationRuleG Symbol -> NP
forall a. String -> PluralRule -> CapitalizationRuleG a -> NPG a
CommonNoun String
n ((String -> String) -> PluralRule
IrregPlur (\String
x -> String -> String
forall a. HasCallStack => [a] -> [a]
init (String -> String
forall a. HasCallStack => [a] -> [a]
init String
x) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"es")) CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst

-- | Constructs a common noun that pluralizes by dropping the last two letters and adding "a"
-- (ex. datum -> data).
cnUM :: String -> NP
cnUM :: String -> NP
cnUM String
n = String -> PluralRule -> CapitalizationRuleG Symbol -> NP
forall a. String -> PluralRule -> CapitalizationRuleG a -> NPG a
CommonNoun String
n ((String -> String) -> PluralRule
IrregPlur (\String
x -> String -> String
forall a. HasCallStack => [a] -> [a]
init (String -> String
forall a. HasCallStack => [a] -> [a]
init String
x) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"a")) CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst

-- | Constructs a common noun that allows you to specify the pluralization rule
-- (as in 'pnIrr').
cnIP :: String -> PluralRule -> NP
cnIP :: String -> PluralRule -> NP
cnIP String
n PluralRule
p = String -> PluralRule -> CapitalizationRuleG Symbol -> NP
forall a. String -> PluralRule -> CapitalizationRuleG a -> NPG a
CommonNoun String
n PluralRule
p CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst

-- | Common noun that allows you to specify both the pluralization rule and the
-- capitalization rule for sentence case (if the noun is used at the beginning
-- of a sentence).
cnIrr :: String -> PluralRule -> CapitalizationRule -> NP
cnIrr :: String -> PluralRule -> CapitalizationRuleG Symbol -> NP
cnIrr = String -> PluralRule -> CapitalizationRuleG Symbol -> NP
forall a. String -> PluralRule -> CapitalizationRuleG a -> NPG a
CommonNoun

-- | Creates a 'NP' with a given singular and plural form (as 'String's) that capitalizes the first
-- letter of the first word for sentence case.
nounPhrase :: String -> PluralString -> NP
nounPhrase :: String -> String -> NP
nounPhrase String
s String
p = PluralForm
-> PluralForm
-> CapitalizationRuleG Symbol
-> CapitalizationRuleG Symbol
-> NP
forall a.
NPStructG a
-> NPStructG a
-> CapitalizationRuleG a
-> CapitalizationRuleG a
-> NPG a
Phrase (String -> PluralForm
forall a. String -> NPStructG a
SC String
s) (String -> PluralForm
forall a. String -> NPStructG a
SC String
p) CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapWords

-- | Similar to 'nounPhrase', but takes a specified capitalization rule for the sentence case.
nounPhrase' :: String -> PluralString -> CapitalizationRule -> NP
nounPhrase' :: String -> String -> CapitalizationRuleG Symbol -> NP
nounPhrase' String
s String
p CapitalizationRuleG Symbol
c = PluralForm
-> PluralForm
-> CapitalizationRuleG Symbol
-> CapitalizationRuleG Symbol
-> NP
forall a.
NPStructG a
-> NPStructG a
-> CapitalizationRuleG a
-> CapitalizationRuleG a
-> NPG a
Phrase (String -> PluralForm
forall a. String -> NPStructG a
SC String
s) (String -> PluralForm
forall a. String -> NPStructG a
SC String
p) CapitalizationRuleG Symbol
c CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapWords

-- | Custom noun phrase constructor that takes a singular form ('NPStruct), plural form ('NPStruct),
-- sentence case capitalization rule, and title case capitalization rule.
nounPhrase'' :: NPStruct -> PluralForm -> CapitalizationRule -> CapitalizationRule -> NP
nounPhrase'' :: PluralForm
-> PluralForm
-> CapitalizationRuleG Symbol
-> CapitalizationRuleG Symbol
-> NP
nounPhrase'' = PluralForm
-> PluralForm
-> CapitalizationRuleG Symbol
-> CapitalizationRuleG Symbol
-> NP
forall a.
NPStructG a
-> NPStructG a
-> CapitalizationRuleG a
-> CapitalizationRuleG a
-> NPG a
Phrase

-- | For things that should not be pluralized (or are self-plural). Works like 'nounPhrase', but with
-- only the first argument.
nounPhraseSP :: String -> NP
nounPhraseSP :: String -> NP
nounPhraseSP String
s = PluralForm
-> PluralForm
-> CapitalizationRuleG Symbol
-> CapitalizationRuleG Symbol
-> NP
forall a.
NPStructG a
-> NPStructG a
-> CapitalizationRuleG a
-> CapitalizationRuleG a
-> NPG a
Phrase (String -> PluralForm
forall a. String -> NPStructG a
SC String
s) (String -> PluralForm
forall a. String -> NPStructG a
SC String
s) CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapWords

-- | Similar to nounPhrase, except it only accepts one 'NPStruct.
-- Plural case is just 'AddS'.
nounPhraseSent :: NPStruct -> NP
nounPhraseSent :: PluralForm -> NP
nounPhraseSent PluralForm
s = PluralForm
-> PluralForm
-> CapitalizationRuleG Symbol
-> CapitalizationRuleG Symbol
-> NP
forall a.
NPStructG a
-> NPStructG a
-> CapitalizationRuleG a
-> CapitalizationRuleG a
-> NPG a
Phrase PluralForm
s (PluralForm -> PluralRule -> PluralForm
sPlur PluralForm
s PluralRule
AddS) CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapWords

-- | Combine two noun phrases. The singular form becomes 'phrase' from t1 followed
-- by 'phrase' of t2. The plural becomes 'phrase' of t1 followed by 'plural' of t2.
-- Uses standard 'CapFirst' sentence case and 'CapWords' title case.
-- For example: @compoundPhrase system constraint@ will have singular form
-- "system constraint" and plural "system constraints".
compoundPhrase :: (NounPhrase a, NounPhrase b) => a -> b -> NP
compoundPhrase :: forall a b. (NounPhrase a, NounPhrase b) => a -> b -> NP
compoundPhrase a
t1 b
t2 = PluralForm
-> PluralForm
-> CapitalizationRuleG Symbol
-> CapitalizationRuleG Symbol
-> NP
forall a.
NPStructG a
-> NPStructG a
-> CapitalizationRuleG a
-> CapitalizationRuleG a
-> NPG a
Phrase
  (a -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP a
t1 PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: b -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP b
t2) (a -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP a
t1 PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: b -> PluralForm
forall n. NounPhrase n => n -> PluralForm
pluralNP b
t2) CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapWords

-- | Similar to 'compoundPhrase', but the sentence case is the same
-- as the title case ('CapWords').
compoundPhrase' :: NP -> NP -> NP
compoundPhrase' :: NP -> NP -> NP
compoundPhrase' NP
t1 NP
t2 = PluralForm
-> PluralForm
-> CapitalizationRuleG Symbol
-> CapitalizationRuleG Symbol
-> NP
forall a.
NPStructG a
-> NPStructG a
-> CapitalizationRuleG a
-> CapitalizationRuleG a
-> NPG a
Phrase
  (NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP NP
t1 PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP NP
t2) (NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP NP
t1 PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
pluralNP NP
t2) CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapWords CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapWords

-- | Similar to 'compoundPhrase'', but accepts two functions that will be used to
-- construct the plural form. For example,
-- @compoundPhrase'' plural phrase system constraint@ would have the plural
-- form "systems constraint".
compoundPhrase'' :: (NP -> NPStruct) -> (NP -> NPStruct) -> NP -> NP -> NP
compoundPhrase'' :: (NP -> PluralForm) -> (NP -> PluralForm) -> NP -> NP -> NP
compoundPhrase'' NP -> PluralForm
f1 NP -> PluralForm
f2 NP
t1 NP
t2 = PluralForm
-> PluralForm
-> CapitalizationRuleG Symbol
-> CapitalizationRuleG Symbol
-> NP
forall a.
NPStructG a
-> NPStructG a
-> CapitalizationRuleG a
-> CapitalizationRuleG a
-> NPG a
Phrase
  (NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP NP
t1 PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP NP
t2) (NP -> PluralForm
f1 NP
t1 PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: NP -> PluralForm
f2 NP
t2) CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapWords CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapWords

--More primes might not be wanted but fixes two issues
-- pluralization problem with software requirements specification (Documentation.hs)
-- SWHS program not being about to use a compound to create the IdeaDict
-- | Similar to 'compoundPhrase', but used when you need a special function applied
-- to the first term of both singular and pluralcases (eg. short or plural).
compoundPhrase''' :: (NP -> NPStruct) -> NP -> NP -> NP
compoundPhrase''' :: (NP -> PluralForm) -> NP -> NP -> NP
compoundPhrase''' NP -> PluralForm
f1 NP
t1 NP
t2 = PluralForm
-> PluralForm
-> CapitalizationRuleG Symbol
-> CapitalizationRuleG Symbol
-> NP
forall a.
NPStructG a
-> NPStructG a
-> CapitalizationRuleG a
-> CapitalizationRuleG a
-> NPG a
Phrase
  (NP -> PluralForm
f1 NP
t1 PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP NP
t2) (NP -> PluralForm
f1 NP
t1 PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
pluralNP NP
t2) CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapWords

--For Data.Drasil.Documentation
-- | Similar to 'compoundPhrase', but pluralizes the first 'NP' for both singular and plural cases.
compoundPhraseP1 :: NP -> NP -> NP
compoundPhraseP1 :: NP -> NP -> NP
compoundPhraseP1 = (NP -> PluralForm) -> NP -> NP -> NP
compoundPhrase''' NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
pluralNP

-- === Helpers ===
-- | Helper function for getting the sentence case of a noun phrase.
atStartNP, atStartNP' :: NounPhrase n => n -> Capitalization
-- | Singular sentence case.
atStartNP :: forall n. NounPhrase n => n -> PluralForm
atStartNP  n
n = n -> (NP -> PluralForm) -> PluralForm
forall n. NounPhrase n => n -> (NP -> PluralForm) -> PluralForm
sentenceCase n
n NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP
-- | Plural sentence case.
atStartNP' :: forall n. NounPhrase n => n -> PluralForm
atStartNP' n
n = n -> (NP -> PluralForm) -> PluralForm
forall n. NounPhrase n => n -> (NP -> PluralForm) -> PluralForm
sentenceCase n
n NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
pluralNP

-- | Helper function for getting the title case of a noun phrase.
titleizeNP, titleizeNP' :: NounPhrase n => n -> Capitalization
-- | Singular title case.
titleizeNP :: forall n. NounPhrase n => n -> PluralForm
titleizeNP  n
n = n -> (NP -> PluralForm) -> PluralForm
forall n. NounPhrase n => n -> (NP -> PluralForm) -> PluralForm
titleCase n
n NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
phraseNP
-- | Plural title case.
titleizeNP' :: forall n. NounPhrase n => n -> PluralForm
titleizeNP' n
n = n -> (NP -> PluralForm) -> PluralForm
forall n. NounPhrase n => n -> (NP -> PluralForm) -> PluralForm
titleCase n
n NP -> PluralForm
forall n. NounPhrase n => n -> PluralForm
pluralNP

-- DO NOT EXPORT --
-- | Pluralization helper function.
sPlur :: NPStruct -> PluralRule -> NPStruct
sPlur :: PluralForm -> PluralRule -> PluralForm
sPlur (SC String
s) PluralRule
AddS = String -> PluralForm
forall a. String -> NPStructG a
SC (String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"s")
sPlur (SC String
s) PluralRule
AddE = String -> PluralForm
forall a. String -> NPStructG a
SC (String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"e")
sPlur s :: PluralForm
s@(SC String
_) PluralRule
AddES = PluralForm -> PluralRule -> PluralForm
sPlur (PluralForm -> PluralRule -> PluralForm
sPlur PluralForm
s PluralRule
AddE) PluralRule
AddS
sPlur s :: PluralForm
s@(SC String
_) PluralRule
SelfPlur = PluralForm
s
sPlur (SC String
sts) (IrregPlur String -> String
f) = String -> PluralForm
forall a. String -> NPStructG a
SC (String -> PluralForm) -> String -> PluralForm
forall a b. (a -> b) -> a -> b
$ String -> String
f String
sts --Custom pluralization
sPlur (PluralForm
a :+!: PluralForm
b) PluralRule
pt = PluralForm
a PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: PluralForm -> PluralRule -> PluralForm
sPlur PluralForm
b PluralRule
pt
sPlur (PluralForm
a :-!: PluralForm
b) PluralRule
pt = PluralForm
a PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:-!: PluralForm -> PluralRule -> PluralForm
sPlur PluralForm
b PluralRule
pt
sPlur PluralForm
a PluralRule
_ = String -> PluralForm
forall a. String -> NPStructG a
SC String
"MISSING PLURAL FOR:" PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: PluralForm
a

-- | Capitalization helper function given a noun phrase.
cap :: NPStruct -> CapitalizationRule -> NPStruct
cap :: PluralForm -> CapitalizationRuleG Symbol -> PluralForm
cap PluralForm
_ (Replace PluralForm
s) = PluralForm
s
cap PluralForm
s CapitalizationRuleG Symbol
CapNothing = PluralForm
s
cap (SC [])     CapitalizationRuleG Symbol
CapFirst = String -> PluralForm
forall a. String -> NPStructG a
SC [] -- ignore this
cap (SC (Char
s:String
ss)) CapitalizationRuleG Symbol
CapFirst = String -> PluralForm
forall a. String -> NPStructG a
SC (Char -> Char
toUpper Char
s Char -> String -> String
forall a. a -> [a] -> [a]
: String
ss)
cap (SC String
s)      CapitalizationRuleG Symbol
CapWords = String -> (String -> String) -> (String -> String) -> PluralForm
capString String
s String -> String
capFirstWord String -> String
capWords
cap (PC Symbol
symb :+!: PluralForm
x) CapitalizationRuleG Symbol
CapFirst = Symbol -> PluralForm
forall a. a -> NPStructG a
PC Symbol
symb PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: PluralForm
x -- TODO: See why the Table of Symbols uses the CapWords case instead of CapFirst for items of the form:
cap (PC Symbol
symb :+!: PluralForm
x) CapitalizationRuleG Symbol
CapWords = Symbol -> PluralForm
forall a. a -> NPStructG a
PC Symbol
symb PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: PluralForm
x -- "x-component". Instead, it displays as "x-Component". Using a temp fix for now by ignoring everything after a P symbol.
cap (PluralForm
s1 :+!: PluralForm
s2) CapitalizationRuleG Symbol
CapWords = PluralForm -> CapitalizationRuleG Symbol -> PluralForm
cap PluralForm
s1 CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapWords PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: PluralForm -> PluralForm
capTail PluralForm
s2
cap (PluralForm
s1 :+!: PluralForm
s2) CapitalizationRuleG Symbol
CapFirst = PluralForm -> CapitalizationRuleG Symbol -> PluralForm
cap PluralForm
s1 CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: PluralForm
s2
cap (PC Symbol
symb :-!: PluralForm
x) CapitalizationRuleG Symbol
CapFirst = Symbol -> PluralForm
forall a. a -> NPStructG a
PC Symbol
symb PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:-!: PluralForm
x -- TODO: See why the Table of Symbols uses the CapWords case instead of CapFirst for items of the form:
cap (PC Symbol
symb :-!: PluralForm
x) CapitalizationRuleG Symbol
CapWords = Symbol -> PluralForm
forall a. a -> NPStructG a
PC Symbol
symb PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:-!: PluralForm
x -- "x-component". Instead, it displays as "x-Component". Using a temp fix for now by ignoring everything after a P symbol.
cap (PluralForm
s1 :-!: PluralForm
s2) CapitalizationRuleG Symbol
CapWords = PluralForm -> CapitalizationRuleG Symbol -> PluralForm
cap PluralForm
s1 CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapWords PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:-!: PluralForm -> PluralForm
capTail PluralForm
s2
cap (PluralForm
s1 :-!: PluralForm
s2) CapitalizationRuleG Symbol
CapFirst = PluralForm -> CapitalizationRuleG Symbol -> PluralForm
cap PluralForm
s1 CapitalizationRuleG Symbol
forall a. CapitalizationRuleG a
CapFirst PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:-!: PluralForm
s2
cap (PC Symbol
p) CapitalizationRuleG Symbol
_ = Symbol -> PluralForm
forall a. a -> NPStructG a
PC Symbol
p

-- | Helper for 'cap' and for capitalizing the end of a 'NPStruct (assumes 'CapWords').
capTail :: NPStruct -> NPStruct
capTail :: PluralForm -> PluralForm
capTail (SC String
s) = String -> (String -> String) -> (String -> String) -> PluralForm
capString String
s String -> String
capWords String -> String
capWords
capTail (PC Symbol
symb :+!: PluralForm
b) = Symbol -> PluralForm
forall a. a -> NPStructG a
PC Symbol
symb PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: PluralForm
b
capTail (PluralForm
a :+!: PluralForm
b) = PluralForm -> PluralForm
capTail PluralForm
a PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: PluralForm -> PluralForm
capTail PluralForm
b
capTail (PC Symbol
symb :-!: PluralForm
b) = Symbol -> PluralForm
forall a. a -> NPStructG a
PC Symbol
symb PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:-!: PluralForm
b
capTail (PluralForm
a :-!: PluralForm
b) = PluralForm -> PluralForm
capTail PluralForm
a PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:-!: PluralForm -> PluralForm
capTail PluralForm
b
capTail (PC Symbol
p) = Symbol -> PluralForm
forall a. a -> NPStructG a
PC Symbol
p

-- | Helper for capitalizing a string.
capString :: String -> (String -> String) -> (String -> String) -> NPStruct
capString :: String -> (String -> String) -> (String -> String) -> PluralForm
capString String
s String -> String
f String -> String
g = String -> PluralForm
forall a. String -> NPStructG a
SC (String -> PluralForm)
-> ([String] -> String) -> [String] -> PluralForm
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> String) -> String -> String
findHyph String -> String
g (String -> String) -> ([String] -> String) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unwords ([String] -> PluralForm) -> [String] -> PluralForm
forall a b. (a -> b) -> a -> b
$ [String] -> [String]
process (String -> [String]
words String
s)
  where
    process :: [String] -> [String]
process (String
x:[String]
xs) = String -> String
f String
x String -> [String] -> [String]
forall a. a -> [a] -> [a]
: (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map String -> String
g [String]
xs
    process []     = []

-- | Finds hyphens in a 'String' and applies capitalization to words after a hyphen.
findHyph :: (String -> String) -> String -> String
findHyph :: (String -> String) -> String -> String
findHyph String -> String
_ String
"" = String
""
findHyph String -> String
_ [Char
x] = [Char
x]
findHyph String -> String
f (Char
x:String
xs)
  | Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-'  = Char
'-' Char -> String -> String
forall a. a -> [a] -> [a]
: (String -> String) -> String -> String
findHyph String -> String
f (String -> String
f String
xs)
  | Bool
otherwise = Char
x Char -> String -> String
forall a. a -> [a] -> [a]
: (String -> String) -> String -> String
findHyph String -> String
f String
xs

-- | Capitalize first word of a 'String'. Does not ignore prepositions, articles, or conjunctions (intended for beginning of a phrase/sentence).
capFirstWord :: String -> String
capFirstWord :: String -> String
capFirstWord String
"" = String
""
capFirstWord w :: String
w@(Char
c:String
cs)
  | Bool -> Bool
not (Char -> Bool
isLetter Char
c) = String
w
  | Bool -> Bool
not (Char -> Bool
isLatin1 Char
c) = String
w
  | Bool
otherwise        = Char -> Char
toUpper Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String
cs

-- | Capitalize all words of a 'String' (unless they are prepositions, articles, or conjunctions).
capWords :: String -> String
capWords :: String -> String
capWords String
"" = String
""
capWords w :: String
w@(Char
c:String
cs)
  | Bool -> Bool
not (Char -> Bool
isLetter Char
c)   = String
w
  | Bool -> Bool
not (Char -> Bool
isLatin1 Char
c)   = String
w
  | String
w String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
doNotCaps = Char -> Char
toLower Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String
cs
  | Bool
otherwise          = Char -> Char
toUpper Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String
cs

-- | Words that should not be capitalized in a title (prepositions, articles, or conjunctions).
doNotCaps :: [String]
doNotCaps :: [String]
doNotCaps = [String
"a", String
"an", String
"the", String
"at", String
"by", String
"for", String
"in", String
"of",
  String
"on", String
"to", String
"up", String
"and", String
"as", String
"but", String
"or", String
"nor"] --Ref http://grammar.yourdictionary.com

surroundNPStruct :: String -> String -> NPStruct -> NPStruct
surroundNPStruct :: String -> String -> PluralForm -> PluralForm
surroundNPStruct String
l String
r (SC String
s)       = String -> PluralForm
forall a. String -> NPStructG a
SC (String -> PluralForm) -> String -> PluralForm
forall a b. (a -> b) -> a -> b
$ String
l String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
r
surroundNPStruct String
l String
r (PluralForm
s1 :+!: PluralForm
s2) = String -> String -> PluralForm -> PluralForm
surroundNPStruct String
l String
"" PluralForm
s1 PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:+!: String -> String -> PluralForm -> PluralForm
surroundNPStruct String
"" String
r PluralForm
s2
surroundNPStruct String
l String
r (PluralForm
s1 :-!: PluralForm
s2) = String -> String -> PluralForm -> PluralForm
surroundNPStruct String
l String
"" PluralForm
s1 PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:-!: String -> String -> PluralForm -> PluralForm
surroundNPStruct String
"" String
r PluralForm
s2
surroundNPStruct String
l String
r (PC Symbol
p)       = String -> PluralForm
forall a. String -> NPStructG a
SC String
l PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:-!: Symbol -> PluralForm
forall a. a -> NPStructG a
PC Symbol
p PluralForm -> PluralForm -> PluralForm
forall a. NPStructG a -> NPStructG a -> NPStructG a
:-!: String -> PluralForm
forall a. String -> NPStructG a
SC String
r