packages feed

gedcom 0.1.0.0 → 0.2.0.0

raw patch · 14 files changed

+1718/−1541 lines, 14 filesdep +hspecdep ~basedep ~megaparsecdep ~monad-loopsPVP ok

version bump matches the API change (PVP)

Dependencies added: hspec

Dependency ranges changed: base, megaparsec, monad-loops, time

API changes (from Hackage documentation)

- Data.Gedcom: AFN :: Text -> AFN
- Data.Gedcom: AKA :: NameType
- Data.Gedcom: Address :: Text -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> ContactDetails -> Address
- Data.Gedcom: Adopted :: Pedigree
- Data.Gedcom: Adoption :: (Maybe AdoptionDetail) -> IndividualEventType
- Data.Gedcom: AdoptionDetail :: (GDRef Family) -> (Maybe Parent) -> AdoptionDetail
- Data.Gedcom: Annuled :: FamilyEventType
- Data.Gedcom: Association :: GDRef Individual -> Text -> [SourceCitation] -> [GDRef Note] -> Association
- Data.Gedcom: Baptism :: IndividualEventType
- Data.Gedcom: BarMitzvah :: IndividualEventType
- Data.Gedcom: BasMitzvah :: IndividualEventType
- Data.Gedcom: Birth :: (Maybe (GDRef Family)) -> IndividualEventType
- Data.Gedcom: BirthName :: NameType
- Data.Gedcom: Blessing :: IndividualEventType
- Data.Gedcom: BothParents :: Parent
- Data.Gedcom: Burial :: IndividualEventType
- Data.Gedcom: ByBirth :: Pedigree
- Data.Gedcom: CallNumber :: Text -> (Maybe MultimediaType) -> CallNumber
- Data.Gedcom: Caste :: Text -> IndividualAttributeType
- Data.Gedcom: Census :: EventType
- Data.Gedcom: Challenged :: ChildLinkStatus
- Data.Gedcom: ChangeDate :: UTCTime -> (Maybe (GDRef Note)) -> ChangeDate
- Data.Gedcom: Charset :: Text -> (Maybe Text) -> Charset
- Data.Gedcom: ChildToFamilyLink :: GDRef Family -> Maybe Pedigree -> Maybe ChildLinkStatus -> [GDRef Note] -> ChildToFamilyLink
- Data.Gedcom: Christening :: (Maybe (GDRef Family)) -> IndividualEventType
- Data.Gedcom: ChristeningAdult :: IndividualEventType
- Data.Gedcom: Confidential :: RestrictionNotice
- Data.Gedcom: Confirmation :: IndividualEventType
- Data.Gedcom: ContactDetails :: [Text] -> [Text] -> [Text] -> [Text] -> ContactDetails
- Data.Gedcom: Corp :: Text -> Maybe Address -> Corp
- Data.Gedcom: Cremation :: IndividualEventType
- Data.Gedcom: Date :: Calendar -> (Maybe Word) -> (Maybe Word) -> Year -> Date
- Data.Gedcom: DateAbout :: Date -> DateApprox
- Data.Gedcom: DateAfter :: Date -> DateRange
- Data.Gedcom: DateApproxV :: DateApprox -> DateValue
- Data.Gedcom: DateBefore :: Date -> DateRange
- Data.Gedcom: DateBetween :: Date -> Date -> DateRange
- Data.Gedcom: DateCalculated :: Date -> DateApprox
- Data.Gedcom: DateEstimated :: Date -> DateApprox
- Data.Gedcom: DateFrom :: Date -> (Maybe Date) -> DatePeriod
- Data.Gedcom: DatePeriodV :: DatePeriod -> DateValue
- Data.Gedcom: DatePhrase :: (Maybe Date) -> Text -> DateValue
- Data.Gedcom: DateRangeV :: DateRange -> DateValue
- Data.Gedcom: DateTo :: Date -> DatePeriod
- Data.Gedcom: DateV :: Date -> DateValue
- Data.Gedcom: Death :: IndividualEventType
- Data.Gedcom: Disproved :: ChildLinkStatus
- Data.Gedcom: Divorce :: FamilyEventType
- Data.Gedcom: DivorceFiled :: FamilyEventType
- Data.Gedcom: Education :: Text -> IndividualAttributeType
- Data.Gedcom: Emigration :: IndividualEventType
- Data.Gedcom: Engagement :: FamilyEventType
- Data.Gedcom: EventDetail :: Maybe Text -> Maybe DateValue -> Maybe Place -> Maybe Address -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe RestrictionNotice -> [GDRef Note] -> [SourceCitation] -> [GDRef Multimedia] -> EventDetail
- Data.Gedcom: EventType :: Text -> EventType
- Data.Gedcom: Fact :: Text -> IndividualAttributeType
- Data.Gedcom: FamCensus :: FamilyEventType
- Data.Gedcom: Family :: Maybe RestrictionNotice -> [FamilyEvent] -> Maybe (GDRef Individual) -> Maybe (GDRef Individual) -> [GDRef Individual] -> Maybe Word -> [GDRef Submitter] -> [UserReference] -> Maybe RIN -> Maybe ChangeDate -> [GDRef Note] -> [SourceCitation] -> [GDRef Multimedia] -> Family
- Data.Gedcom: FamilyEvent :: FamilyEventType -> FamilyEventDetail -> FamilyEvent
- Data.Gedcom: FamilyEventDetail :: Maybe Word -> Maybe Word -> EventDetail -> FamilyEventDetail
- Data.Gedcom: FamilyEventType :: Text -> FamilyEventType
- Data.Gedcom: FamilyEventTypeV :: FamilyEventType -> EventType
- Data.Gedcom: Female :: Sex
- Data.Gedcom: FirstCommunion :: IndividualEventType
- Data.Gedcom: Foster :: Pedigree
- Data.Gedcom: French :: Calendar
- Data.Gedcom: Gedcom :: Header -> [GDRef Family] -> [GDRef Individual] -> [GDRef Multimedia] -> [GDRef Note] -> [GDRef Repository] -> [GDRef Source] -> [GDRef Submitter] -> Gedcom
- Data.Gedcom: GedcomFormat :: Text -> GedcomForm -> GedcomFormat
- Data.Gedcom: GedcomLineageLinked :: GedcomForm
- Data.Gedcom: GedcomUnsupported :: Text -> GedcomForm
- Data.Gedcom: Graduation :: IndividualEventType
- Data.Gedcom: Gregorian :: Calendar
- Data.Gedcom: Hangul :: PhoneticType
- Data.Gedcom: Header :: HeaderSource -> Maybe Text -> Maybe UTCTime -> GDRef Submitter -> Maybe (GDRef Submission) -> Maybe FilePath -> Maybe Text -> GedcomFormat -> Charset -> Maybe Language -> Maybe [Text] -> Maybe Text -> Header
- Data.Gedcom: HeaderSource :: Text -> Maybe Text -> Maybe Text -> Maybe Corp -> Maybe HeaderSourceData -> HeaderSource
- Data.Gedcom: HeaderSourceData :: Text -> Maybe UTCTime -> Maybe Text -> HeaderSourceData
- Data.Gedcom: Hebrew :: Calendar
- Data.Gedcom: Husband :: Parent
- Data.Gedcom: Immigrant :: NameType
- Data.Gedcom: Immigration :: IndividualEventType
- Data.Gedcom: Individual :: Maybe RestrictionNotice -> Maybe PersonalName -> Maybe Sex -> [IndividualEvent] -> [IndividualAttribute] -> [ChildToFamilyLink] -> [SpouseToFamilyLink] -> [GDRef Submitter] -> [Association] -> [GDRef Individual] -> [GDRef Submitter] -> [GDRef Submitter] -> Maybe RFN -> Maybe AFN -> [UserReference] -> Maybe RIN -> Maybe ChangeDate -> [GDRef Note] -> [SourceCitation] -> [GDRef Multimedia] -> Individual
- Data.Gedcom: IndividualAttribute :: IndividualAttributeType -> (IndividualEventDetail) -> IndividualAttribute
- Data.Gedcom: IndividualEvent :: IndividualEventType -> IndividualEventDetail -> IndividualEvent
- Data.Gedcom: IndividualEventDetail :: EventDetail -> Maybe Word -> IndividualEventDetail
- Data.Gedcom: IndividualEventType :: Text -> IndividualEventType
- Data.Gedcom: IndividualEventTypeV :: IndividualEventType -> EventType
- Data.Gedcom: IndvCensus :: IndividualEventType
- Data.Gedcom: Julian :: Calendar
- Data.Gedcom: Kana :: PhoneticType
- Data.Gedcom: Language :: Text -> Language
- Data.Gedcom: Latitude :: Double -> Latitude
- Data.Gedcom: Locked :: RestrictionNotice
- Data.Gedcom: Longitude :: Double -> Longitude
- Data.Gedcom: MF_BMP :: MultimediaFileFormat
- Data.Gedcom: MF_GIF :: MultimediaFileFormat
- Data.Gedcom: MF_JPG :: MultimediaFileFormat
- Data.Gedcom: MF_OLE :: MultimediaFileFormat
- Data.Gedcom: MF_OTHER :: Text -> MultimediaFileFormat
- Data.Gedcom: MF_PCX :: MultimediaFileFormat
- Data.Gedcom: MF_TIF :: MultimediaFileFormat
- Data.Gedcom: MF_WAV :: MultimediaFileFormat
- Data.Gedcom: MT_AUDIO :: MultimediaType
- Data.Gedcom: MT_BOOK :: MultimediaType
- Data.Gedcom: MT_CARD :: MultimediaType
- Data.Gedcom: MT_ELECTRONIC :: MultimediaType
- Data.Gedcom: MT_FICHE :: MultimediaType
- Data.Gedcom: MT_FILM :: MultimediaType
- Data.Gedcom: MT_MAGAZINE :: MultimediaType
- Data.Gedcom: MT_MANUSCRIPT :: MultimediaType
- Data.Gedcom: MT_MAP :: MultimediaType
- Data.Gedcom: MT_NEWSPAPER :: MultimediaType
- Data.Gedcom: MT_OTHER :: Text -> MultimediaType
- Data.Gedcom: MT_PHOTO :: MultimediaType
- Data.Gedcom: MT_TOMBSTONE :: MultimediaType
- Data.Gedcom: MT_VIDEO :: MultimediaType
- Data.Gedcom: Maiden :: NameType
- Data.Gedcom: Male :: Sex
- Data.Gedcom: MapCoord :: Longitude -> Latitude -> MapCoord
- Data.Gedcom: Marriage :: FamilyEventType
- Data.Gedcom: MarriageBann :: FamilyEventType
- Data.Gedcom: MarriageContract :: FamilyEventType
- Data.Gedcom: MarriageLicense :: FamilyEventType
- Data.Gedcom: MarriageSettlement :: FamilyEventType
- Data.Gedcom: Married :: NameType
- Data.Gedcom: Multimedia :: [MultimediaFile] -> Maybe Text -> [UserReference] -> Maybe RIN -> [GDRef Note] -> [SourceCitation] -> Maybe ChangeDate -> Multimedia
- Data.Gedcom: MultimediaFile :: Text -> MultimediaFormat -> Maybe Text -> MultimediaFile
- Data.Gedcom: MultimediaFormat :: MultimediaFileFormat -> (Maybe MultimediaType) -> MultimediaFormat
- Data.Gedcom: NChildren :: Word -> IndividualAttributeType
- Data.Gedcom: NMarriages :: Word -> IndividualAttributeType
- Data.Gedcom: Name :: Text -> (Maybe Text) -> Name
- Data.Gedcom: NameType :: Text -> NameType
- Data.Gedcom: NationalID :: Text -> IndividualAttributeType
- Data.Gedcom: NationalOrigin :: Text -> IndividualAttributeType
- Data.Gedcom: Naturalization :: IndividualEventType
- Data.Gedcom: Note :: Text -> [UserReference] -> Maybe RIN -> [SourceCitation] -> Maybe ChangeDate -> Note
- Data.Gedcom: Occupation :: Text -> IndividualAttributeType
- Data.Gedcom: Ordination :: IndividualEventType
- Data.Gedcom: PersonalName :: Name -> Maybe NameType -> PersonalNamePieces -> [PhoneticName] -> [RomanizedName] -> PersonalName
- Data.Gedcom: PersonalNamePieces :: [Text] -> [Text] -> [Text] -> [Text] -> [Text] -> [Text] -> [GDRef Note] -> [SourceCitation] -> PersonalNamePieces
- Data.Gedcom: PhoneticName :: Name -> PhoneticType -> PersonalNamePieces -> PhoneticName
- Data.Gedcom: PhoneticPlaceName :: PhoneticType -> [Text] -> PhoneticPlaceName
- Data.Gedcom: PhoneticType :: Text -> PhoneticType
- Data.Gedcom: PhysicalDescription :: Text -> IndividualAttributeType
- Data.Gedcom: Pinyin :: RomanType
- Data.Gedcom: Place :: [Text] -> Maybe [Text] -> Maybe PhoneticPlaceName -> Maybe RomanPlaceName -> Maybe MapCoord -> [GDRef Note] -> Place
- Data.Gedcom: Possessions :: Text -> IndividualAttributeType
- Data.Gedcom: Privacy :: RestrictionNotice
- Data.Gedcom: Probate :: IndividualEventType
- Data.Gedcom: Proven :: ChildLinkStatus
- Data.Gedcom: QualityAssessment :: Word -> QualityAssessment
- Data.Gedcom: RFN :: Text -> RFN
- Data.Gedcom: RIN :: Text -> RIN
- Data.Gedcom: Religion :: Text -> IndividualAttributeType
- Data.Gedcom: Repository :: Text -> Maybe Address -> [GDRef Note] -> [UserReference] -> Maybe RIN -> Maybe ChangeDate -> Repository
- Data.Gedcom: RepositoryCitation :: Maybe (GDRef Repository) -> [GDRef Note] -> Maybe CallNumber -> RepositoryCitation
- Data.Gedcom: Residence :: FamilyEventType
- Data.Gedcom: ResidesAt :: IndividualAttributeType
- Data.Gedcom: Retirement :: IndividualEventType
- Data.Gedcom: Romaji :: RomanType
- Data.Gedcom: RomanPlaceName :: RomanType -> [Text] -> RomanPlaceName
- Data.Gedcom: RomanType :: Text -> RomanType
- Data.Gedcom: RomanizedName :: Name -> RomanType -> PersonalNamePieces -> RomanizedName
- Data.Gedcom: Sealing :: Pedigree
- Data.Gedcom: SocialSecurity :: Text -> IndividualAttributeType
- Data.Gedcom: Source :: Maybe SourceData -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> [RepositoryCitation] -> [UserReference] -> Maybe RIN -> Maybe ChangeDate -> [GDRef Note] -> [GDRef Multimedia] -> Source
- Data.Gedcom: SourceCitation :: Either SourceDescription (GDRef Source) -> Maybe Text -> [GDRef Multimedia] -> [GDRef Note] -> Maybe QualityAssessment -> SourceCitation
- Data.Gedcom: SourceData :: [SourceRecordedEvent] -> Maybe Text -> [GDRef Note] -> SourceData
- Data.Gedcom: SourceDescription :: Text -> [Text] -> SourceDescription
- Data.Gedcom: SourceRecordedEvent :: [EventType] -> Maybe DatePeriod -> Maybe [Text] -> SourceRecordedEvent
- Data.Gedcom: SpouseToFamilyLink :: GDRef Family -> [GDRef Note] -> SpouseToFamilyLink
- Data.Gedcom: Submission :: Maybe (GDRef Submitter) -> Maybe Text -> Maybe Text -> Maybe Word -> Maybe Word -> Maybe Bool -> Maybe RIN -> [GDRef Note] -> Maybe ChangeDate -> Submission
- Data.Gedcom: Submitter :: Name -> Maybe Address -> Maybe (GDRef Multimedia) -> [Language] -> Maybe RFN -> Maybe RIN -> [GDRef Note] -> Maybe ChangeDate -> Submitter
- Data.Gedcom: Title :: Text -> IndividualAttributeType
- Data.Gedcom: Undetermined :: Sex
- Data.Gedcom: UserReference :: Text -> (Maybe Text) -> UserReference
- Data.Gedcom: WadeGiles :: RomanType
- Data.Gedcom: Wife :: Parent
- Data.Gedcom: Will :: IndividualEventType
- Data.Gedcom: Year :: Int -> Year
- Data.Gedcom: [addressCity] :: Address -> Maybe Text
- Data.Gedcom: [addressContact] :: Address -> ContactDetails
- Data.Gedcom: [addressCountry] :: Address -> Maybe Text
- Data.Gedcom: [addressEmail] :: ContactDetails -> [Text]
- Data.Gedcom: [addressFax] :: ContactDetails -> [Text]
- Data.Gedcom: [addressLines] :: Address -> Text
- Data.Gedcom: [addressPhone] :: ContactDetails -> [Text]
- Data.Gedcom: [addressPostcode] :: Address -> Maybe Text
- Data.Gedcom: [addressState] :: Address -> Maybe Text
- Data.Gedcom: [addressWWW] :: ContactDetails -> [Text]
- Data.Gedcom: [associationCitation] :: Association -> [SourceCitation]
- Data.Gedcom: [associationIndividual] :: Association -> GDRef Individual
- Data.Gedcom: [associationNote] :: Association -> [GDRef Note]
- Data.Gedcom: [associationRelation] :: Association -> Text
- Data.Gedcom: [childLinkFamily] :: ChildToFamilyLink -> GDRef Family
- Data.Gedcom: [childLinkNote] :: ChildToFamilyLink -> [GDRef Note]
- Data.Gedcom: [childLinkPedigree] :: ChildToFamilyLink -> Maybe Pedigree
- Data.Gedcom: [childLinkStatus] :: ChildToFamilyLink -> Maybe ChildLinkStatus
- Data.Gedcom: [citeMultimedia] :: SourceCitation -> [GDRef Multimedia]
- Data.Gedcom: [citeNote] :: SourceCitation -> [GDRef Note]
- Data.Gedcom: [citePage] :: SourceCitation -> Maybe Text
- Data.Gedcom: [citeQuality] :: SourceCitation -> Maybe QualityAssessment
- Data.Gedcom: [citeSource] :: SourceCitation -> Either SourceDescription (GDRef Source)
- Data.Gedcom: [corpAddress] :: Corp -> Maybe Address
- Data.Gedcom: [corpName] :: Corp -> Text
- Data.Gedcom: [eventDetailAddress] :: EventDetail -> Maybe Address
- Data.Gedcom: [eventDetailAgency] :: EventDetail -> Maybe Text
- Data.Gedcom: [eventDetailCause] :: EventDetail -> Maybe Text
- Data.Gedcom: [eventDetailDate] :: EventDetail -> Maybe DateValue
- Data.Gedcom: [eventDetailMultimedia] :: EventDetail -> [GDRef Multimedia]
- Data.Gedcom: [eventDetailNote] :: EventDetail -> [GDRef Note]
- Data.Gedcom: [eventDetailPlace] :: EventDetail -> Maybe Place
- Data.Gedcom: [eventDetailReligion] :: EventDetail -> Maybe Text
- Data.Gedcom: [eventDetailRestrictionNotice] :: EventDetail -> Maybe RestrictionNotice
- Data.Gedcom: [eventDetailSourceCitation] :: EventDetail -> [SourceCitation]
- Data.Gedcom: [eventDetailType] :: EventDetail -> Maybe Text
- Data.Gedcom: [familyChangeDate] :: Family -> Maybe ChangeDate
- Data.Gedcom: [familyChildren] :: Family -> [GDRef Individual]
- Data.Gedcom: [familyEventDetailAgeHusband] :: FamilyEventDetail -> Maybe Word
- Data.Gedcom: [familyEventDetailAgeWife] :: FamilyEventDetail -> Maybe Word
- Data.Gedcom: [familyEventDetailDetail] :: FamilyEventDetail -> EventDetail
- Data.Gedcom: [familyEventDetail] :: FamilyEvent -> FamilyEventDetail
- Data.Gedcom: [familyEventType] :: FamilyEvent -> FamilyEventType
- Data.Gedcom: [familyEvent] :: Family -> [FamilyEvent]
- Data.Gedcom: [familyHusband] :: Family -> Maybe (GDRef Individual)
- Data.Gedcom: [familyMultimedia] :: Family -> [GDRef Multimedia]
- Data.Gedcom: [familyNote] :: Family -> [GDRef Note]
- Data.Gedcom: [familyRIN] :: Family -> Maybe RIN
- Data.Gedcom: [familyRestrictionNotice] :: Family -> Maybe RestrictionNotice
- Data.Gedcom: [familySourceCitation] :: Family -> [SourceCitation]
- Data.Gedcom: [familySubitter] :: Family -> [GDRef Submitter]
- Data.Gedcom: [familyTotalChildren] :: Family -> Maybe Word
- Data.Gedcom: [familyUserReference] :: Family -> [UserReference]
- Data.Gedcom: [familyWife] :: Family -> Maybe (GDRef Individual)
- Data.Gedcom: [gedcomFamily] :: Gedcom -> [GDRef Family]
- Data.Gedcom: [gedcomForm] :: GedcomFormat -> GedcomForm
- Data.Gedcom: [gedcomHeader] :: Gedcom -> Header
- Data.Gedcom: [gedcomIndividual] :: Gedcom -> [GDRef Individual]
- Data.Gedcom: [gedcomMultimedia] :: Gedcom -> [GDRef Multimedia]
- Data.Gedcom: [gedcomNote] :: Gedcom -> [GDRef Note]
- Data.Gedcom: [gedcomRepository] :: Gedcom -> [GDRef Repository]
- Data.Gedcom: [gedcomSource] :: Gedcom -> [GDRef Source]
- Data.Gedcom: [gedcomSubmitter] :: Gedcom -> [GDRef Submitter]
- Data.Gedcom: [gedcomVersion] :: GedcomFormat -> Text
- Data.Gedcom: [headerCharset] :: Header -> Charset
- Data.Gedcom: [headerCopyright] :: Header -> Maybe Text
- Data.Gedcom: [headerDate] :: Header -> Maybe UTCTime
- Data.Gedcom: [headerDestination] :: Header -> Maybe Text
- Data.Gedcom: [headerFile] :: Header -> Maybe FilePath
- Data.Gedcom: [headerGedcomFormat] :: Header -> GedcomFormat
- Data.Gedcom: [headerLang] :: Header -> Maybe Language
- Data.Gedcom: [headerNote] :: Header -> Maybe Text
- Data.Gedcom: [headerPlaceForm] :: Header -> Maybe [Text]
- Data.Gedcom: [headerSourceCorp] :: HeaderSource -> Maybe Corp
- Data.Gedcom: [headerSourceDataCopyright] :: HeaderSourceData -> Maybe Text
- Data.Gedcom: [headerSourceDataDate] :: HeaderSourceData -> Maybe UTCTime
- Data.Gedcom: [headerSourceDataName] :: HeaderSourceData -> Text
- Data.Gedcom: [headerSourceData] :: HeaderSource -> Maybe HeaderSourceData
- Data.Gedcom: [headerSourceName] :: HeaderSource -> Maybe Text
- Data.Gedcom: [headerSourceSystemID] :: HeaderSource -> Text
- Data.Gedcom: [headerSourceVersion] :: HeaderSource -> Maybe Text
- Data.Gedcom: [headerSource] :: Header -> HeaderSource
- Data.Gedcom: [headerSubmission] :: Header -> Maybe (GDRef Submission)
- Data.Gedcom: [headerSubmitter] :: Header -> GDRef Submitter
- Data.Gedcom: [individualAFN] :: Individual -> Maybe AFN
- Data.Gedcom: [individualAlias] :: Individual -> [GDRef Individual]
- Data.Gedcom: [individualAncestorInterest] :: Individual -> [GDRef Submitter]
- Data.Gedcom: [individualAssociation] :: Individual -> [Association]
- Data.Gedcom: [individualAttribute] :: Individual -> [IndividualAttribute]
- Data.Gedcom: [individualChangeDate] :: Individual -> Maybe ChangeDate
- Data.Gedcom: [individualChildToFamilyLink] :: Individual -> [ChildToFamilyLink]
- Data.Gedcom: [individualDescendantInterest] :: Individual -> [GDRef Submitter]
- Data.Gedcom: [individualEventDetailAge] :: IndividualEventDetail -> Maybe Word
- Data.Gedcom: [individualEventDetailDetail] :: IndividualEventDetail -> EventDetail
- Data.Gedcom: [individualEventDetail] :: IndividualEvent -> IndividualEventDetail
- Data.Gedcom: [individualEventType] :: IndividualEvent -> IndividualEventType
- Data.Gedcom: [individualEvent] :: Individual -> [IndividualEvent]
- Data.Gedcom: [individualMultimedia] :: Individual -> [GDRef Multimedia]
- Data.Gedcom: [individualName] :: Individual -> Maybe PersonalName
- Data.Gedcom: [individualNote] :: Individual -> [GDRef Note]
- Data.Gedcom: [individualRFN] :: Individual -> Maybe RFN
- Data.Gedcom: [individualRIN] :: Individual -> Maybe RIN
- Data.Gedcom: [individualRestrictionNotice] :: Individual -> Maybe RestrictionNotice
- Data.Gedcom: [individualSex] :: Individual -> Maybe Sex
- Data.Gedcom: [individualSourceCitation] :: Individual -> [SourceCitation]
- Data.Gedcom: [individualSpouseToFamilyLink] :: Individual -> [SpouseToFamilyLink]
- Data.Gedcom: [individualSubmitter] :: Individual -> [GDRef Submitter]
- Data.Gedcom: [individualUserReference] :: Individual -> [UserReference]
- Data.Gedcom: [multimediaChangeDate] :: Multimedia -> Maybe ChangeDate
- Data.Gedcom: [multimediaFileFormat] :: MultimediaFile -> MultimediaFormat
- Data.Gedcom: [multimediaFileLink] :: MultimediaFile -> Text
- Data.Gedcom: [multimediaFile] :: Multimedia -> [MultimediaFile]
- Data.Gedcom: [multimediaNote] :: Multimedia -> [GDRef Note]
- Data.Gedcom: [multimediaRIN] :: Multimedia -> Maybe RIN
- Data.Gedcom: [multimediaSourceCitation] :: Multimedia -> [SourceCitation]
- Data.Gedcom: [multimediaTitl] :: Multimedia -> Maybe Text
- Data.Gedcom: [multimediaTitle] :: MultimediaFile -> Maybe Text
- Data.Gedcom: [multimediaUserReference] :: Multimedia -> [UserReference]
- Data.Gedcom: [namePieceGiven] :: PersonalNamePieces -> [Text]
- Data.Gedcom: [namePieceNameNote] :: PersonalNamePieces -> [GDRef Note]
- Data.Gedcom: [namePieceNickname] :: PersonalNamePieces -> [Text]
- Data.Gedcom: [namePiecePrefix] :: PersonalNamePieces -> [Text]
- Data.Gedcom: [namePieceSuffix] :: PersonalNamePieces -> [Text]
- Data.Gedcom: [namePieceSurnamePrefix] :: PersonalNamePieces -> [Text]
- Data.Gedcom: [namePieceSurname] :: PersonalNamePieces -> [Text]
- Data.Gedcom: [namePirceSourceCitation] :: PersonalNamePieces -> [SourceCitation]
- Data.Gedcom: [noteChangeDate] :: Note -> Maybe ChangeDate
- Data.Gedcom: [noteRIN] :: Note -> Maybe RIN
- Data.Gedcom: [noteSourceCitation] :: Note -> [SourceCitation]
- Data.Gedcom: [noteText] :: Note -> Text
- Data.Gedcom: [noteUserReference] :: Note -> [UserReference]
- Data.Gedcom: [personalNameName] :: PersonalName -> Name
- Data.Gedcom: [personalNamePhonetic] :: PersonalName -> [PhoneticName]
- Data.Gedcom: [personalNamePieces] :: PersonalName -> PersonalNamePieces
- Data.Gedcom: [personalNameRoman] :: PersonalName -> [RomanizedName]
- Data.Gedcom: [personalNameType] :: PersonalName -> Maybe NameType
- Data.Gedcom: [phoneticName] :: PhoneticName -> Name
- Data.Gedcom: [phoneticPieces] :: PhoneticName -> PersonalNamePieces
- Data.Gedcom: [phoneticType] :: PhoneticName -> PhoneticType
- Data.Gedcom: [placeForm] :: Place -> Maybe [Text]
- Data.Gedcom: [placeMap] :: Place -> Maybe MapCoord
- Data.Gedcom: [placeName] :: Place -> [Text]
- Data.Gedcom: [placeNote] :: Place -> [GDRef Note]
- Data.Gedcom: [placePhonetic] :: Place -> Maybe PhoneticPlaceName
- Data.Gedcom: [placeRoman] :: Place -> Maybe RomanPlaceName
- Data.Gedcom: [repoCiteCallNumber] :: RepositoryCitation -> Maybe CallNumber
- Data.Gedcom: [repoCiteNote] :: RepositoryCitation -> [GDRef Note]
- Data.Gedcom: [repoCiteRepository] :: RepositoryCitation -> Maybe (GDRef Repository)
- Data.Gedcom: [repositoryAddress] :: Repository -> Maybe Address
- Data.Gedcom: [repositoryChangeDate] :: Repository -> Maybe ChangeDate
- Data.Gedcom: [repositoryName] :: Repository -> Text
- Data.Gedcom: [repositoryNote] :: Repository -> [GDRef Note]
- Data.Gedcom: [repositoryRIN] :: Repository -> Maybe RIN
- Data.Gedcom: [repositoryUserReference] :: Repository -> [UserReference]
- Data.Gedcom: [romanziedName] :: RomanizedName -> Name
- Data.Gedcom: [romanziedPieces] :: RomanizedName -> PersonalNamePieces
- Data.Gedcom: [romanziedType] :: RomanizedName -> RomanType
- Data.Gedcom: [sourceAuthor] :: Source -> Maybe Text
- Data.Gedcom: [sourceChangeDate] :: Source -> Maybe ChangeDate
- Data.Gedcom: [sourceDataAgency] :: SourceData -> Maybe Text
- Data.Gedcom: [sourceDataEventsRecorded] :: SourceData -> [SourceRecordedEvent]
- Data.Gedcom: [sourceDataNote] :: SourceData -> [GDRef Note]
- Data.Gedcom: [sourceData] :: Source -> Maybe SourceData
- Data.Gedcom: [sourceMultimedia] :: Source -> [GDRef Multimedia]
- Data.Gedcom: [sourceNote] :: Source -> [GDRef Note]
- Data.Gedcom: [sourcePublicationFacts] :: Source -> Maybe Text
- Data.Gedcom: [sourceRIN] :: Source -> Maybe RIN
- Data.Gedcom: [sourceRecordedDate] :: SourceRecordedEvent -> Maybe DatePeriod
- Data.Gedcom: [sourceRecordedEventType] :: SourceRecordedEvent -> [EventType]
- Data.Gedcom: [sourceRecordedPlace] :: SourceRecordedEvent -> Maybe [Text]
- Data.Gedcom: [sourceRepositoryCitations] :: Source -> [RepositoryCitation]
- Data.Gedcom: [sourceShortTitle] :: Source -> Maybe Text
- Data.Gedcom: [sourceText] :: Source -> Maybe Text
- Data.Gedcom: [sourceTitle] :: Source -> Maybe Text
- Data.Gedcom: [sourceUserReference] :: Source -> [UserReference]
- Data.Gedcom: [spouseToFamilyLinkFamily] :: SpouseToFamilyLink -> GDRef Family
- Data.Gedcom: [spouseToFamilyLinkNote] :: SpouseToFamilyLink -> [GDRef Note]
- Data.Gedcom: [submissionAncestorGenerations] :: Submission -> Maybe Word
- Data.Gedcom: [submissionChangeDate] :: Submission -> Maybe ChangeDate
- Data.Gedcom: [submissionDescendentGenerations] :: Submission -> Maybe Word
- Data.Gedcom: [submissionFamilyFile] :: Submission -> Maybe Text
- Data.Gedcom: [submissionNote] :: Submission -> [GDRef Note]
- Data.Gedcom: [submissionOrdinanceProcessing] :: Submission -> Maybe Bool
- Data.Gedcom: [submissionRIN] :: Submission -> Maybe RIN
- Data.Gedcom: [submissionSubmitter] :: Submission -> Maybe (GDRef Submitter)
- Data.Gedcom: [submissionTempleCode] :: Submission -> Maybe Text
- Data.Gedcom: [submitterAddress] :: Submitter -> Maybe Address
- Data.Gedcom: [submitterChangeDate] :: Submitter -> Maybe ChangeDate
- Data.Gedcom: [submitterLang] :: Submitter -> [Language]
- Data.Gedcom: [submitterMedia] :: Submitter -> Maybe (GDRef Multimedia)
- Data.Gedcom: [submitterName] :: Submitter -> Name
- Data.Gedcom: [submitterNote] :: Submitter -> [GDRef Note]
- Data.Gedcom: [submitterRFN] :: Submitter -> Maybe RFN
- Data.Gedcom: [submitterRIN] :: Submitter -> Maybe RIN
- Data.Gedcom: data Address
- Data.Gedcom: data AdoptionDetail
- Data.Gedcom: data Association
- Data.Gedcom: data Calendar
- Data.Gedcom: data CallNumber
- Data.Gedcom: data ChangeDate
- Data.Gedcom: data Charset
- Data.Gedcom: data ChildLinkStatus
- Data.Gedcom: data ChildToFamilyLink
- Data.Gedcom: data ContactDetails
- Data.Gedcom: data Corp
- Data.Gedcom: data Date
- Data.Gedcom: data DateApprox
- Data.Gedcom: data DatePeriod
- Data.Gedcom: data DateRange
- Data.Gedcom: data DateValue
- Data.Gedcom: data EventDetail
- Data.Gedcom: data EventType
- Data.Gedcom: data Family
- Data.Gedcom: data FamilyEvent
- Data.Gedcom: data FamilyEventDetail
- Data.Gedcom: data FamilyEventType
- Data.Gedcom: data Gedcom
- Data.Gedcom: data GedcomForm
- Data.Gedcom: data GedcomFormat
- Data.Gedcom: data Header
- Data.Gedcom: data HeaderSource
- Data.Gedcom: data HeaderSourceData
- Data.Gedcom: data Individual
- Data.Gedcom: data IndividualAttribute
- Data.Gedcom: data IndividualAttributeType
- Data.Gedcom: data IndividualEvent
- Data.Gedcom: data IndividualEventDetail
- Data.Gedcom: data IndividualEventType
- Data.Gedcom: data MapCoord
- Data.Gedcom: data Multimedia
- Data.Gedcom: data MultimediaFile
- Data.Gedcom: data MultimediaFileFormat
- Data.Gedcom: data MultimediaFormat
- Data.Gedcom: data MultimediaType
- Data.Gedcom: data Name
- Data.Gedcom: data NameType
- Data.Gedcom: data Note
- Data.Gedcom: data Parent
- Data.Gedcom: data Pedigree
- Data.Gedcom: data PersonalName
- Data.Gedcom: data PersonalNamePieces
- Data.Gedcom: data PhoneticName
- Data.Gedcom: data PhoneticPlaceName
- Data.Gedcom: data PhoneticType
- Data.Gedcom: data Place
- Data.Gedcom: data Repository
- Data.Gedcom: data RepositoryCitation
- Data.Gedcom: data RestrictionNotice
- Data.Gedcom: data RomanPlaceName
- Data.Gedcom: data RomanType
- Data.Gedcom: data RomanizedName
- Data.Gedcom: data Sex
- Data.Gedcom: data Source
- Data.Gedcom: data SourceCitation
- Data.Gedcom: data SourceData
- Data.Gedcom: data SourceDescription
- Data.Gedcom: data SourceRecordedEvent
- Data.Gedcom: data SpouseToFamilyLink
- Data.Gedcom: data Submission
- Data.Gedcom: data Submitter
- Data.Gedcom: data UserReference
- Data.Gedcom: newtype AFN
- Data.Gedcom: newtype Language
- Data.Gedcom: newtype Latitude
- Data.Gedcom: newtype Longitude
- Data.Gedcom: newtype QualityAssessment
- Data.Gedcom: newtype RFN
- Data.Gedcom: newtype RIN
- Data.Gedcom: newtype Year
+ Data.Gedcom.Internal.Common: (<&>) :: Functor f => f a -> (a -> b) -> f b
+ Data.Gedcom.Internal.Common: dateExact :: Parser (Int, Word, Int)
+ Data.Gedcom.Internal.Common: infixl 1 <&>
+ Data.Gedcom.Internal.Common: month :: Parser Word
+ Data.Gedcom.Internal.Common: monthFr :: Parser Word
+ Data.Gedcom.Internal.Common: monthHeb :: Parser Word
+ Data.Gedcom.Internal.Common: timeToPicos :: (Int, Int, Int, Double) -> DiffTime
+ Data.Gedcom.Internal.Common: timeValue :: Parser (Maybe (Int, Int, Int, Double))
+ Data.Gedcom.Internal.Common: trim :: Text -> Text
+ Data.Gedcom.Internal.Common: type Parser = Parsec Void Text
+ Data.Gedcom.Internal.Common: withDefault :: Alternative f => a -> f a -> f a
+ Data.Gedcom.Internal.Common: yearGreg :: Parser Int
+ Data.Gedcom.Internal.CoreTypes: DuplicateRef :: Text -> GDError
+ Data.Gedcom.Internal.CoreTypes: FormatError :: Text -> GDError
+ Data.Gedcom.Internal.CoreTypes: GDEscape :: Text -> GDEscape
+ Data.Gedcom.Internal.CoreTypes: GDLevel :: Int -> GDLevel
+ Data.Gedcom.Internal.CoreTypes: GDLine :: GDLevel -> (Maybe GDXRefID) -> GDTag -> (Maybe GDLineValue) -> GDLine
+ Data.Gedcom.Internal.CoreTypes: GDLineItem :: [(Maybe GDEscape, Text)] -> GDLineItem
+ Data.Gedcom.Internal.CoreTypes: GDLineItemV :: GDLineItem -> GDLineValue
+ Data.Gedcom.Internal.CoreTypes: GDRoot :: [GDTree] -> GDRoot
+ Data.Gedcom.Internal.CoreTypes: GDStructure :: a -> GDRef a
+ Data.Gedcom.Internal.CoreTypes: GDTag :: Text -> GDTag
+ Data.Gedcom.Internal.CoreTypes: GDTree :: GDLine -> [GDTree] -> GDTree
+ Data.Gedcom.Internal.CoreTypes: GDXRef :: GDXRefID -> GDRef a
+ Data.Gedcom.Internal.CoreTypes: GDXRefID :: Text -> GDXRefID
+ Data.Gedcom.Internal.CoreTypes: GDXRefIDV :: GDXRefID -> GDLineValue
+ Data.Gedcom.Internal.CoreTypes: LineFormatError :: Text -> GDError
+ Data.Gedcom.Internal.CoreTypes: RefNotPresent :: GDXRefID -> GDRefError
+ Data.Gedcom.Internal.CoreTypes: RequiredRef :: Text -> GDError
+ Data.Gedcom.Internal.CoreTypes: TagError :: Text -> GDError
+ Data.Gedcom.Internal.CoreTypes: UnexpectedRef :: Text -> GDError
+ Data.Gedcom.Internal.CoreTypes: WrongRefType :: TypeRep -> TypeRep -> GDRefError
+ Data.Gedcom.Internal.CoreTypes: data GDError
+ Data.Gedcom.Internal.CoreTypes: data GDLine
+ Data.Gedcom.Internal.CoreTypes: data GDLineValue
+ Data.Gedcom.Internal.CoreTypes: data GDRef a
+ Data.Gedcom.Internal.CoreTypes: data GDRefError
+ Data.Gedcom.Internal.CoreTypes: data GDRoot
+ Data.Gedcom.Internal.CoreTypes: data GDTree
+ Data.Gedcom.Internal.CoreTypes: gdFilterEscapes :: [GDEscape] -> [(Maybe GDEscape, Text)] -> [(Maybe GDEscape, Text)]
+ Data.Gedcom.Internal.CoreTypes: gdIgnoreEscapes :: [(Maybe GDEscape, Text)] -> Text
+ Data.Gedcom.Internal.CoreTypes: gdLineData :: GDLineItem -> [(Maybe GDEscape, Text)]
+ Data.Gedcom.Internal.CoreTypes: gdTrimLineItem :: GDLineItem -> GDLineItem
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Base.Monoid Data.Gedcom.Internal.CoreTypes.GDLineItem
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Classes.Eq Data.Gedcom.Internal.CoreTypes.GDEscape
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Classes.Eq Data.Gedcom.Internal.CoreTypes.GDLevel
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Classes.Eq Data.Gedcom.Internal.CoreTypes.GDLine
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Classes.Eq Data.Gedcom.Internal.CoreTypes.GDLineItem
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Classes.Eq Data.Gedcom.Internal.CoreTypes.GDLineValue
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Classes.Eq Data.Gedcom.Internal.CoreTypes.GDRoot
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Classes.Eq Data.Gedcom.Internal.CoreTypes.GDTag
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Classes.Eq Data.Gedcom.Internal.CoreTypes.GDTree
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Classes.Eq Data.Gedcom.Internal.CoreTypes.GDXRefID
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Gedcom.Internal.CoreTypes.GDRef a)
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Classes.Ord Data.Gedcom.Internal.CoreTypes.GDLevel
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Classes.Ord Data.Gedcom.Internal.CoreTypes.GDTag
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Classes.Ord Data.Gedcom.Internal.CoreTypes.GDXRefID
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Num.Num Data.Gedcom.Internal.CoreTypes.GDLevel
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Show.Show Data.Gedcom.Internal.CoreTypes.GDError
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Show.Show Data.Gedcom.Internal.CoreTypes.GDEscape
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Show.Show Data.Gedcom.Internal.CoreTypes.GDLevel
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Show.Show Data.Gedcom.Internal.CoreTypes.GDLine
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Show.Show Data.Gedcom.Internal.CoreTypes.GDLineItem
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Show.Show Data.Gedcom.Internal.CoreTypes.GDLineValue
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Show.Show Data.Gedcom.Internal.CoreTypes.GDRefError
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Show.Show Data.Gedcom.Internal.CoreTypes.GDRoot
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Show.Show Data.Gedcom.Internal.CoreTypes.GDTag
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Show.Show Data.Gedcom.Internal.CoreTypes.GDTree
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Show.Show Data.Gedcom.Internal.CoreTypes.GDXRefID
+ Data.Gedcom.Internal.CoreTypes: instance GHC.Show.Show a => GHC.Show.Show (Data.Gedcom.Internal.CoreTypes.GDRef a)
+ Data.Gedcom.Internal.CoreTypes: newtype GDEscape
+ Data.Gedcom.Internal.CoreTypes: newtype GDLevel
+ Data.Gedcom.Internal.CoreTypes: newtype GDLineItem
+ Data.Gedcom.Internal.CoreTypes: newtype GDTag
+ Data.Gedcom.Internal.CoreTypes: newtype GDXRefID
+ Data.Gedcom.Internal.LineParser: gdDelim :: Parser (Maybe Char)
+ Data.Gedcom.Internal.LineParser: gdRoot :: Parser GDRoot
+ Data.Gedcom.Internal.ParseMonads: addReference :: Typeable a => GDXRefID -> a -> StructureMonad ()
+ Data.Gedcom.Internal.ParseMonads: data MultiMonad a
+ Data.Gedcom.Internal.ParseMonads: data StructureMonad a
+ Data.Gedcom.Internal.ParseMonads: instance Control.Monad.Error.Class.MonadError Data.Gedcom.Internal.CoreTypes.GDError Data.Gedcom.Internal.ParseMonads.MultiMonad
+ Data.Gedcom.Internal.ParseMonads: instance Control.Monad.Error.Class.MonadError Data.Gedcom.Internal.CoreTypes.GDError Data.Gedcom.Internal.ParseMonads.StructureMonad
+ Data.Gedcom.Internal.ParseMonads: instance GHC.Base.Applicative Data.Gedcom.Internal.ParseMonads.MultiMonad
+ Data.Gedcom.Internal.ParseMonads: instance GHC.Base.Applicative Data.Gedcom.Internal.ParseMonads.StructureMonad
+ Data.Gedcom.Internal.ParseMonads: instance GHC.Base.Functor Data.Gedcom.Internal.ParseMonads.MultiMonad
+ Data.Gedcom.Internal.ParseMonads: instance GHC.Base.Functor Data.Gedcom.Internal.ParseMonads.StructureMonad
+ Data.Gedcom.Internal.ParseMonads: instance GHC.Base.Monad Data.Gedcom.Internal.ParseMonads.MultiMonad
+ Data.Gedcom.Internal.ParseMonads: instance GHC.Base.Monad Data.Gedcom.Internal.ParseMonads.StructureMonad
+ Data.Gedcom.Internal.ParseMonads: parseMulti :: StructureParser a -> MultiMonad [a]
+ Data.Gedcom.Internal.ParseMonads: parseOptional :: StructureParser a -> MultiMonad (Maybe a)
+ Data.Gedcom.Internal.ParseMonads: parseRequired :: GDTag -> StructureParser a -> MultiMonad a
+ Data.Gedcom.Internal.ParseMonads: runMultiMonad :: [GDTree] -> MultiMonad a -> StructureMonad a
+ Data.Gedcom.Internal.ParseMonads: runStructure :: StructureMonad a -> (Either GDError a, Map GDXRefID Dynamic)
+ Data.Gedcom.Internal.ParseMonads: type StructureParser a = GDTree The subtree to parse. -> StructureMonad (Either GDTree a) Either parsed structure, or the subtree itself if the subtree doesn't contain the expected GEDCOM structure.
+ Data.Gedcom.Internal.Parser: parseBoolTag :: GDTag -> StructureParser Bool
+ Data.Gedcom.Internal.Parser: parseGedcom :: GDRoot -> (Either GDError Gedcom, Map GDXRefID Dynamic)
+ Data.Gedcom.Internal.Parser: parseHeader :: StructureParser Header
+ Data.Gedcom.Internal.Parser: parseLinkTag :: Typeable a => GDTag -> StructureParser (GDRef a)
+ Data.Gedcom.Internal.Parser: parseListTag :: GDTag -> StructureParser [Text]
+ Data.Gedcom.Internal.Parser: parseNoLinkTag :: Typeable a => GDTag -> NoLinkHandler a -> StructureParser a
+ Data.Gedcom.Internal.Parser: parseTag :: Typeable a => GDTag -> NoLinkHandler a -> StructureParser (GDRef a)
+ Data.Gedcom.Internal.Parser: parseTextTag :: GDTag -> StructureParser Text
+ Data.Gedcom.Internal.Parser: parseWordTag :: GDTag -> StructureParser Word
+ Data.Gedcom.Structure: AFN :: Text -> AFN
+ Data.Gedcom.Structure: AKA :: NameType
+ Data.Gedcom.Structure: Address :: Text -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> ContactDetails -> Address
+ Data.Gedcom.Structure: Adopted :: Pedigree
+ Data.Gedcom.Structure: Adoption :: (Maybe AdoptionDetail) -> IndividualEventType
+ Data.Gedcom.Structure: AdoptionDetail :: (GDRef Family) -> (Maybe Parent) -> AdoptionDetail
+ Data.Gedcom.Structure: Annuled :: FamilyEventType
+ Data.Gedcom.Structure: Association :: GDRef Individual -> Text -> [SourceCitation] -> [GDRef Note] -> Association
+ Data.Gedcom.Structure: Baptism :: IndividualEventType
+ Data.Gedcom.Structure: BarMitzvah :: IndividualEventType
+ Data.Gedcom.Structure: BasMitzvah :: IndividualEventType
+ Data.Gedcom.Structure: Birth :: (Maybe (GDRef Family)) -> IndividualEventType
+ Data.Gedcom.Structure: BirthName :: NameType
+ Data.Gedcom.Structure: Blessing :: IndividualEventType
+ Data.Gedcom.Structure: BothParents :: Parent
+ Data.Gedcom.Structure: Burial :: IndividualEventType
+ Data.Gedcom.Structure: ByBirth :: Pedigree
+ Data.Gedcom.Structure: CallNumber :: Text -> (Maybe MultimediaType) -> CallNumber
+ Data.Gedcom.Structure: Caste :: Text -> IndividualAttributeType
+ Data.Gedcom.Structure: Census :: EventType
+ Data.Gedcom.Structure: Challenged :: ChildLinkStatus
+ Data.Gedcom.Structure: ChangeDate :: UTCTime -> (Maybe (GDRef Note)) -> ChangeDate
+ Data.Gedcom.Structure: Charset :: Text -> (Maybe Text) -> Charset
+ Data.Gedcom.Structure: ChildToFamilyLink :: GDRef Family -> Maybe Pedigree -> Maybe ChildLinkStatus -> [GDRef Note] -> ChildToFamilyLink
+ Data.Gedcom.Structure: Christening :: (Maybe (GDRef Family)) -> IndividualEventType
+ Data.Gedcom.Structure: ChristeningAdult :: IndividualEventType
+ Data.Gedcom.Structure: Confidential :: RestrictionNotice
+ Data.Gedcom.Structure: Confirmation :: IndividualEventType
+ Data.Gedcom.Structure: ContactDetails :: [Text] -> [Text] -> [Text] -> [Text] -> ContactDetails
+ Data.Gedcom.Structure: Corp :: Text -> Maybe Address -> Corp
+ Data.Gedcom.Structure: Cremation :: IndividualEventType
+ Data.Gedcom.Structure: Date :: Calendar -> (Maybe Word) -> (Maybe Word) -> Year -> Date
+ Data.Gedcom.Structure: DateAbout :: Date -> DateApprox
+ Data.Gedcom.Structure: DateAfter :: Date -> DateRange
+ Data.Gedcom.Structure: DateApproxV :: DateApprox -> DateValue
+ Data.Gedcom.Structure: DateBefore :: Date -> DateRange
+ Data.Gedcom.Structure: DateBetween :: Date -> Date -> DateRange
+ Data.Gedcom.Structure: DateCalculated :: Date -> DateApprox
+ Data.Gedcom.Structure: DateEstimated :: Date -> DateApprox
+ Data.Gedcom.Structure: DateFrom :: Date -> (Maybe Date) -> DatePeriod
+ Data.Gedcom.Structure: DatePeriodV :: DatePeriod -> DateValue
+ Data.Gedcom.Structure: DatePhrase :: (Maybe Date) -> Text -> DateValue
+ Data.Gedcom.Structure: DateRangeV :: DateRange -> DateValue
+ Data.Gedcom.Structure: DateTo :: Date -> DatePeriod
+ Data.Gedcom.Structure: DateV :: Date -> DateValue
+ Data.Gedcom.Structure: Death :: IndividualEventType
+ Data.Gedcom.Structure: Disproved :: ChildLinkStatus
+ Data.Gedcom.Structure: Divorce :: FamilyEventType
+ Data.Gedcom.Structure: DivorceFiled :: FamilyEventType
+ Data.Gedcom.Structure: Education :: Text -> IndividualAttributeType
+ Data.Gedcom.Structure: Emigration :: IndividualEventType
+ Data.Gedcom.Structure: Engagement :: FamilyEventType
+ Data.Gedcom.Structure: EventDetail :: Maybe Text -> Maybe DateValue -> Maybe Place -> Maybe Address -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe RestrictionNotice -> [GDRef Note] -> [SourceCitation] -> [GDRef Multimedia] -> EventDetail
+ Data.Gedcom.Structure: EventType :: Text -> EventType
+ Data.Gedcom.Structure: Fact :: Text -> IndividualAttributeType
+ Data.Gedcom.Structure: FamCensus :: FamilyEventType
+ Data.Gedcom.Structure: Family :: Maybe RestrictionNotice -> [FamilyEvent] -> Maybe (GDRef Individual) -> Maybe (GDRef Individual) -> [GDRef Individual] -> Maybe Word -> [GDRef Submitter] -> [UserReference] -> Maybe RIN -> Maybe ChangeDate -> [GDRef Note] -> [SourceCitation] -> [GDRef Multimedia] -> Family
+ Data.Gedcom.Structure: FamilyEvent :: FamilyEventType -> FamilyEventDetail -> FamilyEvent
+ Data.Gedcom.Structure: FamilyEventDetail :: Maybe Word -> Maybe Word -> EventDetail -> FamilyEventDetail
+ Data.Gedcom.Structure: FamilyEventType :: Text -> FamilyEventType
+ Data.Gedcom.Structure: FamilyEventTypeV :: FamilyEventType -> EventType
+ Data.Gedcom.Structure: Female :: Sex
+ Data.Gedcom.Structure: FirstCommunion :: IndividualEventType
+ Data.Gedcom.Structure: Foster :: Pedigree
+ Data.Gedcom.Structure: French :: Calendar
+ Data.Gedcom.Structure: Gedcom :: Header -> [GDRef Family] -> [GDRef Individual] -> [GDRef Multimedia] -> [GDRef Note] -> [GDRef Repository] -> [GDRef Source] -> [GDRef Submitter] -> Gedcom
+ Data.Gedcom.Structure: GedcomFormat :: Text -> GedcomForm -> GedcomFormat
+ Data.Gedcom.Structure: GedcomLineageLinked :: GedcomForm
+ Data.Gedcom.Structure: GedcomUnsupported :: Text -> GedcomForm
+ Data.Gedcom.Structure: Graduation :: IndividualEventType
+ Data.Gedcom.Structure: Gregorian :: Calendar
+ Data.Gedcom.Structure: Hangul :: PhoneticType
+ Data.Gedcom.Structure: Header :: HeaderSource -> Maybe Text -> Maybe UTCTime -> GDRef Submitter -> Maybe (GDRef Submission) -> Maybe FilePath -> Maybe Text -> GedcomFormat -> Charset -> Maybe Language -> Maybe [Text] -> Maybe Text -> Header
+ Data.Gedcom.Structure: HeaderSource :: Text -> Maybe Text -> Maybe Text -> Maybe Corp -> Maybe HeaderSourceData -> HeaderSource
+ Data.Gedcom.Structure: HeaderSourceData :: Text -> Maybe UTCTime -> Maybe Text -> HeaderSourceData
+ Data.Gedcom.Structure: Hebrew :: Calendar
+ Data.Gedcom.Structure: Husband :: Parent
+ Data.Gedcom.Structure: Immigrant :: NameType
+ Data.Gedcom.Structure: Immigration :: IndividualEventType
+ Data.Gedcom.Structure: Individual :: Maybe RestrictionNotice -> Maybe PersonalName -> Maybe Sex -> [IndividualEvent] -> [IndividualAttribute] -> [ChildToFamilyLink] -> [SpouseToFamilyLink] -> [GDRef Submitter] -> [Association] -> [GDRef Individual] -> [GDRef Submitter] -> [GDRef Submitter] -> Maybe RFN -> Maybe AFN -> [UserReference] -> Maybe RIN -> Maybe ChangeDate -> [GDRef Note] -> [SourceCitation] -> [GDRef Multimedia] -> Individual
+ Data.Gedcom.Structure: IndividualAttribute :: IndividualAttributeType -> (IndividualEventDetail) -> IndividualAttribute
+ Data.Gedcom.Structure: IndividualEvent :: IndividualEventType -> IndividualEventDetail -> IndividualEvent
+ Data.Gedcom.Structure: IndividualEventDetail :: EventDetail -> Maybe Word -> IndividualEventDetail
+ Data.Gedcom.Structure: IndividualEventType :: Text -> IndividualEventType
+ Data.Gedcom.Structure: IndividualEventTypeV :: IndividualEventType -> EventType
+ Data.Gedcom.Structure: IndvCensus :: IndividualEventType
+ Data.Gedcom.Structure: Julian :: Calendar
+ Data.Gedcom.Structure: Kana :: PhoneticType
+ Data.Gedcom.Structure: Language :: Text -> Language
+ Data.Gedcom.Structure: Latitude :: Double -> Latitude
+ Data.Gedcom.Structure: Locked :: RestrictionNotice
+ Data.Gedcom.Structure: Longitude :: Double -> Longitude
+ Data.Gedcom.Structure: MF_BMP :: MultimediaFileFormat
+ Data.Gedcom.Structure: MF_GIF :: MultimediaFileFormat
+ Data.Gedcom.Structure: MF_JPG :: MultimediaFileFormat
+ Data.Gedcom.Structure: MF_OLE :: MultimediaFileFormat
+ Data.Gedcom.Structure: MF_OTHER :: Text -> MultimediaFileFormat
+ Data.Gedcom.Structure: MF_PCX :: MultimediaFileFormat
+ Data.Gedcom.Structure: MF_TIF :: MultimediaFileFormat
+ Data.Gedcom.Structure: MF_WAV :: MultimediaFileFormat
+ Data.Gedcom.Structure: MT_AUDIO :: MultimediaType
+ Data.Gedcom.Structure: MT_BOOK :: MultimediaType
+ Data.Gedcom.Structure: MT_CARD :: MultimediaType
+ Data.Gedcom.Structure: MT_ELECTRONIC :: MultimediaType
+ Data.Gedcom.Structure: MT_FICHE :: MultimediaType
+ Data.Gedcom.Structure: MT_FILM :: MultimediaType
+ Data.Gedcom.Structure: MT_MAGAZINE :: MultimediaType
+ Data.Gedcom.Structure: MT_MANUSCRIPT :: MultimediaType
+ Data.Gedcom.Structure: MT_MAP :: MultimediaType
+ Data.Gedcom.Structure: MT_NEWSPAPER :: MultimediaType
+ Data.Gedcom.Structure: MT_OTHER :: Text -> MultimediaType
+ Data.Gedcom.Structure: MT_PHOTO :: MultimediaType
+ Data.Gedcom.Structure: MT_TOMBSTONE :: MultimediaType
+ Data.Gedcom.Structure: MT_VIDEO :: MultimediaType
+ Data.Gedcom.Structure: Maiden :: NameType
+ Data.Gedcom.Structure: Male :: Sex
+ Data.Gedcom.Structure: MapCoord :: Longitude -> Latitude -> MapCoord
+ Data.Gedcom.Structure: Marriage :: FamilyEventType
+ Data.Gedcom.Structure: MarriageBann :: FamilyEventType
+ Data.Gedcom.Structure: MarriageContract :: FamilyEventType
+ Data.Gedcom.Structure: MarriageLicense :: FamilyEventType
+ Data.Gedcom.Structure: MarriageSettlement :: FamilyEventType
+ Data.Gedcom.Structure: Married :: NameType
+ Data.Gedcom.Structure: Multimedia :: [MultimediaFile] -> Maybe Text -> [UserReference] -> Maybe RIN -> [GDRef Note] -> [SourceCitation] -> Maybe ChangeDate -> Multimedia
+ Data.Gedcom.Structure: MultimediaFile :: Text -> MultimediaFormat -> Maybe Text -> MultimediaFile
+ Data.Gedcom.Structure: MultimediaFormat :: MultimediaFileFormat -> (Maybe MultimediaType) -> MultimediaFormat
+ Data.Gedcom.Structure: NChildren :: Word -> IndividualAttributeType
+ Data.Gedcom.Structure: NMarriages :: Word -> IndividualAttributeType
+ Data.Gedcom.Structure: Name :: Text -> (Maybe Text) -> Name
+ Data.Gedcom.Structure: NameType :: Text -> NameType
+ Data.Gedcom.Structure: NationalID :: Text -> IndividualAttributeType
+ Data.Gedcom.Structure: NationalOrigin :: Text -> IndividualAttributeType
+ Data.Gedcom.Structure: Naturalization :: IndividualEventType
+ Data.Gedcom.Structure: Note :: Text -> [UserReference] -> Maybe RIN -> [SourceCitation] -> Maybe ChangeDate -> Note
+ Data.Gedcom.Structure: Occupation :: Text -> IndividualAttributeType
+ Data.Gedcom.Structure: Ordination :: IndividualEventType
+ Data.Gedcom.Structure: PersonalName :: Name -> Maybe NameType -> PersonalNamePieces -> [PhoneticName] -> [RomanizedName] -> PersonalName
+ Data.Gedcom.Structure: PersonalNamePieces :: [Text] -> [Text] -> [Text] -> [Text] -> [Text] -> [Text] -> [GDRef Note] -> [SourceCitation] -> PersonalNamePieces
+ Data.Gedcom.Structure: PhoneticName :: Name -> PhoneticType -> PersonalNamePieces -> PhoneticName
+ Data.Gedcom.Structure: PhoneticPlaceName :: PhoneticType -> [Text] -> PhoneticPlaceName
+ Data.Gedcom.Structure: PhoneticType :: Text -> PhoneticType
+ Data.Gedcom.Structure: PhysicalDescription :: Text -> IndividualAttributeType
+ Data.Gedcom.Structure: Pinyin :: RomanType
+ Data.Gedcom.Structure: Place :: [Text] -> Maybe [Text] -> Maybe PhoneticPlaceName -> Maybe RomanPlaceName -> Maybe MapCoord -> [GDRef Note] -> Place
+ Data.Gedcom.Structure: Possessions :: Text -> IndividualAttributeType
+ Data.Gedcom.Structure: Privacy :: RestrictionNotice
+ Data.Gedcom.Structure: Probate :: IndividualEventType
+ Data.Gedcom.Structure: Proven :: ChildLinkStatus
+ Data.Gedcom.Structure: QualityAssessment :: Word -> QualityAssessment
+ Data.Gedcom.Structure: RFN :: Text -> RFN
+ Data.Gedcom.Structure: RIN :: Text -> RIN
+ Data.Gedcom.Structure: Religion :: Text -> IndividualAttributeType
+ Data.Gedcom.Structure: Repository :: Text -> Maybe Address -> [GDRef Note] -> [UserReference] -> Maybe RIN -> Maybe ChangeDate -> Repository
+ Data.Gedcom.Structure: RepositoryCitation :: Maybe (GDRef Repository) -> [GDRef Note] -> Maybe CallNumber -> RepositoryCitation
+ Data.Gedcom.Structure: Residence :: FamilyEventType
+ Data.Gedcom.Structure: ResidesAt :: IndividualAttributeType
+ Data.Gedcom.Structure: Retirement :: IndividualEventType
+ Data.Gedcom.Structure: Romaji :: RomanType
+ Data.Gedcom.Structure: RomanPlaceName :: RomanType -> [Text] -> RomanPlaceName
+ Data.Gedcom.Structure: RomanType :: Text -> RomanType
+ Data.Gedcom.Structure: RomanizedName :: Name -> RomanType -> PersonalNamePieces -> RomanizedName
+ Data.Gedcom.Structure: Sealing :: Pedigree
+ Data.Gedcom.Structure: SocialSecurity :: Text -> IndividualAttributeType
+ Data.Gedcom.Structure: Source :: Maybe SourceData -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> Maybe Text -> [RepositoryCitation] -> [UserReference] -> Maybe RIN -> Maybe ChangeDate -> [GDRef Note] -> [GDRef Multimedia] -> Source
+ Data.Gedcom.Structure: SourceCitation :: Either SourceDescription (GDRef Source) -> Maybe Text -> [GDRef Multimedia] -> [GDRef Note] -> Maybe QualityAssessment -> SourceCitation
+ Data.Gedcom.Structure: SourceData :: [SourceRecordedEvent] -> Maybe Text -> [GDRef Note] -> SourceData
+ Data.Gedcom.Structure: SourceDescription :: Text -> [Text] -> SourceDescription
+ Data.Gedcom.Structure: SourceRecordedEvent :: [EventType] -> Maybe DatePeriod -> Maybe [Text] -> SourceRecordedEvent
+ Data.Gedcom.Structure: SpouseToFamilyLink :: GDRef Family -> [GDRef Note] -> SpouseToFamilyLink
+ Data.Gedcom.Structure: Submission :: Maybe (GDRef Submitter) -> Maybe Text -> Maybe Text -> Maybe Word -> Maybe Word -> Maybe Bool -> Maybe RIN -> [GDRef Note] -> Maybe ChangeDate -> Submission
+ Data.Gedcom.Structure: Submitter :: Name -> Maybe Address -> Maybe (GDRef Multimedia) -> [Language] -> Maybe RFN -> Maybe RIN -> [GDRef Note] -> Maybe ChangeDate -> Submitter
+ Data.Gedcom.Structure: Title :: Text -> IndividualAttributeType
+ Data.Gedcom.Structure: Undetermined :: Sex
+ Data.Gedcom.Structure: UserReference :: Text -> (Maybe Text) -> UserReference
+ Data.Gedcom.Structure: WadeGiles :: RomanType
+ Data.Gedcom.Structure: Wife :: Parent
+ Data.Gedcom.Structure: Will :: IndividualEventType
+ Data.Gedcom.Structure: Year :: Int -> Year
+ Data.Gedcom.Structure: [addressCity] :: Address -> Maybe Text
+ Data.Gedcom.Structure: [addressContact] :: Address -> ContactDetails
+ Data.Gedcom.Structure: [addressCountry] :: Address -> Maybe Text
+ Data.Gedcom.Structure: [addressEmail] :: ContactDetails -> [Text]
+ Data.Gedcom.Structure: [addressFax] :: ContactDetails -> [Text]
+ Data.Gedcom.Structure: [addressLines] :: Address -> Text
+ Data.Gedcom.Structure: [addressPhone] :: ContactDetails -> [Text]
+ Data.Gedcom.Structure: [addressPostcode] :: Address -> Maybe Text
+ Data.Gedcom.Structure: [addressState] :: Address -> Maybe Text
+ Data.Gedcom.Structure: [addressWWW] :: ContactDetails -> [Text]
+ Data.Gedcom.Structure: [associationCitation] :: Association -> [SourceCitation]
+ Data.Gedcom.Structure: [associationIndividual] :: Association -> GDRef Individual
+ Data.Gedcom.Structure: [associationNote] :: Association -> [GDRef Note]
+ Data.Gedcom.Structure: [associationRelation] :: Association -> Text
+ Data.Gedcom.Structure: [childLinkFamily] :: ChildToFamilyLink -> GDRef Family
+ Data.Gedcom.Structure: [childLinkNote] :: ChildToFamilyLink -> [GDRef Note]
+ Data.Gedcom.Structure: [childLinkPedigree] :: ChildToFamilyLink -> Maybe Pedigree
+ Data.Gedcom.Structure: [childLinkStatus] :: ChildToFamilyLink -> Maybe ChildLinkStatus
+ Data.Gedcom.Structure: [citeMultimedia] :: SourceCitation -> [GDRef Multimedia]
+ Data.Gedcom.Structure: [citeNote] :: SourceCitation -> [GDRef Note]
+ Data.Gedcom.Structure: [citePage] :: SourceCitation -> Maybe Text
+ Data.Gedcom.Structure: [citeQuality] :: SourceCitation -> Maybe QualityAssessment
+ Data.Gedcom.Structure: [citeSource] :: SourceCitation -> Either SourceDescription (GDRef Source)
+ Data.Gedcom.Structure: [corpAddress] :: Corp -> Maybe Address
+ Data.Gedcom.Structure: [corpName] :: Corp -> Text
+ Data.Gedcom.Structure: [eventDetailAddress] :: EventDetail -> Maybe Address
+ Data.Gedcom.Structure: [eventDetailAgency] :: EventDetail -> Maybe Text
+ Data.Gedcom.Structure: [eventDetailCause] :: EventDetail -> Maybe Text
+ Data.Gedcom.Structure: [eventDetailDate] :: EventDetail -> Maybe DateValue
+ Data.Gedcom.Structure: [eventDetailMultimedia] :: EventDetail -> [GDRef Multimedia]
+ Data.Gedcom.Structure: [eventDetailNote] :: EventDetail -> [GDRef Note]
+ Data.Gedcom.Structure: [eventDetailPlace] :: EventDetail -> Maybe Place
+ Data.Gedcom.Structure: [eventDetailReligion] :: EventDetail -> Maybe Text
+ Data.Gedcom.Structure: [eventDetailRestrictionNotice] :: EventDetail -> Maybe RestrictionNotice
+ Data.Gedcom.Structure: [eventDetailSourceCitation] :: EventDetail -> [SourceCitation]
+ Data.Gedcom.Structure: [eventDetailType] :: EventDetail -> Maybe Text
+ Data.Gedcom.Structure: [familyChangeDate] :: Family -> Maybe ChangeDate
+ Data.Gedcom.Structure: [familyChildren] :: Family -> [GDRef Individual]
+ Data.Gedcom.Structure: [familyEventDetailAgeHusband] :: FamilyEventDetail -> Maybe Word
+ Data.Gedcom.Structure: [familyEventDetailAgeWife] :: FamilyEventDetail -> Maybe Word
+ Data.Gedcom.Structure: [familyEventDetailDetail] :: FamilyEventDetail -> EventDetail
+ Data.Gedcom.Structure: [familyEventDetail] :: FamilyEvent -> FamilyEventDetail
+ Data.Gedcom.Structure: [familyEventType] :: FamilyEvent -> FamilyEventType
+ Data.Gedcom.Structure: [familyEvent] :: Family -> [FamilyEvent]
+ Data.Gedcom.Structure: [familyHusband] :: Family -> Maybe (GDRef Individual)
+ Data.Gedcom.Structure: [familyMultimedia] :: Family -> [GDRef Multimedia]
+ Data.Gedcom.Structure: [familyNote] :: Family -> [GDRef Note]
+ Data.Gedcom.Structure: [familyRIN] :: Family -> Maybe RIN
+ Data.Gedcom.Structure: [familyRestrictionNotice] :: Family -> Maybe RestrictionNotice
+ Data.Gedcom.Structure: [familySourceCitation] :: Family -> [SourceCitation]
+ Data.Gedcom.Structure: [familySubitter] :: Family -> [GDRef Submitter]
+ Data.Gedcom.Structure: [familyTotalChildren] :: Family -> Maybe Word
+ Data.Gedcom.Structure: [familyUserReference] :: Family -> [UserReference]
+ Data.Gedcom.Structure: [familyWife] :: Family -> Maybe (GDRef Individual)
+ Data.Gedcom.Structure: [gedcomFamily] :: Gedcom -> [GDRef Family]
+ Data.Gedcom.Structure: [gedcomForm] :: GedcomFormat -> GedcomForm
+ Data.Gedcom.Structure: [gedcomHeader] :: Gedcom -> Header
+ Data.Gedcom.Structure: [gedcomIndividual] :: Gedcom -> [GDRef Individual]
+ Data.Gedcom.Structure: [gedcomMultimedia] :: Gedcom -> [GDRef Multimedia]
+ Data.Gedcom.Structure: [gedcomNote] :: Gedcom -> [GDRef Note]
+ Data.Gedcom.Structure: [gedcomRepository] :: Gedcom -> [GDRef Repository]
+ Data.Gedcom.Structure: [gedcomSource] :: Gedcom -> [GDRef Source]
+ Data.Gedcom.Structure: [gedcomSubmitter] :: Gedcom -> [GDRef Submitter]
+ Data.Gedcom.Structure: [gedcomVersion] :: GedcomFormat -> Text
+ Data.Gedcom.Structure: [headerCharset] :: Header -> Charset
+ Data.Gedcom.Structure: [headerCopyright] :: Header -> Maybe Text
+ Data.Gedcom.Structure: [headerDate] :: Header -> Maybe UTCTime
+ Data.Gedcom.Structure: [headerDestination] :: Header -> Maybe Text
+ Data.Gedcom.Structure: [headerFile] :: Header -> Maybe FilePath
+ Data.Gedcom.Structure: [headerGedcomFormat] :: Header -> GedcomFormat
+ Data.Gedcom.Structure: [headerLang] :: Header -> Maybe Language
+ Data.Gedcom.Structure: [headerNote] :: Header -> Maybe Text
+ Data.Gedcom.Structure: [headerPlaceForm] :: Header -> Maybe [Text]
+ Data.Gedcom.Structure: [headerSourceCorp] :: HeaderSource -> Maybe Corp
+ Data.Gedcom.Structure: [headerSourceDataCopyright] :: HeaderSourceData -> Maybe Text
+ Data.Gedcom.Structure: [headerSourceDataDate] :: HeaderSourceData -> Maybe UTCTime
+ Data.Gedcom.Structure: [headerSourceDataName] :: HeaderSourceData -> Text
+ Data.Gedcom.Structure: [headerSourceData] :: HeaderSource -> Maybe HeaderSourceData
+ Data.Gedcom.Structure: [headerSourceName] :: HeaderSource -> Maybe Text
+ Data.Gedcom.Structure: [headerSourceSystemID] :: HeaderSource -> Text
+ Data.Gedcom.Structure: [headerSourceVersion] :: HeaderSource -> Maybe Text
+ Data.Gedcom.Structure: [headerSource] :: Header -> HeaderSource
+ Data.Gedcom.Structure: [headerSubmission] :: Header -> Maybe (GDRef Submission)
+ Data.Gedcom.Structure: [headerSubmitter] :: Header -> GDRef Submitter
+ Data.Gedcom.Structure: [individualAFN] :: Individual -> Maybe AFN
+ Data.Gedcom.Structure: [individualAlias] :: Individual -> [GDRef Individual]
+ Data.Gedcom.Structure: [individualAncestorInterest] :: Individual -> [GDRef Submitter]
+ Data.Gedcom.Structure: [individualAssociation] :: Individual -> [Association]
+ Data.Gedcom.Structure: [individualAttribute] :: Individual -> [IndividualAttribute]
+ Data.Gedcom.Structure: [individualChangeDate] :: Individual -> Maybe ChangeDate
+ Data.Gedcom.Structure: [individualChildToFamilyLink] :: Individual -> [ChildToFamilyLink]
+ Data.Gedcom.Structure: [individualDescendantInterest] :: Individual -> [GDRef Submitter]
+ Data.Gedcom.Structure: [individualEventDetailAge] :: IndividualEventDetail -> Maybe Word
+ Data.Gedcom.Structure: [individualEventDetailDetail] :: IndividualEventDetail -> EventDetail
+ Data.Gedcom.Structure: [individualEventDetail] :: IndividualEvent -> IndividualEventDetail
+ Data.Gedcom.Structure: [individualEventType] :: IndividualEvent -> IndividualEventType
+ Data.Gedcom.Structure: [individualEvent] :: Individual -> [IndividualEvent]
+ Data.Gedcom.Structure: [individualMultimedia] :: Individual -> [GDRef Multimedia]
+ Data.Gedcom.Structure: [individualName] :: Individual -> Maybe PersonalName
+ Data.Gedcom.Structure: [individualNote] :: Individual -> [GDRef Note]
+ Data.Gedcom.Structure: [individualRFN] :: Individual -> Maybe RFN
+ Data.Gedcom.Structure: [individualRIN] :: Individual -> Maybe RIN
+ Data.Gedcom.Structure: [individualRestrictionNotice] :: Individual -> Maybe RestrictionNotice
+ Data.Gedcom.Structure: [individualSex] :: Individual -> Maybe Sex
+ Data.Gedcom.Structure: [individualSourceCitation] :: Individual -> [SourceCitation]
+ Data.Gedcom.Structure: [individualSpouseToFamilyLink] :: Individual -> [SpouseToFamilyLink]
+ Data.Gedcom.Structure: [individualSubmitter] :: Individual -> [GDRef Submitter]
+ Data.Gedcom.Structure: [individualUserReference] :: Individual -> [UserReference]
+ Data.Gedcom.Structure: [multimediaChangeDate] :: Multimedia -> Maybe ChangeDate
+ Data.Gedcom.Structure: [multimediaFileFormat] :: MultimediaFile -> MultimediaFormat
+ Data.Gedcom.Structure: [multimediaFileLink] :: MultimediaFile -> Text
+ Data.Gedcom.Structure: [multimediaFile] :: Multimedia -> [MultimediaFile]
+ Data.Gedcom.Structure: [multimediaNote] :: Multimedia -> [GDRef Note]
+ Data.Gedcom.Structure: [multimediaRIN] :: Multimedia -> Maybe RIN
+ Data.Gedcom.Structure: [multimediaSourceCitation] :: Multimedia -> [SourceCitation]
+ Data.Gedcom.Structure: [multimediaTitl] :: Multimedia -> Maybe Text
+ Data.Gedcom.Structure: [multimediaTitle] :: MultimediaFile -> Maybe Text
+ Data.Gedcom.Structure: [multimediaUserReference] :: Multimedia -> [UserReference]
+ Data.Gedcom.Structure: [namePieceGiven] :: PersonalNamePieces -> [Text]
+ Data.Gedcom.Structure: [namePieceNameNote] :: PersonalNamePieces -> [GDRef Note]
+ Data.Gedcom.Structure: [namePieceNickname] :: PersonalNamePieces -> [Text]
+ Data.Gedcom.Structure: [namePiecePrefix] :: PersonalNamePieces -> [Text]
+ Data.Gedcom.Structure: [namePieceSuffix] :: PersonalNamePieces -> [Text]
+ Data.Gedcom.Structure: [namePieceSurnamePrefix] :: PersonalNamePieces -> [Text]
+ Data.Gedcom.Structure: [namePieceSurname] :: PersonalNamePieces -> [Text]
+ Data.Gedcom.Structure: [namePirceSourceCitation] :: PersonalNamePieces -> [SourceCitation]
+ Data.Gedcom.Structure: [noteChangeDate] :: Note -> Maybe ChangeDate
+ Data.Gedcom.Structure: [noteRIN] :: Note -> Maybe RIN
+ Data.Gedcom.Structure: [noteSourceCitation] :: Note -> [SourceCitation]
+ Data.Gedcom.Structure: [noteText] :: Note -> Text
+ Data.Gedcom.Structure: [noteUserReference] :: Note -> [UserReference]
+ Data.Gedcom.Structure: [personalNameName] :: PersonalName -> Name
+ Data.Gedcom.Structure: [personalNamePhonetic] :: PersonalName -> [PhoneticName]
+ Data.Gedcom.Structure: [personalNamePieces] :: PersonalName -> PersonalNamePieces
+ Data.Gedcom.Structure: [personalNameRoman] :: PersonalName -> [RomanizedName]
+ Data.Gedcom.Structure: [personalNameType] :: PersonalName -> Maybe NameType
+ Data.Gedcom.Structure: [phoneticName] :: PhoneticName -> Name
+ Data.Gedcom.Structure: [phoneticPieces] :: PhoneticName -> PersonalNamePieces
+ Data.Gedcom.Structure: [phoneticType] :: PhoneticName -> PhoneticType
+ Data.Gedcom.Structure: [placeForm] :: Place -> Maybe [Text]
+ Data.Gedcom.Structure: [placeMap] :: Place -> Maybe MapCoord
+ Data.Gedcom.Structure: [placeName] :: Place -> [Text]
+ Data.Gedcom.Structure: [placeNote] :: Place -> [GDRef Note]
+ Data.Gedcom.Structure: [placePhonetic] :: Place -> Maybe PhoneticPlaceName
+ Data.Gedcom.Structure: [placeRoman] :: Place -> Maybe RomanPlaceName
+ Data.Gedcom.Structure: [repoCiteCallNumber] :: RepositoryCitation -> Maybe CallNumber
+ Data.Gedcom.Structure: [repoCiteNote] :: RepositoryCitation -> [GDRef Note]
+ Data.Gedcom.Structure: [repoCiteRepository] :: RepositoryCitation -> Maybe (GDRef Repository)
+ Data.Gedcom.Structure: [repositoryAddress] :: Repository -> Maybe Address
+ Data.Gedcom.Structure: [repositoryChangeDate] :: Repository -> Maybe ChangeDate
+ Data.Gedcom.Structure: [repositoryName] :: Repository -> Text
+ Data.Gedcom.Structure: [repositoryNote] :: Repository -> [GDRef Note]
+ Data.Gedcom.Structure: [repositoryRIN] :: Repository -> Maybe RIN
+ Data.Gedcom.Structure: [repositoryUserReference] :: Repository -> [UserReference]
+ Data.Gedcom.Structure: [romanziedName] :: RomanizedName -> Name
+ Data.Gedcom.Structure: [romanziedPieces] :: RomanizedName -> PersonalNamePieces
+ Data.Gedcom.Structure: [romanziedType] :: RomanizedName -> RomanType
+ Data.Gedcom.Structure: [sourceAuthor] :: Source -> Maybe Text
+ Data.Gedcom.Structure: [sourceChangeDate] :: Source -> Maybe ChangeDate
+ Data.Gedcom.Structure: [sourceDataAgency] :: SourceData -> Maybe Text
+ Data.Gedcom.Structure: [sourceDataEventsRecorded] :: SourceData -> [SourceRecordedEvent]
+ Data.Gedcom.Structure: [sourceDataNote] :: SourceData -> [GDRef Note]
+ Data.Gedcom.Structure: [sourceData] :: Source -> Maybe SourceData
+ Data.Gedcom.Structure: [sourceMultimedia] :: Source -> [GDRef Multimedia]
+ Data.Gedcom.Structure: [sourceNote] :: Source -> [GDRef Note]
+ Data.Gedcom.Structure: [sourcePublicationFacts] :: Source -> Maybe Text
+ Data.Gedcom.Structure: [sourceRIN] :: Source -> Maybe RIN
+ Data.Gedcom.Structure: [sourceRecordedDate] :: SourceRecordedEvent -> Maybe DatePeriod
+ Data.Gedcom.Structure: [sourceRecordedEventType] :: SourceRecordedEvent -> [EventType]
+ Data.Gedcom.Structure: [sourceRecordedPlace] :: SourceRecordedEvent -> Maybe [Text]
+ Data.Gedcom.Structure: [sourceRepositoryCitations] :: Source -> [RepositoryCitation]
+ Data.Gedcom.Structure: [sourceShortTitle] :: Source -> Maybe Text
+ Data.Gedcom.Structure: [sourceText] :: Source -> Maybe Text
+ Data.Gedcom.Structure: [sourceTitle] :: Source -> Maybe Text
+ Data.Gedcom.Structure: [sourceUserReference] :: Source -> [UserReference]
+ Data.Gedcom.Structure: [spouseToFamilyLinkFamily] :: SpouseToFamilyLink -> GDRef Family
+ Data.Gedcom.Structure: [spouseToFamilyLinkNote] :: SpouseToFamilyLink -> [GDRef Note]
+ Data.Gedcom.Structure: [submissionAncestorGenerations] :: Submission -> Maybe Word
+ Data.Gedcom.Structure: [submissionChangeDate] :: Submission -> Maybe ChangeDate
+ Data.Gedcom.Structure: [submissionDescendentGenerations] :: Submission -> Maybe Word
+ Data.Gedcom.Structure: [submissionFamilyFile] :: Submission -> Maybe Text
+ Data.Gedcom.Structure: [submissionNote] :: Submission -> [GDRef Note]
+ Data.Gedcom.Structure: [submissionOrdinanceProcessing] :: Submission -> Maybe Bool
+ Data.Gedcom.Structure: [submissionRIN] :: Submission -> Maybe RIN
+ Data.Gedcom.Structure: [submissionSubmitter] :: Submission -> Maybe (GDRef Submitter)
+ Data.Gedcom.Structure: [submissionTempleCode] :: Submission -> Maybe Text
+ Data.Gedcom.Structure: [submitterAddress] :: Submitter -> Maybe Address
+ Data.Gedcom.Structure: [submitterChangeDate] :: Submitter -> Maybe ChangeDate
+ Data.Gedcom.Structure: [submitterLang] :: Submitter -> [Language]
+ Data.Gedcom.Structure: [submitterMedia] :: Submitter -> Maybe (GDRef Multimedia)
+ Data.Gedcom.Structure: [submitterName] :: Submitter -> Name
+ Data.Gedcom.Structure: [submitterNote] :: Submitter -> [GDRef Note]
+ Data.Gedcom.Structure: [submitterRFN] :: Submitter -> Maybe RFN
+ Data.Gedcom.Structure: [submitterRIN] :: Submitter -> Maybe RIN
+ Data.Gedcom.Structure: data Address
+ Data.Gedcom.Structure: data AdoptionDetail
+ Data.Gedcom.Structure: data Association
+ Data.Gedcom.Structure: data Calendar
+ Data.Gedcom.Structure: data CallNumber
+ Data.Gedcom.Structure: data ChangeDate
+ Data.Gedcom.Structure: data Charset
+ Data.Gedcom.Structure: data ChildLinkStatus
+ Data.Gedcom.Structure: data ChildToFamilyLink
+ Data.Gedcom.Structure: data ContactDetails
+ Data.Gedcom.Structure: data Corp
+ Data.Gedcom.Structure: data Date
+ Data.Gedcom.Structure: data DateApprox
+ Data.Gedcom.Structure: data DatePeriod
+ Data.Gedcom.Structure: data DateRange
+ Data.Gedcom.Structure: data DateValue
+ Data.Gedcom.Structure: data EventDetail
+ Data.Gedcom.Structure: data EventType
+ Data.Gedcom.Structure: data Family
+ Data.Gedcom.Structure: data FamilyEvent
+ Data.Gedcom.Structure: data FamilyEventDetail
+ Data.Gedcom.Structure: data FamilyEventType
+ Data.Gedcom.Structure: data Gedcom
+ Data.Gedcom.Structure: data GedcomForm
+ Data.Gedcom.Structure: data GedcomFormat
+ Data.Gedcom.Structure: data Header
+ Data.Gedcom.Structure: data HeaderSource
+ Data.Gedcom.Structure: data HeaderSourceData
+ Data.Gedcom.Structure: data Individual
+ Data.Gedcom.Structure: data IndividualAttribute
+ Data.Gedcom.Structure: data IndividualAttributeType
+ Data.Gedcom.Structure: data IndividualEvent
+ Data.Gedcom.Structure: data IndividualEventDetail
+ Data.Gedcom.Structure: data IndividualEventType
+ Data.Gedcom.Structure: data MapCoord
+ Data.Gedcom.Structure: data Multimedia
+ Data.Gedcom.Structure: data MultimediaFile
+ Data.Gedcom.Structure: data MultimediaFileFormat
+ Data.Gedcom.Structure: data MultimediaFormat
+ Data.Gedcom.Structure: data MultimediaType
+ Data.Gedcom.Structure: data Name
+ Data.Gedcom.Structure: data NameType
+ Data.Gedcom.Structure: data Note
+ Data.Gedcom.Structure: data Parent
+ Data.Gedcom.Structure: data Pedigree
+ Data.Gedcom.Structure: data PersonalName
+ Data.Gedcom.Structure: data PersonalNamePieces
+ Data.Gedcom.Structure: data PhoneticName
+ Data.Gedcom.Structure: data PhoneticPlaceName
+ Data.Gedcom.Structure: data PhoneticType
+ Data.Gedcom.Structure: data Place
+ Data.Gedcom.Structure: data Repository
+ Data.Gedcom.Structure: data RepositoryCitation
+ Data.Gedcom.Structure: data RestrictionNotice
+ Data.Gedcom.Structure: data RomanPlaceName
+ Data.Gedcom.Structure: data RomanType
+ Data.Gedcom.Structure: data RomanizedName
+ Data.Gedcom.Structure: data Sex
+ Data.Gedcom.Structure: data Source
+ Data.Gedcom.Structure: data SourceCitation
+ Data.Gedcom.Structure: data SourceData
+ Data.Gedcom.Structure: data SourceDescription
+ Data.Gedcom.Structure: data SourceRecordedEvent
+ Data.Gedcom.Structure: data SpouseToFamilyLink
+ Data.Gedcom.Structure: data Submission
+ Data.Gedcom.Structure: data Submitter
+ Data.Gedcom.Structure: data UserReference
+ Data.Gedcom.Structure: instance GHC.Classes.Eq Data.Gedcom.Structure.GedcomForm
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.AFN
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Address
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.AdoptionDetail
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Association
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Calendar
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.CallNumber
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.ChangeDate
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Charset
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.ChildLinkStatus
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.ChildToFamilyLink
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.ContactDetails
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Corp
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Date
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.DateApprox
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.DatePeriod
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.DateRange
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.DateValue
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.EventDetail
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.EventType
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Family
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.FamilyEvent
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.FamilyEventDetail
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.FamilyEventType
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Gedcom
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.GedcomForm
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.GedcomFormat
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Header
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.HeaderSource
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.HeaderSourceData
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Individual
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.IndividualAttribute
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.IndividualAttributeType
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.IndividualEvent
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.IndividualEventDetail
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.IndividualEventType
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Language
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Latitude
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Longitude
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.MapCoord
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Multimedia
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.MultimediaFile
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.MultimediaFileFormat
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.MultimediaFormat
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.MultimediaType
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Name
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.NameType
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Note
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Parent
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Pedigree
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.PersonalName
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.PersonalNamePieces
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.PhoneticName
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.PhoneticPlaceName
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.PhoneticType
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Place
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.QualityAssessment
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.RFN
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.RIN
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Repository
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.RepositoryCitation
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.RestrictionNotice
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.RomanPlaceName
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.RomanType
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.RomanizedName
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Sex
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Source
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.SourceCitation
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.SourceData
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.SourceDescription
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.SourceRecordedEvent
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.SpouseToFamilyLink
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Submission
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Submitter
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.UserReference
+ Data.Gedcom.Structure: instance GHC.Show.Show Data.Gedcom.Structure.Year
+ Data.Gedcom.Structure: newtype AFN
+ Data.Gedcom.Structure: newtype Language
+ Data.Gedcom.Structure: newtype Latitude
+ Data.Gedcom.Structure: newtype Longitude
+ Data.Gedcom.Structure: newtype QualityAssessment
+ Data.Gedcom.Structure: newtype RFN
+ Data.Gedcom.Structure: newtype RIN
+ Data.Gedcom.Structure: newtype Year

Files

changelog.md view
@@ -1,3 +1,8 @@+0.2.0.0+	* Upgrade to stackage 9.6 and make ready for GHC 8.2+  * Add some test cases+  * Expose internal modules+ 0.1.0.0   * Initial release 
gedcom.cabal view
@@ -1,15 +1,14 @@ name:                gedcom-version:             0.1.0.0+version:             0.2.0.0 synopsis:            Parser for the GEDCOM genealogy file format. description:         A parser for the legacy GEDCOM 5.5 file format. GEDCOM is-                     widely used by genealogy software, despite the limitations-                     of the format.+                     a widely used file format in genealogy. homepage:            https://github.com/CLowcay/hs-gedcom license:             BSD3 license-file:        LICENSE author:              Callum Lowcay maintainer:          cwslowcay@gmail.com-copyright:           2017 Callum Lowcay+copyright:           2018 Callum Lowcay category:            Genealogy build-type:          Simple extra-source-files:  README.md changelog.md@@ -19,22 +18,23 @@   hs-source-dirs:      src   ghc-options:         -Wall   exposed-modules:     Data.Gedcom-                       , Data.Text.Encoding.ANSEL-  other-modules:       Data.Gedcom.Common                        , Data.Gedcom.Internal.Common-                       , Data.Gedcom.LineParser-                       , Data.Gedcom.ParseMonads-                       , Data.Gedcom.Parser+                       , Data.Gedcom.Internal.CoreTypes+                       , Data.Gedcom.Internal.LineParser+                       , Data.Gedcom.Internal.ParseMonads+                       , Data.Gedcom.Internal.Parser                        , Data.Gedcom.Structure-  build-depends:       base >= 4.7 && < 5+                       , Data.Text.Encoding.ANSEL+  other-modules:       +  build-depends:       base >= 4.8 && < 5                        , array >= 0.5.1.1 && < 0.6                        , bytestring >= 0.10.8.1 && < 0.11                        , containers >= 0.5.7.1 && < 0.6-                       , megaparsec >= 5.3.1 && < 5.4-                       , monad-loops >= 0.4.3 && < 4.4+                       , megaparsec >= 6.3 && < 6.4+                       , monad-loops >= 0.4.3 && < 0.5                        , mtl >= 2.2.1 && < 2.3                        , text-all >= 0.4.1.1 && < 0.5-                       , time >= 1.6.0.1 && < 1.7+                       , time >= 1.8 && < 1.9   default-language:    Haskell2010  test-suite gedcom-test@@ -43,6 +43,9 @@   main-is:             Spec.hs   build-depends:       base                      , gedcom+                     , hspec >= 2.4.4 && < 2.5+                     , text-all >= 0.4.1.1 && < 0.5+                       , megaparsec >= 5.3.1 && < 5.4   ghc-options:         -threaded -rtsopts -with-rtsopts=-N   default-language:    Haskell2010 
src/Data/Gedcom.hs view
@@ -24,14 +24,15 @@ import Control.Applicative import Data.Dynamic import Data.Either-import Data.Gedcom.Common-import Data.Gedcom.LineParser-import Data.Gedcom.ParseMonads-import Data.Gedcom.Parser+import Data.Gedcom.Internal.CoreTypes+import Data.Gedcom.Internal.LineParser+import Data.Gedcom.Internal.ParseMonads+import Data.Gedcom.Internal.Parser import Data.Gedcom.Structure import Data.Maybe import Data.Monoid import Data.Text.Encoding.ANSEL+import Data.Typeable import qualified Data.ByteString as B import qualified Data.Map as M import qualified Data.Text.All as T
− src/Data/Gedcom/Common.hs
@@ -1,131 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE OverloadedStrings #-}--{-|-Module: Data.Gedcom.Common-Description: Common utility functions for parsing GEDCOM-Copyright: (c) Callum Lowcay, 2017-License: BSD3-Maintainer: cwslowcay@gmail.com-Stability: experimental-Portability: GHC--}-module Data.Gedcom.Common (-  GDRefError (..),-  GDError (..),-  GDRef (..),-  GDRoot (..),-  GDTree (..),-  GDLine (..),-  GDLineValue (..),-  GDLineItem (..),-  GDEscape (..),-  GDXRefID (..),-  GDTag (..),-  GDLevel (..),--  gdLineData,-  gdTrimLineItem,-  gdIgnoreEscapes,-  gdFilterEscapes-) where--import Control.Arrow-import Data.Char-import Data.List-import Data.Monoid-import Data.Typeable-import qualified Data.Text.All as T---- | An error arising from dereferencing a 'GDRef'-data GDRefError =-    RefNotPresent GDXRefID         -- ^ The referred structure doesn't exist.-  | WrongRefType TypeRep TypeRep   -- ^ Dereferenced structure had the wrong type--instance Show GDRefError where-  show (RefNotPresent thisID) = "Missing referenced structure " ++ (show thisID)-  show (WrongRefType got expected) = "Referenced value has wrong type, expected "-    ++ (show expected) ++ " but saw " ++ (show got)---- | A parse error.-data GDError =-    LineFormatError T.Text -- ^ A badly formatted GEDCOM line-  | UnexpectedRef T.Text   -- ^ A reference where a reference wasn't allowed-  | RequiredRef T.Text     -- ^ Missing a reference where a reference was required-  | DuplicateRef T.Text    -- ^ Two targets for the same reference-  | FormatError T.Text     -- ^ A badly formatted field-  | TagError T.Text        -- ^ The wrong tag-  deriving Show---- | A reference to another structure-data GDRef a =-    GDStructure a          -- ^ Already dereferenced.-  | GDXRef GDXRefID        -- ^ The 'GDXRefID' to look up-  deriving Show---- | A raw GEDCOM syntax tree-data GDRoot = GDRoot [GDTree] deriving Show---- | A GEDCOM subtree-data GDTree = GDTree GDLine [GDTree] deriving Show---- | A GEDCOM line-data GDLine = GDLine GDLevel (Maybe GDXRefID) GDTag (Maybe GDLineValue)-  deriving Show---- | The value field-data GDLineValue =-  GDLineItemV GDLineItem | GDXRefIDV GDXRefID deriving (Show, Eq)---- | Line text-newtype GDLineItem = GDLineItem [(Maybe GDEscape, T.Text)] deriving (Show, Eq)---- | An escape sequence-newtype GDEscape = GDEscape T.Text deriving (Show, Eq)---- | A cross reference ID-newtype GDXRefID = GDXRefID T.Text deriving (Show, Eq, Ord)---- | The tag field-newtype GDTag = GDTag T.Text deriving (Show, Eq, Ord)---- | The level field-newtype GDLevel = GDLevel Int deriving (Show, Eq, Ord, Num)---- | Extract the line text-gdLineData :: GDLineItem -> [(Maybe GDEscape, T.Text)]-gdLineData (GDLineItem v) = v--instance Monoid GDLineItem where-  mempty = GDLineItem []-  mappend (GDLineItem l1) (GDLineItem l2) =-    GDLineItem . fmap coalease . groupBy canCoalease$ l1 <> l2-    where-      coalease [] = (Nothing, "") -      coalease (l:ls) = foldl' (\(_, t1) (e, t2) -> (e, t1 <> t2)) l ls-      canCoalease (Nothing, _) (_, _) = True-      canCoalease _ _ = False---- | Trim white space off the start an end of a GEDCOM line text.-gdTrimLineItem :: GDLineItem -> GDLineItem-gdTrimLineItem (GDLineItem []) = GDLineItem []-gdTrimLineItem (GDLineItem ((e, t):rst)) =-  let-    rst' = reverse$ case reverse rst of-      [] -> []-      ((e', t'):rst'') -> (e', T.dropWhile isSpace t'):rst''-  in GDLineItem$ (e, T.dropWhile isSpace t):rst'---- | Ignore escape sequences-gdIgnoreEscapes :: [(Maybe GDEscape, T.Text)] -> T.Text-gdIgnoreEscapes  = T.concat . fmap snd---- | Ignore certain escape sequences-gdFilterEscapes ::-  [GDEscape] -> [(Maybe GDEscape, T.Text)] -> [(Maybe GDEscape, T.Text)]-gdFilterEscapes escapes =-  gdLineData . mconcat . fmap GDLineItem . fmap (:[]) . fmap (first f)-  where-    f (Just e) = if e `elem` escapes then Just e else Nothing-    f Nothing = Nothing-
src/Data/Gedcom/Internal/Common.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE OverloadedStrings #-}+ {-| Module: Data.Gedcom.Internal.Common Description: Common utility functions for parsing@@ -17,11 +19,13 @@ import Data.Char import Data.Maybe import Data.Time.Clock+import Data.Void import qualified Data.Text.All as T import Text.Megaparsec+import Text.Megaparsec.Char  -- | Parsers from 'T.Text' using the default error component.-type Parser = Parsec Dec T.Text+type Parser = Parsec Void T.Text  infixl 1 <&> 
+ src/Data/Gedcom/Internal/CoreTypes.hs view
@@ -0,0 +1,131 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}++{-|+Module: Data.Gedcom.Common+Description: Common utility functions for parsing GEDCOM+Copyright: (c) Callum Lowcay, 2017+License: BSD3+Maintainer: cwslowcay@gmail.com+Stability: experimental+Portability: GHC+-}+module Data.Gedcom.Internal.CoreTypes (+  GDRefError (..),+  GDError (..),+  GDRef (..),+  GDRoot (..),+  GDTree (..),+  GDLine (..),+  GDLineValue (..),+  GDLineItem (..),+  GDEscape (..),+  GDXRefID (..),+  GDTag (..),+  GDLevel (..),++  gdLineData,+  gdTrimLineItem,+  gdIgnoreEscapes,+  gdFilterEscapes+) where++import Control.Arrow+import Data.Char+import Data.List+import Data.Monoid+import Data.Typeable+import qualified Data.Text.All as T++-- | An error arising from dereferencing a 'GDRef'+data GDRefError =+    RefNotPresent GDXRefID         -- ^ The referred structure doesn't exist.+  | WrongRefType TypeRep TypeRep   -- ^ Dereferenced structure had the wrong type++instance Show GDRefError where+  show (RefNotPresent thisID) = "Missing referenced structure " ++ (show thisID)+  show (WrongRefType got expected) = "Referenced value has wrong type, expected "+    ++ (show expected) ++ " but saw " ++ (show got)++-- | A parse error.+data GDError =+    LineFormatError T.Text -- ^ A badly formatted GEDCOM line+  | UnexpectedRef T.Text   -- ^ A reference where a reference wasn't allowed+  | RequiredRef T.Text     -- ^ Missing a reference where a reference was required+  | DuplicateRef T.Text    -- ^ Two targets for the same reference+  | FormatError T.Text     -- ^ A badly formatted field+  | TagError T.Text        -- ^ The wrong tag+  deriving Show++-- | A reference to another structure+data GDRef a =+    GDStructure a          -- ^ Already dereferenced.+  | GDXRef GDXRefID        -- ^ The 'GDXRefID' to look up+  deriving (Show, Eq)++-- | A raw GEDCOM syntax tree+data GDRoot = GDRoot [GDTree] deriving (Show, Eq)++-- | A GEDCOM subtree+data GDTree = GDTree GDLine [GDTree] deriving (Show, Eq)++-- | A GEDCOM line+data GDLine = GDLine GDLevel (Maybe GDXRefID) GDTag (Maybe GDLineValue)+  deriving (Show, Eq)++-- | The value field+data GDLineValue =+  GDLineItemV GDLineItem | GDXRefIDV GDXRefID deriving (Show, Eq)++-- | Line text+newtype GDLineItem = GDLineItem [(Maybe GDEscape, T.Text)] deriving (Show, Eq)++-- | An escape sequence+newtype GDEscape = GDEscape T.Text deriving (Show, Eq)++-- | A cross reference ID+newtype GDXRefID = GDXRefID T.Text deriving (Show, Eq, Ord)++-- | The tag field+newtype GDTag = GDTag T.Text deriving (Show, Eq, Ord)++-- | The level field+newtype GDLevel = GDLevel Int deriving (Show, Eq, Ord, Num)++-- | Extract the line text+gdLineData :: GDLineItem -> [(Maybe GDEscape, T.Text)]+gdLineData (GDLineItem v) = v++instance Monoid GDLineItem where+  mempty = GDLineItem []+  mappend (GDLineItem l1) (GDLineItem l2) =+    GDLineItem . fmap coalease . groupBy canCoalease$ l1 <> l2+    where+      coalease [] = (Nothing, "") +      coalease (l:ls) = foldl' (\(_, t1) (e, t2) -> (e, t1 <> t2)) l ls+      canCoalease (Nothing, _) (_, _) = True+      canCoalease _ _ = False++-- | Trim white space off the start an end of a GEDCOM line text.+gdTrimLineItem :: GDLineItem -> GDLineItem+gdTrimLineItem (GDLineItem []) = GDLineItem []+gdTrimLineItem (GDLineItem ((e, t):rst)) =+  let+    rst' = reverse$ case reverse rst of+      [] -> []+      ((e', t'):rst'') -> (e', T.dropWhile isSpace t'):rst''+  in GDLineItem$ (e, T.dropWhile isSpace t):rst'++-- | Ignore escape sequences+gdIgnoreEscapes :: [(Maybe GDEscape, T.Text)] -> T.Text+gdIgnoreEscapes  = T.concat . fmap snd++-- | Ignore certain escape sequences+gdFilterEscapes ::+  [GDEscape] -> [(Maybe GDEscape, T.Text)] -> [(Maybe GDEscape, T.Text)]+gdFilterEscapes escapes =+  gdLineData . mconcat . fmap GDLineItem . fmap (:[]) . fmap (first f)+  where+    f (Just e) = if e `elem` escapes then Just e else Nothing+    f Nothing = Nothing+
+ src/Data/Gedcom/Internal/LineParser.hs view
@@ -0,0 +1,148 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TupleSections #-}++{-|+Module: Data.Gedcom.LineParser+Description: Low-level GEDCOM parser+Copyright: (c) Callum Lowcay, 2017+License: BSD3+Maintainer: cwslowcay@gmail.com+Stability: experimental+Portability: GHC++This module parses a Text string into a GEDCOM syntax tree.++-}+module Data.Gedcom.Internal.LineParser (+  gdRoot, gdDelim+) where++import Control.Monad+import Data.Char+import Data.Gedcom.Internal.Common+import Data.Gedcom.Internal.CoreTypes+import Data.Maybe+import Data.Monoid+import qualified Data.Text.All as T+import Text.Megaparsec+import Text.Megaparsec.Char++-- | Parse any_char.+gdAnyChar :: Parser T.Text+gdAnyChar = (fmap T.singleton gdNonAt) <|> "@@"++-- | Parse non_at.+gdNonAt :: Parser Char+gdNonAt = satisfy (\c -> (not.isControl) c && c /= '@' && c /= '\x7F')++-- | Parse alphanum.+gdAlphaNum :: Parser Char+gdAlphaNum = alphaNumChar <|> char '_'++-- | Parse delim.+gdDelim :: Parser (Maybe Char)+gdDelim = optional$ char '\x20'++-- | Parse escape.+gdEscape :: Parser GDEscape+gdEscape = GDEscape <$>+  ("@#" *> gdEscapeText <* char '@' <* (optional$ char ' '))++-- | Parse escape_text.+gdEscapeText :: Parser T.Text+gdEscapeText = T.concat <$> many gdAnyChar++-- | Parse level.+gdLevel :: Parser GDLevel+gdLevel = GDLevel . read <$> count' 1 2 digitChar <* gdDelim++-- | Parse line_item.+gdLineItem :: Parser GDLineItem+gdLineItem = fmap GDLineItem . some$+  (,) <$> optional gdEscape <*> (T.concat <$> some gdAnyChar)++-- | Parse pointer.+gdPointer :: Parser GDXRefID+gdPointer = char '@' *> plabel <* char '@'+  where plabel = fmap (GDXRefID . T.pack)$+                  (:) <$> gdAlphaNum <*> (many gdNonAt)++-- | Parse line_value+gdLineValue :: Parser GDLineValue+gdLineValue = eitherP gdPointer gdLineItem <&> \x -> case x of+  Left v -> GDXRefIDV v+  Right v -> GDLineItemV v++-- | Parse optional_line_value.+gdOptionalLineValue :: Parser GDLineValue+gdOptionalLineValue = gdDelim *> gdLineValue++-- | Parse optional_xref_ID.+gdOptionalXRefID :: Parser (Maybe GDXRefID)+gdOptionalXRefID = gdXRefID <* gdDelim++-- | Parse tag.+gdTag :: Parser GDTag+gdTag = GDTag . T.toUpper . T.pack <$> many gdAlphaNum++-- | parse terminator.+gdTerminator :: Parser T.Text+gdTerminator = "\n" <|> "\r" <|> "\r\n" <|> "\n\r"++-- | Parse xref_ID.+gdXRefID :: Parser (Maybe GDXRefID)+gdXRefID = optional $ fmap (\(GDXRefID t) -> GDXRefID t) gdPointer++-- | Parse gedcom_line.+gdLine :: Parser GDLine+gdLine = GDLine <$>+  gdLevel <*>+  gdOptionalXRefID <*>+  gdTag <*>+  (optional gdOptionalLineValue) <* gdTerminator++-- | Convert local ids to global ids.+gdExpandID ::+     GDXRefID -- ^ The parent structure's ID+  -> GDXRefID -- ^ The local ID.+  -> GDXRefID -- ^ A global ID.+gdExpandID (GDXRefID pid) s@(GDXRefID sub) =+  case T.uncons sub of+    Nothing -> s+    Just ('!', _) -> GDXRefID$ pid <> sub+    _ -> s++-- | Convert local ids to global ids.+gdExpandPointer ::+     GDXRefID     -- ^ The parent structure's ID.+  -> GDLineValue  -- ^ The line to update.+  -> GDLineValue  -- ^ An updated line where local ID's have been made global.+gdExpandPointer pid v = case v of+  GDLineItemV _ -> v+  GDXRefIDV p -> GDXRefIDV$ gdExpandID pid p++-- | Parse a line at a fixed level+gdLineLevel ::+     GDXRefID -- ^ The parent ID +  -> GDLevel  -- ^ The level to parse the line at+  -> Parser GDLine+gdLineLevel pid n = do+  (GDLine n' xrid tag v) <- gdLine+  when (n' /= n)$ fail$ "Saw a " ++ (show tag) +++    " tag at level " ++ (show n') +++    " but expected level was " ++ (show n)+  return$ GDLine n' (fmap (gdExpandID pid) xrid) tag (fmap (gdExpandPointer pid) v)++-- | Parse a GEDCOM subtree+gdTree ::+     GDXRefID -- ^ The parent ID+  -> GDLevel  -- ^ The level where the subtree is rooted+  -> Parser GDTree+gdTree pid n = try$ do+  line@(GDLine _ pid' _ _) <- gdLineLevel pid n+  GDTree line <$> many (gdTree (fromMaybe pid pid') (n + 1))++-- | Parse the raw GEDCOM syntax tree.+gdRoot :: Parser GDRoot+gdRoot = GDRoot <$> (many$ gdTree (GDXRefID "") 0)+
+ src/Data/Gedcom/Internal/ParseMonads.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}++{-|+Module: Data.Gedcom.ParseMonads+Description: Monads for parsing GEDCOM records+Copyright: (c) Callum Lowcay, 2017+License: BSD3+Maintainer: cwslowcay@gmail.com+Stability: experimental+Portability: GHC++This module contains monads and utility functions for extracting GEDCOM records+from the raw syntax tree.++-}+module Data.Gedcom.Internal.ParseMonads (+  StructureParser,+  MultiMonad,+  runMultiMonad,+  parseMulti,+  parseOptional,+  parseRequired,+  StructureMonad,+  addReference,+  runStructure+) where++import Control.Monad+import Control.Monad.Except+import Control.Monad.State+import Data.Dynamic+import Data.Either+import Data.Foldable+import Data.Gedcom.Internal.CoreTypes+import Data.Maybe+import Data.Monoid+import qualified Data.Map as M+import qualified Data.Text.All as T++-- | A parser that extracts a GEDCOM structure from a GEDCOM subtree.+type StructureParser a =+     GDTree                               -- ^ The  subtree to parse.+  -> StructureMonad (Either GDTree a)     -- ^ Either parsed structure, or the subtree itself if the subtree doesn't contain the expected GEDCOM structure.++-- | A Monad for parsing GEDCOM structures out of a list of GEDCOM subtrees.+newtype MultiMonad a =+  MultiMonad (ExceptT GDError (StateT [GDTree] StructureMonad) a)+  deriving (Monad, Functor, Applicative, MonadError GDError)++-- | Run a 'MultiMonad' into a 'StructureMonad'.+runMultiMonad ::+     [GDTree]         -- ^ The subtrees to parse the structure from.+  -> MultiMonad a     -- ^ The MultiMonad that does the parsing.+  -> StructureMonad a+runMultiMonad children (MultiMonad m) =+  ((flip evalStateT) children.runExceptT$ m) >>= rethrowError+  where rethrowError x = case x of+                           Left e -> throwError e+                           Right v -> return v++-- | Parse multiple instances of a structure+parseMulti :: StructureParser a -> MultiMonad [a]+parseMulti p = MultiMonad$ do+  ls <- lift$ get+  (others, vs) <- lift$ lift$ partitionEithers <$> p `traverse` ls+  lift$ put others+  return vs++-- | Parse an optional instance of a structure+parseOptional :: StructureParser a -> MultiMonad (Maybe a)+parseOptional p = MultiMonad$ do+  ls <- lift$ get+  (mr, leftover) <-+    lift$ lift$ foldrM (\v (r, rest) ->+      if isJust r then return (r, v:rest)+      else pick v rest.toMaybe <$> p v) (Nothing, []) ls+  lift$ put leftover+  return mr+  where+    toMaybe (Left _) = Nothing+    toMaybe (Right v) = Just v+    pick v rest Nothing = (Nothing, v:rest)+    pick _ rest x = (x, rest)++-- | Parse a required instance of a structure+parseRequired ::+     GDTag       -- ^ The tag that identifies the required structure.+  -> StructureParser a+  -> MultiMonad a+parseRequired tag p = do+  r <- parseOptional p+  case r of+    Just v -> return v+    Nothing -> throwError.TagError$+      "Could not find required " <> (T.show tag) <> " tag"++-- | A monad for parsing an instance of a GEDCOM structure from a GEDCOM+-- subtree.+newtype StructureMonad a =+  StructureMonad (ExceptT GDError (State (M.Map GDXRefID Dynamic)) a)+  deriving (Monad, Functor, Applicative, MonadError GDError)++-- | Add a reference to the cross reference table.+addReference :: Typeable a+  => GDXRefID            -- ^ The cross reference to add.+  -> a                   -- ^ The value the reference will resolve to.+  -> StructureMonad ()+addReference thisID value = StructureMonad$ do+  alreadySeen <- M.member thisID <$> lift get+  when alreadySeen$+    throwError.DuplicateRef$ "Duplicate definition of " <> (T.show thisID)+  lift.modify$ M.insert thisID (toDyn value)+  return ()++-- | Run a 'StructureMonad', returning either an error or a value, and the+-- cross reference table.+runStructure :: StructureMonad a -> (Either GDError a, M.Map GDXRefID Dynamic)+runStructure (StructureMonad m) = (flip runState) M.empty . runExceptT$ m+
+ src/Data/Gedcom/Internal/Parser.hs view
@@ -0,0 +1,1135 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecursiveDo #-}+{-# LANGUAGE TupleSections #-}++{-|+Module: Data.Gedcom.Parser+Description: GEDCOM high level parsers+Copyright: (c) Callum Lowcay, 2017+License: BSD3+Maintainer: cwslowcay@gmail.com+Stability: experimental+Portability: GHC++These parsers extract the GEDCOM records from the raw syntax tree.++-}+module Data.Gedcom.Internal.Parser (+  parseGedcom,+  parseHeader,++  parseBoolTag,+  parseWordTag,+  parseTextTag,+  parseListTag,+  parseTag,+  parseLinkTag,+  parseNoLinkTag+) where++import Control.Applicative+import Control.Monad.Except+import Data.Bifunctor+import Data.Dynamic+import Data.Gedcom.Internal.Common+import Data.Gedcom.Internal.CoreTypes+import Data.Gedcom.Internal.LineParser+import Data.Gedcom.Internal.ParseMonads+import Data.Gedcom.Structure+import Data.Maybe+import Data.Monoid+import Data.Time.Calendar+import Data.Time.Clock+import qualified Data.Map.Lazy as M+import qualified Data.Text.All as T+import Text.Megaparsec+import Text.Megaparsec.Char++-- | Parse a 'Gedcom' value from the raw GEDCOM syntax tree.+parseGedcom :: GDRoot -> (Either GDError Gedcom, M.Map GDXRefID Dynamic)+parseGedcom (GDRoot children) =+  runStructure.runMultiMonad children$ Gedcom+    <$> parseRequired (GDTag "HEAD") parseHeader+    <*> parseMulti parseFamily+    <*> parseMulti (parseIndividual (GDTag "INDI"))+    <*> parseMulti parseMultimediaRecord+    <*> parseMulti parseNote+    <*> parseMulti parseRepository+    <*> parseMulti parseSource+    <*> parseMulti (parseSubmitter (GDTag "SUBM"))++-- | Parse a 'Header'.+parseHeader :: StructureParser Header+parseHeader = parseNoLinkTag (GDTag "HEAD")$ \(_, children) ->+  runMultiMonad children$ Header+    <$> parseRequired (GDTag "SOUR") parseHeaderSource+    <*> parseOptional (parseTextTag (GDTag "DEST"))+    <*> parseOptional parseExactDateTime+    <*> parseRequired (GDTag "SUBM") (parseSubmitter (GDTag "SUBM"))+    <*> parseOptional parseSubmission+    <*> parseOptional parseFile+    <*> parseOptional parseCopyright+    <*> parseRequired (GDTag "GEDC") parseGedcomFormat+    <*> parseRequired (GDTag "CHAR") parseCharset+    <*> parseOptional parseLanguage+    <*> parseOptional parsePlaceForm+    <*> parseOptional (parseTextTag (GDTag "NOTE"))++-- | Parse a 'HeaderSource'.+parseHeaderSource :: StructureParser HeaderSource+parseHeaderSource = parseNoLinkTag (GDTag "SOUR")$ \(sid, children) ->+  runMultiMonad children$ HeaderSource (gdIgnoreEscapes sid)+    <$> parseOptional parseVersion+    <*> parseOptional parseName+    <*> parseOptional parseCorp+    <*> parseOptional parseHeaderSourceData++-- | Parse a 'Corp'.+parseCorp :: StructureParser Corp+parseCorp = parseNoLinkTag (GDTag "COPR")$ \(name, children) ->+  runMultiMonad children$ Corp (gdIgnoreEscapes name)+    <$> (parseContactDetails >>= (parseOptional.parseAddress))++-- | Parse a 'HeaderSourceData'.+parseHeaderSourceData :: StructureParser HeaderSourceData+parseHeaderSourceData = parseNoLinkTag (GDTag "DATA")$ \(name, children) ->+  runMultiMonad children$ HeaderSourceData (gdIgnoreEscapes name)+    <$> parseOptional parseExactDate+    <*> parseOptional parseCopyright++-- | Parse a 'Family'.+parseFamily :: StructureParser (GDRef Family)+parseFamily = parseTag (GDTag "FAM")$ \(_, children) ->+  runMultiMonad children$ Family+    <$> parseOptional parseRestrictionNotice+    <*> parseFamilyEvent+    <*> parseOptional (parseIndividual (GDTag "HUSB"))+    <*> parseOptional (parseIndividual (GDTag "WIFE"))+    <*> parseMulti (parseIndividual (GDTag "CHIL"))+    <*> parseOptional (parseWordTag (GDTag "NCHI"))+    <*> parseMulti (parseSubmitter (GDTag "SUBM"))+    <*> parseMulti parseUserReference+    <*> parseOptional parseRIN+    <*> parseOptional parseChangeDate+    <*> parseMulti parseNote+    <*> parseMulti parseSourceCitation+    <*> parseMulti parseMultimedia++-- | Parse an 'Individual'.+parseIndividual :: GDTag -> StructureParser (GDRef Individual)+parseIndividual tag = parseTag tag$ \(_, children) ->+  runMultiMonad children$ Individual+    <$> parseOptional parseRestrictionNotice+    <*> parseOptional parsePersonalName+    <*> parseOptional parseSex+    <*> parseIndividualEvent+    <*> parseIndividualAttribute+    <*> parseMulti parseChildToFamilyLink+    <*> parseMulti parseSpouseToFamilyLink+    <*> parseMulti (parseSubmitter (GDTag "SUBM"))+    <*> parseMulti parseAssociation+    <*> parseMulti (parseIndividual (GDTag "ALIA"))+    <*> parseMulti (parseSubmitter (GDTag "ANCI"))+    <*> parseMulti (parseSubmitter (GDTag "DECI"))+    <*> parseOptional parseRFN+    <*> parseOptional parseAFN+    <*> parseMulti parseUserReference+    <*> parseOptional parseRIN+    <*> parseOptional parseChangeDate+    <*> parseMulti parseNote+    <*> parseMulti parseSourceCitation+    <*> parseMulti parseMultimedia++-- | Parse a 'Node'.+parseNote :: StructureParser (GDRef Note)+parseNote = parseTag (GDTag "NOTE")$ \(t, children) ->+  runMultiMonad children$ Note (gdIgnoreEscapes t)+    <$> parseMulti parseUserReference+    <*> parseOptional parseRIN+    <*> parseMulti parseSourceCitation+    <*> parseOptional parseChangeDate++-- | Parse a 'Repository'.+parseRepository :: StructureParser (GDRef Repository)+parseRepository = parseTag (GDTag "REPO")$ \(_, children) ->+  runMultiMonad children$ Repository+    <$> parseRequired (GDTag "NAME") parseName+    <*> (parseContactDetails >>= (parseOptional.parseAddress))+    <*> parseMulti parseNote+    <*> parseMulti parseUserReference+    <*> parseOptional parseRIN+    <*> parseOptional parseChangeDate++-- | Parse a 'Source'.+parseSource :: StructureParser (GDRef Source)+parseSource = parseTag (GDTag "SOUR")$ \(_, children) ->+  runMultiMonad children$ Source+    <$> parseOptional parseSourceData+    <*> parseOptional (parseTextTag (GDTag "AUTH"))+    <*> parseOptional (parseTextTag (GDTag "TITL"))+    <*> parseOptional (parseTextTag (GDTag "ABBR"))+    <*> parseOptional (parseTextTag (GDTag "PUBL"))+    <*> parseOptional (parseTextTag (GDTag "TEXT"))+    <*> parseMulti parseRepositoryCitation+    <*> parseMulti parseUserReference+    <*> parseOptional parseRIN+    <*> parseOptional parseChangeDate+    <*> parseMulti parseNote+    <*> parseMulti parseMultimedia++-- | Parse a 'Submitter'.+parseSubmitter :: GDTag -> StructureParser (GDRef Submitter)+parseSubmitter tag = parseTag tag$ \(_, children) ->+  runMultiMonad children$ Submitter+    <$> parseRequired (GDTag "NAME")+      ((fmap.fmap.fmap) getPersonalName parseName)+    <*> (parseContactDetails >>= (parseOptional.parseAddress))+    <*> parseOptional parseMultimedia+    <*> parseMulti parseLanguage+    <*> parseOptional parseRFN+    <*> parseOptional parseRIN+    <*> parseMulti parseNote+    <*> parseOptional parseChangeDate++-- | Parse a 'Submission'.+parseSubmission :: StructureParser (GDRef Submission)+parseSubmission = parseTag (GDTag "SUBN")$ \(_, children) ->+  runMultiMonad children$ Submission+    <$> parseOptional (parseSubmitter (GDTag "SUBM"))+    <*> parseOptional (parseTextTag (GDTag "FAMF"))+    <*> parseOptional (parseTextTag (GDTag "TEMP"))+    <*> parseOptional (parseWordTag (GDTag "ANCE"))+    <*> parseOptional (parseWordTag (GDTag "DESC"))+    <*> parseOptional (parseBoolTag (GDTag "ORDI"))+    <*> parseOptional parseRIN+    <*> parseMulti parseNote+    <*> parseOptional parseChangeDate++-- | Parse a 'RestrictionNotice'.+parseRestrictionNotice :: StructureParser RestrictionNotice+parseRestrictionNotice = parseNoLinkTag (GDTag "RESN")$ \(t, _) ->+  case parseMaybe parser (gdIgnoreEscapes t) of+    Nothing -> throwError.FormatError$+      "Bad restriction notice " <> (T.show t)+    Just r -> return r+  where parser :: Parser RestrictionNotice+        parser =     (Confidential <$ "confidential")+                 <|> (Locked <$ "locked")+                 <|> (Privacy <$ "privacy")++-- | Parse a list of 'FamilyEvent's.+parseFamilyEvent :: MultiMonad [FamilyEvent]+parseFamilyEvent = do+    concat <$> mapM (parseMulti.familyEventTag) [+      (GDTag "ANUL", const Annuled),+      (GDTag "CENS", const FamCensus),+      (GDTag "DIV",  const Divorce),+      (GDTag "DIVF", const DivorceFiled),+      (GDTag "ENGA", const Engagement),+      (GDTag "MARB", const MarriageBann),+      (GDTag "MARC", const MarriageContract),+      (GDTag "MARR", const Marriage),+      (GDTag "MARL", const MarriageLicense),+      (GDTag "MARS", const MarriageSettlement),+      (GDTag "RESI", const Residence),+      (GDTag "EVEN", FamilyEventType)]+  where+    familyEventTag (tag, mkType) = parseNoLinkTag tag$ \(t, children) ->+      runMultiMonad children$ FamilyEvent (mkType$ gdIgnoreEscapes t)+        <$> parseFamilyEventDetail++-- | Parse a 'FamiltyEventDetail'.+parseFamilyEventDetail :: MultiMonad FamilyEventDetail+parseFamilyEventDetail = FamilyEventDetail+  <$> parseOptional (parseAge (GDTag "HUSB"))+  <*> parseOptional (parseAge (GDTag "WIFE"))+  <*> parseEventDetail++-- | Parse an 'EventDetail'.+parseEventDetail :: MultiMonad EventDetail+parseEventDetail = EventDetail+  <$> parseOptional (parseTextTag (GDTag "TYPE"))+  <*> parseOptional parseDateValue+  <*> parseOptional parsePlace+  <*> (parseContactDetails >>= (parseOptional.parseAddress))+  <*> parseOptional (parseTextTag (GDTag "AGNC"))+  <*> parseOptional (parseTextTag (GDTag "RELI"))+  <*> parseOptional (parseTextTag (GDTag "CAUS"))+  <*> parseOptional parseRestrictionNotice+  <*> parseMulti parseNote+  <*> parseMulti parseSourceCitation+  <*> parseMulti parseMultimedia++-- | Parse an AGE tag.+parseAge :: GDTag -> StructureParser Word+parseAge tag = parseNoLinkTag tag$ \(_, children) ->+  runMultiMonad children$+    parseRequired (GDTag "AGE") (parseWordTag (GDTag "AGE"))++-- | Parse a 'SourceData'.+parseSourceData :: StructureParser SourceData+parseSourceData = parseNoLinkTag (GDTag "DATA")$ \(_, children) ->+  runMultiMonad children$ SourceData+    <$> parseMulti parseSourceRecordedEvent+    <*> parseOptional (parseTextTag (GDTag "AGNC"))+    <*> parseMulti parseNote++-- | Parse a 'Place'.+parsePlace :: StructureParser Place+parsePlace = parseNoLinkTag (GDTag "PLAC")$ \(t, children) ->+  runMultiMonad children$ Place+    <$> (pure$ T.splitOn "," . gdIgnoreEscapes$ t)+    <*> parseOptional (parseListTag (GDTag "FORM"))+    <*> parseOptional parsePhoneticPlaceName+    <*> parseOptional parseRomanPlaceName+    <*> parseOptional parseMapCoord+    <*> parseMulti parseNote++-- | Parse a 'PhoneticPlaceName'.+parsePhoneticPlaceName :: StructureParser PhoneticPlaceName+parsePhoneticPlaceName = parseNoLinkTag (GDTag "FONE")$ \(t, children) ->+  runMultiMonad children$ PhoneticPlaceName+    <$> parseRequired (GDTag "TYPE") parsePhoneticType+    <*> (pure . T.splitOn "," . gdIgnoreEscapes$ t)++-- | Parse a 'RomanPlaceName'.+parseRomanPlaceName :: StructureParser RomanPlaceName+parseRomanPlaceName = parseNoLinkTag (GDTag "ROMN")$ \(t, children) ->+  runMultiMonad children$ RomanPlaceName+    <$> parseRequired (GDTag "TYPE") parseRomanType+    <*> (pure . T.splitOn "," . gdIgnoreEscapes$ t)++-- | Parse a 'PhoneticType'.+parsePhoneticType :: StructureParser PhoneticType+parsePhoneticType = parseNoLinkTag (GDTag "TYPE")$ \(t, _) ->+  return$ case trim . T.toUpper . gdIgnoreEscapes$ t of+    "HANGUL" -> Hangul+    "KANA" -> Kana+    v -> PhoneticType v++-- | Parse a 'RomanType'.+parseRomanType :: StructureParser RomanType+parseRomanType = parseNoLinkTag (GDTag "TYPE")$ \(t, _) ->+  return$ case trim . T.toUpper . gdIgnoreEscapes$ t of+    "PINYIN" -> Pinyin+    "ROMAJI" -> Romaji+    "WADEGILES" -> WadeGiles+    v -> RomanType v++-- | Parse a 'MapCoord'.+parseMapCoord :: StructureParser MapCoord+parseMapCoord = parseNoLinkTag (GDTag "MAP")$ \(_, children) ->+  runMultiMonad children$ MapCoord+    <$> parseRequired (GDTag "LATI") ((fmap.fmap.fmap) Longitude$+      parseLongLat (GDTag "LATI") 'N' 'S')+    <*> parseRequired (GDTag "LONG") ((fmap.fmap.fmap) Latitude$+      parseLongLat (GDTag "LONG") 'E' 'W')++-- | Parse a 'Longitude' or 'Latitude' value.+parseLongLat ::+     GDTag -- ^ The tag to parse+  -> Char  -- ^ The single character prefix that indicates a positive value.  +  -> Char  -- ^ The single character prefix that indicates a negative value.+  -> StructureParser Double+parseLongLat tag p n = parseNoLinkTag tag$ \(t, _) ->+  case T.uncons . T.toUpper . gdIgnoreEscapes$ t of+    Nothing -> throwError.FormatError$+      "Badly formatted longitude/latitude " <> (T.show t)+    Just (i, r) ->+      if i == p then return$ read . T.unpack$ r+      else if i == n then return$ negate . read . T.unpack$ r+      else throwError.FormatError$+        "Badly formatted longitude/latitude" <> (T.show t)++-- | Parse a 'PersonalName'.+parsePersonalName :: StructureParser PersonalName+parsePersonalName = parseNoLinkTag (GDTag "NAME")$ \(n, children) ->+  runMultiMonad children$ PersonalName+    <$> (pure.getPersonalName.gdIgnoreEscapes$ n)+    <*> parseOptional parseNameType+    <*> parseNamePieces+    <*> parseMulti parsePhoneticName+    <*> parseMulti parseRomanName+    +-- | Extract a 'Name' from a string.+getPersonalName :: T.Text -> Name+getPersonalName = Name <$> reformat <*> (getMiddle . T.splitOn "/")+  where+   reformat = T.unwords . T.words . T.map (\c -> if c == '/' then ' ' else c)+   getMiddle [_, m, _] = Just$ trim m+   getMiddle _ = Nothing++-- | Parse a 'NameType'.+parseNameType :: StructureParser NameType+parseNameType = parseNoLinkTag (GDTag "TYPE")$ \(t', _) ->+  let t = gdIgnoreEscapes t'+  in return . fromMaybe (NameType t) . parseMaybe parser $ t+  where parser :: Parser NameType+        parser =     (AKA <$ "aka")+                 <|> (BirthName <$ "birth")+                 <|> (Immigrant <$ "immigrant")+                 <|> (Maiden <$ "maiden")+                 <|> (Married <$ "married")++-- | Parse a 'PersonalNamePieces' structure.+parseNamePieces :: MultiMonad PersonalNamePieces+parseNamePieces = PersonalNamePieces+  <$> (fromMaybe [] <$> parseOptional (parseListTag (GDTag "NPFX")))+  <*> (fromMaybe [] <$> parseOptional (parseListTag (GDTag "GIVN")))+  <*> (fromMaybe [] <$> parseOptional (parseListTag (GDTag "NICK")))+  <*> (fromMaybe [] <$> parseOptional (parseListTag (GDTag "SPFX")))+  <*> (fromMaybe [] <$> parseOptional (parseListTag (GDTag "SURN")))+  <*> (fromMaybe [] <$> parseOptional (parseListTag (GDTag "NSFX")))+  <*> parseMulti parseNote+  <*> parseMulti parseSourceCitation++-- | Parse a 'PhoneticName'.+parsePhoneticName :: StructureParser PhoneticName+parsePhoneticName = parseNoLinkTag (GDTag "FONE")$ \(t, children) ->+  runMultiMonad children$ PhoneticName+    <$> (pure.getPersonalName.gdIgnoreEscapes$ t)+    <*> parseRequired (GDTag "TYPE") parsePhoneticType+    <*> parseNamePieces++-- | Parse a 'RomanizedName'.+parseRomanName :: StructureParser RomanizedName+parseRomanName = parseNoLinkTag (GDTag "FONE")$ \(t, children) ->+  runMultiMonad children$ RomanizedName+    <$> (pure.getPersonalName.gdIgnoreEscapes$ t)+    <*> parseRequired (GDTag "TYPE") parseRomanType+    <*> parseNamePieces++-- | Parse a 'Sex'.+parseSex :: StructureParser Sex+parseSex = parseNoLinkTag (GDTag "SEX")$ \(t, _) ->+  case trim . T.toUpper . gdIgnoreEscapes $ t of+    "M" -> return Male+    "F" -> return Female+    "U" -> return Undetermined+    _ -> throwError.FormatError$ "Unknown sex code " <> (T.show t)+  +-- | Parse a list of 'IndividualAttribute's.+parseIndividualAttribute :: MultiMonad [IndividualAttribute]+parseIndividualAttribute = do+    concat <$> mapM (parseMulti.attributeTag) [+      (GDTag "CAST", Caste),+      (GDTag "DSCR", PhysicalDescription),+      (GDTag "EDUC",  Education),+      (GDTag "IPNO", NationalID),+      (GDTag "NATI", NationalOrigin),+      (GDTag "NCHI", NChildren . read . T.unpack),+      (GDTag "NMR", NMarriages . read . T.unpack),+      (GDTag "OCCU", Occupation),+      (GDTag "PROP", Possessions),+      (GDTag "RELI", Religion),+      (GDTag "RESI", const ResidesAt),+      (GDTag "SSN", SocialSecurity),+      (GDTag "TITL", Title),+      (GDTag "FACT", Fact)]+  where+    attributeTag (tag, mkType) = parseNoLinkTag tag$ \(t, children) ->+      runMultiMonad children$ IndividualAttribute (mkType$ gdIgnoreEscapes t)+        <$> parseIndividualEventDetail++-- | Parse a list of 'IndividualEvent's+parseIndividualEvent :: MultiMonad [IndividualEvent]+parseIndividualEvent = do+    famc <- concat <$> mapM (parseMulti.famcTag)+      [(GDTag "BIRT", Birth), (GDTag "CHR", Christening)]+    adop <- parseMulti.parseNoLinkTag (GDTag "ADOP")$ \(_, children) ->+      runMultiMonad children$ IndividualEvent+        <$> (Adoption <$> parseOptional parseAdopFamilyRef)+        <*> parseIndividualEventDetail+    simple <- concat <$> mapM (parseMulti.eventTag) [+      (GDTag "DEAT", const Death),+      (GDTag "BURI", const Burial),+      (GDTag "CREM", const Cremation),+      (GDTag "BAPM", const Baptism),+      (GDTag "BARM", const BarMitzvah),+      (GDTag "BASM", const BasMitzvah),+      (GDTag "BLES", const Blessing),+      (GDTag "CHRA", const ChristeningAdult),+      (GDTag "CONF", const Confirmation),+      (GDTag "FCOM", const FirstCommunion),+      (GDTag "ORDN", const Ordination),+      (GDTag "NATU", const Naturalization),+      (GDTag "EMIG", const Emigration),+      (GDTag "IMMI", const Immigration),+      (GDTag "CENS", const IndvCensus),+      (GDTag "PROB", const Probate),+      (GDTag "WILL", const Will),+      (GDTag "GRAD", const Graduation),+      (GDTag "RETI", const Retirement),+      (GDTag "EVEN", IndividualEventType)]+    return$ famc ++ adop ++ simple+  where+    eventTag (tag, mkType) = parseNoLinkTag tag$ \(t, children) ->+      runMultiMonad children$ IndividualEvent (mkType$ gdIgnoreEscapes t)+        <$> parseIndividualEventDetail+    famcTag (tag, mkType) = parseNoLinkTag tag$ \(_, children) ->+      runMultiMonad children$ IndividualEvent+        <$> (mkType <$> parseOptional parseFamilyRef)+        <*> parseIndividualEventDetail+    parseFamilyRef = parseLinkTag (GDTag "FAMC") +    parseAdopFamilyRef = parseTagFull (GDTag "FAMC") nullrref$ \(lb, children) ->+      case lb of+        Right _ -> throwError.RequiredRef$ "Missing link in FAMC"+        Left f -> runMultiMonad children$+          AdoptionDetail f <$> parseOptional parseParent+    parseParent = parseNoLinkTag (GDTag "ADOP")$ \(t, _) ->+      case trim . T.toUpper . gdIgnoreEscapes $ t of+        "HUSB" -> return Husband+        "WIFE" -> return Wife+        "BOTH" -> return BothParents+        _ -> throwError.FormatError$ "Invalid parent " <> (T.show t)++-- | Parse an 'IndividualEventDetail'.+parseIndividualEventDetail :: MultiMonad IndividualEventDetail+parseIndividualEventDetail = IndividualEventDetail+  <$> parseEventDetail+  <*> parseOptional (parseWordTag (GDTag "AGE"))++-- | Parse a 'ChildToFamilyLink'.+parseChildToFamilyLink :: StructureParser ChildToFamilyLink+parseChildToFamilyLink = parseTagFull (GDTag "FAMC") nullrref$ \(lb, children) ->+  case lb of+    Right _ -> throwError.RequiredRef$ "Missing link in FAMC"+    Left f -> runMultiMonad children$ ChildToFamilyLink f+      <$> parseOptional parsePedigree+      <*> parseOptional parseChildLinkStatus+      <*> parseMulti parseNote++-- | Parse a 'Pedigree'.+parsePedigree :: StructureParser Pedigree+parsePedigree = parseNoLinkTag (GDTag "PEDI")$ \(t, _) ->+  case trim . T.toUpper . gdIgnoreEscapes$ t of+    "ADOPTED" -> return Adopted+    "BIRTH" -> return ByBirth+    "FOSTER" -> return Foster+    "SEALING" -> return Sealing+    _ -> throwError.FormatError$ "Invalid pedigree code " <> (T.show t)++-- | Parse a 'ChildLinkStatus'.+parseChildLinkStatus :: StructureParser ChildLinkStatus+parseChildLinkStatus = parseNoLinkTag (GDTag "STAT")$ \(t, _) ->+  case trim . T.toUpper . gdIgnoreEscapes$ t of+    "CHALLENGED" -> return Challenged+    "DISPROVEN" -> return Disproved+    "PROVEN" -> return Proven+    _ -> throwError.FormatError$ "Invalid child link status " <> (T.show t)++-- | Parse a 'SpouseToFamilyLink'.+parseSpouseToFamilyLink :: StructureParser SpouseToFamilyLink+parseSpouseToFamilyLink = parseTagFull (GDTag "FAMS") nullrref$+  \(lb, children) ->+    case lb of+      Right _ -> throwError.RequiredRef$ "Missing link in FAMS"+      Left f -> runMultiMonad children$ SpouseToFamilyLink f+        <$> parseMulti parseNote++-- | Parse an 'Association'.+parseAssociation :: StructureParser Association+parseAssociation = parseTagFull (GDTag "ASSO") nullrref$ \(lb, children) ->+  case lb of+    Right _ -> throwError.RequiredRef$ "Missing link in ASSO"+    Left i -> runMultiMonad children$ Association i+      <$> parseRequired (GDTag "RELA") (parseTextTag (GDTag "RELA"))+      <*> parseMulti parseSourceCitation+      <*> parseMulti parseNote++-- | Parse a 'SourceRecordedEvent'.+parseSourceRecordedEvent :: StructureParser SourceRecordedEvent+parseSourceRecordedEvent = parseNoLinkTag (GDTag "EVEN")$+  \(recorded, children) ->+   runMultiMonad children$ SourceRecordedEvent+     <$> (pure . catMaybes . fmap getEventType+       . T.splitOn "," . gdIgnoreEscapes$ recorded)+     <*> parseOptional fullParseDatePeriod+     <*> parseOptional (parseListTag (GDTag "PLAC"))+     where+      fullParseDatePeriod = parseNoLinkTag (GDTag "DATE")$ \(date, _) ->+        case parseDatePeriod date of+          Just v -> return v+          Nothing -> throwError.FormatError$+            "Badly formatted date period: " <> (T.show date)++-- | Parse a 'RepositoryCitation'.+parseRepositoryCitation :: StructureParser RepositoryCitation+parseRepositoryCitation = parseTagFull (GDTag "REPO") nullrref$+  \(lb, children) ->+    let repo = case lb of+                 Left v -> Just v+                 Right _ -> Nothing+    in runMultiMonad children$ RepositoryCitation repo+      <$> parseMulti parseNote+      <*> parseOptional parseCallNumber++-- | Parse a 'CallNumber'.+parseCallNumber :: StructureParser CallNumber+parseCallNumber = parseNoLinkTag (GDTag "CALN")$ \(n, children) ->+  runMultiMonad children$ CallNumber (gdIgnoreEscapes n)+    <$> parseOptional (parseMultimediaType (GDTag "MEDI"))++-- | Parse a 'SourceCitation'.+parseSourceCitation :: StructureParser SourceCitation+parseSourceCitation = parseTagFull (GDTag "SOUR") nullrref$+  \(lb, children) ->+    case lb of+      Left source ->+        runMultiMonad children$ SourceCitation (Right source)+          <$> parseOptional (parseTextTag (GDTag "PAGE"))+          <*> parseMulti parseMultimedia+          <*> parseMulti parseNote+          <*> parseOptional parseQuality+      Right description ->+        runMultiMonad children$ SourceCitation+          <$> (Left . SourceDescription (gdIgnoreEscapes description)+            <$> parseMulti (parseTextTag (GDTag "TEXT")))+          <*> pure Nothing+          <*> parseMulti parseMultimedia+          <*> parseMulti parseNote+          <*> parseOptional parseQuality++-- | Parse a 'GedcomFormat'.+parseGedcomFormat :: StructureParser GedcomFormat+parseGedcomFormat = parseNoLinkTag (GDTag "GEDC")$ \(_, children) ->+  runMultiMonad children$ GedcomFormat+    <$> parseRequired (GDTag "VERS") parseVersion+    <*> parseRequired (GDTag "FORM") parseGedcomForm++-- | Parse a 'GedcomForm'.+parseGedcomForm :: StructureParser GedcomForm+parseGedcomForm = parseNoLinkTag (GDTag "FORM")$ \(t, _) ->+  return$ if (T.toUpper . gdIgnoreEscapes$ t) == "LINEAGE-LINKED"+    then GedcomLineageLinked+    else GedcomUnsupported (gdIgnoreEscapes t)++-- | Parse a 'Charset'.+parseCharset :: StructureParser Charset+parseCharset = parseNoLinkTag (GDTag "CHAR")$ \(cs, children) ->+  runMultiMonad children$ Charset (gdIgnoreEscapes cs)+    <$> parseOptional parseVersion++-- | Parse a 'ChangeDate'.+parseChangeDate :: StructureParser ChangeDate+parseChangeDate = parseNoLinkTag (GDTag "CHAN")$ \(_, children) ->+  runMultiMonad children$ ChangeDate+    <$> parseRequired (GDTag "DATE") parseExactDateTime+    <*> parseOptional parseNote++-- | Parse 'ContactDetails'.+parseContactDetails :: MultiMonad ContactDetails+parseContactDetails = ContactDetails+  <$> parseMulti (parseTextTag (GDTag "PHON"))+  <*> parseMulti (parseTextTag (GDTag "EMAIL"))+  <*> parseMulti (parseTextTag (GDTag "FAX"))+  <*> parseMulti (parseTextTag (GDTag "WWW"))++-- | Parse an 'Address'.+parseAddress :: ContactDetails -> StructureParser Address+parseAddress contacts = parseNoLinkTag (GDTag "ADDR")$ \(addr, children) ->+  runMultiMonad children$ Address (gdIgnoreEscapes addr)+    <$> parseOptional (parseTextTag (GDTag "CITY"))+    <*> parseOptional (parseTextTag (GDTag "STAE"))+    <*> parseOptional (parseTextTag (GDTag "POS"))+    <*> parseOptional (parseTextTag (GDTag "CTRY"))+    <*> pure contacts++-- | Parse a 'DateValue'.+parseDateValue :: StructureParser DateValue+parseDateValue = parseNoLinkTag (GDTag "DATE")$ \(t, _) ->+  let date = (DateApproxV <$> parseDateApprox t)+         <|> (DateRangeV <$> parseDateRange t)+         <|> (DatePeriodV <$> parseDatePeriod t)+         <|> (parseDatePhrase t)+         <|> (DateV <$> parseDate t)+  in case date of+    Just x -> return x+    Nothing -> throwError.FormatError$ "Invalid date format " <> (T.show t)++-- | Decode a calendar escape sequence to a 'Calendar'.+decodeCalendarEscape :: Maybe GDEscape -> Calendar+decodeCalendarEscape Nothing = Gregorian+decodeCalendarEscape (Just (GDEscape c)) = case T.toUpper c of+                                             "DGREGORIAN" -> Gregorian+                                             "DJULIAN" -> Julian+                                             "DHEBREW" -> Hebrew+                                             "DFRENCH" -> French+                                             "DROMAN" -> Julian+                                             "DUNKNOWN" -> Gregorian+                                             _ -> Gregorian++-- | Prepare text for parsing a 'DateValue'.+prepareDateText :: [(Maybe GDEscape, T.Text)] -> [(Maybe GDEscape, T.Text)]+prepareDateText = gdFilterEscapes [+                    GDEscape "DGREGORIAN",+                    GDEscape "DJULIAN",+                    GDEscape "DHEBREW",+                    GDEscape "DFRENCH",+                    GDEscape "DROMAN",+                    GDEscape "DUNKNOWN"]++-- | Attempt to extract a 'DatePeriod' from a string with escape sequences.+parseDatePeriod :: [(Maybe GDEscape, T.Text)] -> Maybe DatePeriod+parseDatePeriod t = case prepareDateText t of+  ((mCalendarEscape1, t1'):rest) ->+    let+      calendar1 = decodeCalendarEscape mCalendarEscape1+      t1 = trim$ T.toUpper t1'+      from = trim <$> T.stripPrefix "FROM" t1+      to = trim <$> T.stripPrefix "TO" t1+    in case to of+      Just r -> DateTo <$> getDate calendar1 r+      Nothing -> case from of+        Nothing -> Nothing+        Just r ->+          let topcs = T.splitOn "TO"$ r+          in case topcs of+            [mfdate, mto] -> DateFrom+                <$> getDate calendar1 (trim mfdate)+                <*> (pure$ getDate calendar1 (trim mto))+            [mfdate] -> case rest of+                [] -> DateFrom+                  <$> getDate calendar1 (trim mfdate) <*> (pure Nothing)+                ((mCalendarEscape2, t2'):_) ->+                  let+                    calendar2 = decodeCalendarEscape mCalendarEscape2+                    t2 = trim$ T.toUpper t2'+                    to2 = trim <$> T.stripPrefix "TO" t2+                  in case to2 of+                    Nothing -> Nothing+                    Just r2 -> DateFrom+                      <$> getDate calendar1 (trim mfdate)+                      <*> (pure$ getDate calendar2 (trim r2))+            _ -> Nothing+  _ -> Nothing++-- | Attempt to extract a 'DateRange' from a string with escape sequences.+parseDateRange :: [(Maybe GDEscape, T.Text)] -> Maybe DateRange+parseDateRange t = case prepareDateText t of+  ((mCalendarEscape1, t1):rest) ->+    let+      calendar1 = decodeCalendarEscape mCalendarEscape1+      (pref, date1) = second trim . T.splitAt 3 . T.toUpper . trim $ t1+    in case pref of+      "BEF" -> DateBefore <$> getDate calendar1 date1+      "AFT" -> DateAfter <$> getDate calendar1 date1+      "BET" -> case T.splitOn "AND" date1 of+        [d1, date2'] -> DateBetween+          <$> getDate calendar1 d1+          <*> getDate calendar1 (trim date2')+        [d1] -> case rest of+          [] -> Nothing+          ((mCalendarEscape2, t2):_) ->+            let calendar2 = decodeCalendarEscape mCalendarEscape2+            in DateBetween+              <$> getDate calendar1 d1+              <*> getDate calendar2 (trim t2)+        _ -> Nothing+      _ -> Nothing+  _ -> Nothing++-- | Attempt to extract a 'DateApprox' from a string with escape sequences.+parseDateApprox :: [(Maybe GDEscape, T.Text)] -> Maybe DateApprox+parseDateApprox t = case prepareDateText t of+  ((mCalendarEscape1, t1):_) ->+    let+      calendar1 = decodeCalendarEscape mCalendarEscape1+      (pref, date) = second trim . T.splitAt 3 . T.toUpper . trim $ t1+      cons = case pref of+        "ABT" -> Just DateAbout+        "CAL" -> Just DateCalculated+        "EST" -> Just DateEstimated+        _ -> Nothing+    in cons <*> getDate calendar1 date+  _ -> Nothing++-- | Attempt to extract a 'DatePhrase' from a string with escape sequences.+parseDatePhrase :: [(Maybe GDEscape, T.Text)] -> Maybe DateValue+parseDatePhrase t = case prepareDateText t of+  ((mCalendarEscape1, t1):_) ->+    let+      calendar1 = decodeCalendarEscape mCalendarEscape1+      int = trim <$> T.stripPrefix "INT" t1+      opp = trim <$> T.stripPrefix "(" t1+    in case int of+      Nothing -> case opp of+        Nothing -> Nothing+        Just phrase -> Just$+          DatePhrase Nothing (trim . T.dropEnd 1$ phrase)+      Just rest -> case trim <$> T.splitOn "(" rest of+        [date, phrase] -> Just$ +          DatePhrase (getDate calendar1 date) (trim . T.dropEnd 1$ phrase)+        _ -> Nothing+  _ -> Nothing++-- | Attempt to extract a 'Date' from a string with escape sequences.+parseDate :: [(Maybe GDEscape, T.Text)] -> Maybe Date+parseDate t = case prepareDateText t of+    ((mCalendarEscape, cal):rest) ->+      let calendar = decodeCalendarEscape mCalendarEscape+      in getDate calendar (cal <> gdIgnoreEscapes rest)+    _ -> Nothing++-- | Parse a 'Date' from a given string assuming the given 'Calendar'.+getDate :: Calendar -> T.Text -> Maybe Date+getDate calendar = parseMaybe parser+  where+    yearParser = case calendar of+      Gregorian -> yearGreg+      _ -> read <$> count' 1 4 digitChar+    parseYear = (\y bc -> Year$ if bc then (0 - y) else y)+      <$> yearParser <*> ((True <$ "B.C.") <|> pure False)+    parser :: Parser Date+    parser =+      (try$ Date calendar+          <$> (Just . read <$> count' 1 2 digitChar)+          <*> (gdDelim >> (Just <$> parseMonth))+          <*> (gdDelim >> parseYear))+      <|> (try$ Date calendar Nothing+          <$> (gdDelim >> (Just <$> parseMonth))+          <*> (gdDelim >> parseYear))+      <|> (Date calendar Nothing Nothing+          <$> (gdDelim >> parseYear))+    parseMonth = case calendar of+                   Gregorian -> month+                   Julian -> month+                   Hebrew -> monthHeb+                   French -> monthFr+      +-- | Parse an exact date.+parseExactDate :: StructureParser UTCTime+parseExactDate = parseNoLinkTag (GDTag "DATE")$ \(date, _) ->+  case parseMaybe dateExact (gdIgnoreEscapes date) of+    Nothing -> throwError.FormatError$ "Bad date \"" <> (T.show date) <> "\""+    Just (d, m, y) ->+      return$ UTCTime+        (fromGregorian (fromIntegral y) (fromIntegral m) d)+        (secondsToDiffTime 0)++-- | Parse an exact date and time.+parseExactDateTime :: StructureParser UTCTime+parseExactDateTime = parseNoLinkTag (GDTag "DATE")$ \(date, children) -> do+  mtime <- runMultiMonad children$ parseOptional (parseTextTag (GDTag "TIME"))++  dt <- case mtime of+    Nothing -> return$ secondsToDiffTime 0+    Just t -> case parseMaybe timeValue t of+      Nothing -> throwError.FormatError$ "Bad time \"" <> (T.show t) <> "\""+      Just Nothing -> return$ secondsToDiffTime 0+      Just (Just time) -> return$ timeToPicos time++  case parseMaybe dateExact (gdIgnoreEscapes date) of+    Nothing -> throwError.FormatError$ "Bad date \"" <> (T.show date) <> "\""+    Just (d, m, y) -> return$ UTCTime+      (fromGregorian (fromIntegral y) (fromIntegral m) d) dt++-- | Parse a 'Multimedia' record.+parseMultimediaRecord :: StructureParser (GDRef Multimedia)+parseMultimediaRecord = parseMultimediaRaw (GDTag "TYPE")++-- | Parse a 'Multimedia' link.+parseMultimedia :: StructureParser (GDRef Multimedia)+parseMultimedia = parseMultimediaRaw (GDTag "MEDI")++-- | Actual parser for 'Multimedia' values.+parseMultimediaRaw :: GDTag -> StructureParser (GDRef Multimedia)+parseMultimediaRaw typeTag = parseTag (GDTag "OBJE")$ \(_, children) ->+  runMultiMonad children$ Multimedia+    <$> ((parseOptional (parseMultimediaFormat typeTag)) >>=+      (parseMulti.(parseMultimediaFile typeTag)))+    <*> parseOptional (parseTextTag (GDTag "TITL"))+    <*> parseMulti parseUserReference+    <*> parseOptional parseRIN+    <*> parseMulti parseNote+    <*> parseMulti parseSourceCitation+    <*> parseOptional parseChangeDate++-- | Parse a 'MultimediaFile'.+parseMultimediaFile ::+  GDTag -> Maybe MultimediaFormat ->+  StructureParser MultimediaFile+parseMultimediaFile typeTag mf = parseNoLinkTag (GDTag "FILE")$+  \(name, children) -> do+    (mc, title) <- runMultiMonad children$ (,)+      <$> parseOptional (parseMultimediaFormat typeTag)+      <*> parseOptional (parseTextTag (GDTag "TITL"))+    case mc <|> mf of+      Nothing -> throwError.TagError$ "Missing FORM tag for file format"+      Just c -> return$ MultimediaFile (gdIgnoreEscapes name) c title++-- | Parse a 'MultimediaFormat'.+parseMultimediaFormat :: GDTag -> StructureParser MultimediaFormat+parseMultimediaFormat tag = parseNoLinkTag (GDTag "FORM")$ \(v', children) ->+  let v = gdIgnoreEscapes v'+  in runMultiMonad children$ MultimediaFormat+    (fromMaybe (MF_OTHER v)$ parseMaybe parser v)+    <$> parseOptional (parseMultimediaType tag)++  where+    parser :: Parser MultimediaFileFormat+    parser =     (MF_BMP <$ "bmp")+             <|> (MF_GIF <$ "gif")+             <|> (MF_JPG <$ "jpg")+             <|> (MF_OLE <$ "ole")+             <|> (MF_PCX <$ "pcx")+             <|> (MF_TIF <$ "tif")+             <|> (MF_WAV <$ "wav")++-- | Parse a 'MultimediaType'.+parseMultimediaType :: GDTag -> StructureParser MultimediaType+parseMultimediaType tag = parseNoLinkTag tag$ \(v', _) ->+  let v = gdIgnoreEscapes v'+  in return.fromMaybe (MT_OTHER v)$ parseMaybe parser v+  where+    parser :: Parser MultimediaType+    parser =     (MT_AUDIO <$ "audio")+             <|> (MT_BOOK <$ "book")+             <|> (MT_CARD <$ "card")+             <|> (MT_ELECTRONIC <$ "electronic")+             <|> (MT_FICHE <$ "fiche")+             <|> (MT_FILM <$ "film")+             <|> (MT_MAGAZINE <$ "magazine")+             <|> (MT_MANUSCRIPT <$ "manuscript")+             <|> (MT_MAP <$ "map")+             <|> (MT_NEWSPAPER <$ "newspaper")+             <|> (MT_PHOTO <$ "photo")+             <|> (MT_TOMBSTONE <$ "tombstone")+             <|> (MT_VIDEO <$ "video")++-- | Parse a 'FamilyEventType'.+getFamilyEventType :: T.Text -> Maybe FamilyEventType+getFamilyEventType = parseMaybe parser+  where+    parser :: Parser FamilyEventType+    parser =     (Annuled <$ "ANUL")+             <|> (FamCensus <$ "CENS")+             <|> (Divorce <$ "DIV")+             <|> (DivorceFiled <$ "DIVF")+             <|> (Engagement <$ "ENGA")+             <|> (MarriageBann <$ "MARB")+             <|> (MarriageContract <$ "MARC")+             <|> (Marriage <$ "MARR")+             <|> (MarriageLicense <$ "MARL")+             <|> (MarriageSettlement <$ "MARS")+             <|> (Residence <$ "RESI")+             <|> (FamilyEventType . T.pack <$>+               ("EVEN" *> gdDelim *> many anyChar))++-- | Parse an 'IndividualEventType'.+getIndividualEventType :: T.Text -> Maybe IndividualEventType+getIndividualEventType = parseMaybe parser+  where+    parser :: Parser IndividualEventType+    parser =     (Birth Nothing <$ ("BIRTH"+                    *> optional (gdDelim >> "Y")))+             <|> (Christening Nothing <$ ("CHR"+                    *> optional (gdDelim >> "Y")))+             <|> (Death <$ ("DEAT"+                    *> optional (gdDelim >> "Y")))+             <|> (Burial <$ "BURI")+             <|> (Cremation <$ "CREM")+             <|> (Adoption Nothing <$ "ADOP")+             <|> (Baptism <$ "BAPM")+             <|> (BarMitzvah <$ "BARM")+             <|> (BasMitzvah <$ "BASM")+             <|> (Blessing <$ "BLES")+             <|> (ChristeningAdult <$ "CHRA")+             <|> (Confirmation <$ "CONF")+             <|> (FirstCommunion <$ "FCOM")+             <|> (Ordination <$ "ORDN")+             <|> (Naturalization <$ "NATU")+             <|> (Emigration <$ "EMIG")+             <|> (Immigration <$ "IMMI")+             <|> (IndvCensus <$ "CENS")+             <|> (Probate <$ "PROB")+             <|> (Will <$ "WILL")+             <|> (Graduation <$ "GRAD")+             <|> (Retirement <$ "RETI")+             <|> (IndividualEventType . T.pack <$>+               ("EVEN" *> gdDelim *> many anyChar))++-- | Parse an 'EventType'.+getEventType :: T.Text -> Maybe EventType+getEventType et =+  let+    t = trim$ T.toUpper et+    fam = getFamilyEventType et+    indv = getIndividualEventType et+  in+    if t == "CENS" then Just Census+    else if (T.take 4 t) == "EVEN" then+      Just . EventType . trim . T.drop 4$ et+    else fmap FamilyEventTypeV fam <|> fmap IndividualEventTypeV indv++-- | Parse a place form structure.+parsePlaceForm :: StructureParser [T.Text]+parsePlaceForm = parseNoLinkTag (GDTag "PLAC")$ \(_, children) ->+  runMultiMonad children$ fromMaybe [].(fmap$ T.splitOn ",") <$>+    parseOptional (parseTextTag (GDTag "FORM"))++-- | Parse a 'UserReference'.+parseUserReference :: StructureParser UserReference+parseUserReference = parseNoLinkTag (GDTag "REFN")$ \(i, children) ->+  runMultiMonad children$ UserReference (gdIgnoreEscapes i)+    <$> parseOptional (parseTextTag (GDTag "TYPE"))++-- | Parse a version structure.+parseVersion :: StructureParser T.Text+parseVersion = parseTextTag (GDTag "VERS")++-- | Parse a NAME tag.+parseName :: StructureParser T.Text+parseName = parseTextTag (GDTag "NAME")++-- | Parse a copyright tag.+parseCopyright :: StructureParser T.Text+parseCopyright = parseTextTag (GDTag "COPR")++-- | Parse a file name.+parseFile :: StructureParser FilePath+parseFile = (fmap.fmap.fmap) T.unpack$ parseTextTag (GDTag "FILE")++-- | Parse an 'AFN'.+parseAFN :: StructureParser AFN+parseAFN = (fmap.fmap.fmap) AFN$ parseTextTag (GDTag "AFN")++-- | Parse a 'RFN'.+parseRFN :: StructureParser RFN+parseRFN = (fmap.fmap.fmap) RFN$ parseTextTag (GDTag "RFN")++-- | Parse a 'RIN'.+parseRIN :: StructureParser RIN+parseRIN = (fmap.fmap.fmap) RIN$ parseTextTag (GDTag "RIN")++-- | Parse a 'Language'.+parseLanguage :: StructureParser Language+parseLanguage = (fmap.fmap.fmap) (Language) $ parseTextTag (GDTag "LANG")++-- | Parse a 'QualityAssessment'.+parseQuality :: StructureParser QualityAssessment+parseQuality = (fmap.fmap.fmap) QualityAssessment $ parseWordTag (GDTag "QUAY")++-- | Parse a boolean value.+parseBoolTag :: GDTag -> StructureParser Bool+parseBoolTag tag = parseNoLinkTag tag$ \(v, _) ->+  case parseMaybe ynParser (gdIgnoreEscapes v) of+    Nothing -> throwError.FormatError$ "Expected boolean, saw " <> (T.show v)+    Just yn -> return yn+  where+    ynParser :: Parser Bool+    ynParser = (True <$ "yes") <|> (False <$ "no")++-- | Parse a Word value.+parseWordTag :: GDTag -> StructureParser Word+parseWordTag tag = parseNoLinkTag tag$ \(v, _) ->+  case parseMaybe parser (gdIgnoreEscapes v) of+    Nothing -> throwError.FormatError$ "Expected number, saw " <> (T.show v)+    Just n -> return . read $ n+  where+    parser :: Parser String+    parser = many digitChar++-- | Extract the text from a tag.+parseTextTag :: GDTag -> StructureParser T.Text+parseTextTag tag = parseNoLinkTag tag (return.gdIgnoreEscapes.fst)++-- | Extract a list of comma separated values from a tag.+parseListTag :: GDTag -> StructureParser [T.Text]+parseListTag tag =+  parseNoLinkTag tag (return . split . trim . gdIgnoreEscapes . fst)+  where+    split "" = []+    split s = T.splitOn "," s++-- | Handler for tags that cannot contain cross references.+type NoLinkHandler a =+  ([(Maybe GDEscape, T.Text)], [GDTree]) -> StructureMonad a++-- | Handler for general tags.+type TagHandler b a =+  (Either (GDRef b) [(Maybe GDEscape, T.Text)], [GDTree])+  -> StructureMonad a++-- | A function that adds references to the cross reference table.+type RegisterRef a = GDTag -> GDXRefID -> a -> StructureMonad ()++-- | Don't add any references.+nullrref :: Typeable a => RegisterRef a+nullrref _ _ _ = return ()++-- | Add direct references only.+defrref :: Typeable a => RegisterRef (GDRef a)+defrref _ thisID (GDStructure a) = addReference thisID a+defrref tag _ _ = throwError.UnexpectedRef$+  "Referenced structure references another structure " <> (T.show tag)++-- | Parse a tag which is either a GEDCOM structure, or a reference to the+-- expected GEDCOM structure.+parseTag :: Typeable a+  => GDTag            -- ^ The tag to parse.+  -> NoLinkHandler a  -- ^ A handler for the tag+  -> StructureParser (GDRef a)+parseTag tag handler = parseTagFull tag defrref$ \(lb, children) ->+  case lb of+    Left ref -> return ref+    Right text -> GDStructure <$> handler (text, children)++-- | Parse a tag which cannot contain a cross reference (i.e. the tag must+-- contain the structure itself, not a reference to another structure).+parseNoLinkTag :: Typeable a+  => GDTag            -- ^ The tag to parse.+  -> NoLinkHandler a  -- ^ A handler for the tag.+  -> StructureParser a+parseNoLinkTag tag handler = parseTagFull tag nullrref$ \(lb, children) ->+  case lb of+    Left _ -> throwError.UnexpectedRef$+      "Cannot follow cross references on " <> (T.show tag)+    Right text -> handler (text, children)++-- | Parse a tag which must contain a cross reference to another structure, not+-- the structure itself.+parseLinkTag :: Typeable a => GDTag -> StructureParser (GDRef a)+parseLinkTag tag = parseTagFull tag nullrref$ \(lb, _) ->+  case lb of+    Left ref -> return ref+    Right _ -> throwError.RequiredRef$+      "Expected cross reference was missing in " <> (T.show tag)++-- | The most general tag parsing function.+parseTagFull :: Typeable a+  => GDTag             -- ^ The tag to parse.+  -> RegisterRef a     -- ^ How to register cross references.+  -> TagHandler b a    -- ^ How to convert the tag into a GEDCOM structure.+  -> StructureParser a+parseTagFull tag rref handler t@(GDTree (GDLine _ mthisID tag' v) children) =+  if tag /= tag' then return$ Left t else do+    r <- case v of+      Nothing -> Right <$> (handler.(first Right)$ parseCont mempty children)+      Just (GDXRefIDV xref) -> do+        Right <$> (handler (Left (GDXRef xref), children))+      Just (GDLineItemV l1) ->+        Right <$> (handler.(first Right)$ parseCont l1 children)+    case (mthisID, r) of+      (Just thisID, Right rv) -> rref tag thisID rv+      _ -> return ()+    return r++-- | Handle CONT and CONC tags.+parseCont ::+     GDLineItem -- ^ The value of the first line+  -> [GDTree]   -- ^ The sub tree+  -> ([(Maybe GDEscape, T.Text)], [GDTree])  -- ^ The concatenation of the values of all the CONT and CONC tags, and the remaining tags.+parseCont l1 children =+    bimap assemble (fmap snd).span (isJust.fst)$+      zipWith (\l r -> (cont l <|> conc l, r)) children children+  where+    assemble = gdLineData . mconcat . (l1:) . catMaybes . fmap fst+    cont (GDTree (GDLine _ _ (GDTag "CONT") (Just (GDLineItemV l))) _) =+      Just$ GDLineItem [(Nothing, "\r\n")] <> l+    cont _ = Nothing+    conc (GDTree (GDLine _ _ (GDTag "CONC") (Just (GDLineItemV l))) _) =+      Just$ gdTrimLineItem l+    conc _ = Nothing+
− src/Data/Gedcom/LineParser.hs
@@ -1,147 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TupleSections #-}--{-|-Module: Data.Gedcom.LineParser-Description: Low-level GEDCOM parser-Copyright: (c) Callum Lowcay, 2017-License: BSD3-Maintainer: cwslowcay@gmail.com-Stability: experimental-Portability: GHC--This module parses a Text string into a GEDCOM syntax tree.---}-module Data.Gedcom.LineParser (-  gdRoot, gdDelim-) where--import Control.Monad-import Data.Char-import Data.Gedcom.Common-import Data.Gedcom.Internal.Common-import Data.Maybe-import Data.Monoid-import qualified Data.Text.All as T-import Text.Megaparsec---- | Parse any_char.-gdAnyChar :: Parser String-gdAnyChar = (fmap (:[]) gdNonAt) <|> string "@@"---- | Parse non_at.-gdNonAt :: Parser Char-gdNonAt = satisfy (\c -> (not.isControl) c && c /= '@' && c /= '\x7F')---- | Parse alphanum.-gdAlphaNum :: Parser Char-gdAlphaNum = alphaNumChar <|> char '_'---- | Parse delim.-gdDelim :: Parser (Maybe Char)-gdDelim = optional$ char '\x20'---- | Parse escape.-gdEscape :: Parser GDEscape-gdEscape = GDEscape . T.pack <$>-  (string "@#" *> gdEscapeText <* char '@' <* (optional$ char ' '))---- | Parse escape_text.-gdEscapeText :: Parser String-gdEscapeText = concat <$> many gdAnyChar---- | Parse level.-gdLevel :: Parser GDLevel-gdLevel = GDLevel . read <$> count' 1 2 digitChar <* gdDelim---- | Parse line_item.-gdLineItem :: Parser GDLineItem-gdLineItem = fmap GDLineItem . some$-  (,) <$> optional gdEscape <*> (T.pack . concat <$> some gdAnyChar)---- | Parse pointer.-gdPointer :: Parser GDXRefID-gdPointer = char '@' *> plabel <* char '@'-  where plabel = fmap (GDXRefID . T.pack)$-                  (:) <$> gdAlphaNum <*> (many gdNonAt)---- | Parse line_value-gdLineValue :: Parser GDLineValue-gdLineValue = eitherP gdPointer gdLineItem <&> \x -> case x of-  Left v -> GDXRefIDV v-  Right v -> GDLineItemV v---- | Parse optional_line_value.-gdOptionalLineValue :: Parser GDLineValue-gdOptionalLineValue = gdDelim *> gdLineValue---- | Parse optional_xref_ID.-gdOptionalXRefID :: Parser (Maybe GDXRefID)-gdOptionalXRefID = gdXRefID <* gdDelim---- | Parse tag.-gdTag :: Parser GDTag-gdTag = GDTag . T.toUpper . T.pack <$> many gdAlphaNum---- | parse terminator.-gdTerminator :: Parser String-gdTerminator = string "\n" <|> string "\r" <|> string "\r\n" <|> string "\n\r"---- | Parse xref_ID.-gdXRefID :: Parser (Maybe GDXRefID)-gdXRefID = optional $ fmap (\(GDXRefID t) -> GDXRefID t) gdPointer---- | Parse gedcom_line.-gdLine :: Parser GDLine-gdLine = GDLine <$>-  gdLevel <*>-  gdOptionalXRefID <*>-  gdTag <*>-  (optional gdOptionalLineValue) <* gdTerminator---- | Convert local ids to global ids.-gdExpandID ::-     GDXRefID -- ^ The parent structure's ID-  -> GDXRefID -- ^ The local ID.-  -> GDXRefID -- ^ A global ID.-gdExpandID (GDXRefID pid) s@(GDXRefID sub) =-  case T.uncons sub of-    Nothing -> s-    Just ('!', _) -> GDXRefID$ pid <> sub-    _ -> s---- | Convert local ids to global ids.-gdExpandPointer ::-     GDXRefID     -- ^ The parent structure's ID.-  -> GDLineValue  -- ^ The line to update.-  -> GDLineValue  -- ^ An updated line where local ID's have been made global.-gdExpandPointer pid v = case v of-  GDLineItemV _ -> v-  GDXRefIDV p -> GDXRefIDV$ gdExpandID pid p---- | Parse a line at a fixed level-gdLineLevel ::-     GDXRefID -- ^ The parent ID -  -> GDLevel  -- ^ The level to parse the line at-  -> Parser GDLine-gdLineLevel pid n = do-  (GDLine n' xrid tag v) <- gdLine-  when (n' /= n)$ fail$ "Saw a " ++ (show tag) ++-    " tag at level " ++ (show n') ++-    " but expected level was " ++ (show n)-  return$ GDLine n' (fmap (gdExpandID pid) xrid) tag (fmap (gdExpandPointer pid) v)---- | Parse a GEDCOM subtree-gdTree ::-     GDXRefID -- ^ The parent ID-  -> GDLevel  -- ^ The level where the subtree is rooted-  -> Parser GDTree-gdTree pid n = try$ do-  line@(GDLine _ pid' _ _) <- gdLineLevel pid n-  GDTree line <$> many (gdTree (fromMaybe pid pid') (n + 1))---- | Parse the raw GEDCOM syntax tree.-gdRoot :: Parser GDRoot-gdRoot = GDRoot <$> (many$ gdTree (GDXRefID "") 0)-
− src/Data/Gedcom/ParseMonads.hs
@@ -1,120 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE OverloadedStrings #-}--{-|-Module: Data.Gedcom.ParseMonads-Description: Monads for parsing GEDCOM records-Copyright: (c) Callum Lowcay, 2017-License: BSD3-Maintainer: cwslowcay@gmail.com-Stability: experimental-Portability: GHC--This module contains monads and utility functions for extracting GEDCOM records-from the raw syntax tree.---}-module Data.Gedcom.ParseMonads (-  StructureParser,-  MultiMonad,-  runMultiMonad,-  parseMulti,-  parseOptional,-  parseRequired,-  StructureMonad,-  addReference,-  runStructure-) where--import Control.Monad-import Control.Monad.Except-import Control.Monad.State-import Data.Dynamic-import Data.Either-import Data.Foldable-import Data.Gedcom.Common-import Data.Maybe-import Data.Monoid-import qualified Data.Map as M-import qualified Data.Text.All as T---- | A parser that extracts a GEDCOM structure from a GEDCOM subtree.-type StructureParser a =-     GDTree                               -- ^ The  subtree to parse.-  -> StructureMonad (Either GDTree a)     -- ^ Either parsed structure, or the subtree itself if the subtree doesn't contain the expected GEDCOM structure.---- | A Monad for parsing GEDCOM structures out of a list of GEDCOM subtrees.-newtype MultiMonad a =-  MultiMonad (ExceptT GDError (StateT [GDTree] StructureMonad) a)-  deriving (Monad, Functor, Applicative, MonadError GDError)---- | Run a 'MultiMonad' into a 'StructureMonad'.-runMultiMonad ::-     [GDTree]         -- ^ The subtrees to parse the structure from.-  -> MultiMonad a     -- ^ The MultiMonad that does the parsing.-  -> StructureMonad a-runMultiMonad children (MultiMonad m) =-  ((flip evalStateT) children.runExceptT$ m) >>= rethrowError-  where rethrowError x = case x of-                           Left e -> throwError e-                           Right v -> return v---- | Parse multiple instances of a structure-parseMulti :: StructureParser a -> MultiMonad [a]-parseMulti p = MultiMonad$ do-  ls <- lift$ get-  (others, vs) <- lift$ lift$ partitionEithers <$> p `traverse` ls-  lift$ put others-  return vs---- | Parse an optional instance of a structure-parseOptional :: StructureParser a -> MultiMonad (Maybe a)-parseOptional p = MultiMonad$ do-  ls <- lift$ get-  (mr, leftover) <--    lift$ lift$ foldrM (\v (r, rest) ->-      if isJust r then return (r, v:rest)-      else pick v rest.toMaybe <$> p v) (Nothing, []) ls-  lift$ put leftover-  return mr-  where-    toMaybe (Left _) = Nothing-    toMaybe (Right v) = Just v-    pick v rest Nothing = (Nothing, v:rest)-    pick _ rest x = (x, rest)---- | Parse a required instance of a structure-parseRequired ::-     GDTag       -- ^ The tag that identifies the required structure.-  -> StructureParser a-  -> MultiMonad a-parseRequired tag p = do-  r <- parseOptional p-  case r of-    Just v -> return v-    Nothing -> throwError.TagError$-      "Could not find required " <> (T.show tag) <> " tag"---- | A monad for parsing an instance of a GEDCOM structure from a GEDCOM--- subtree.-newtype StructureMonad a =-  StructureMonad (ExceptT GDError (State (M.Map GDXRefID Dynamic)) a)-  deriving (Monad, Functor, Applicative, MonadError GDError)---- | Add a reference to the cross reference table.-addReference :: Typeable a-  => GDXRefID            -- ^ The cross reference to add.-  -> a                   -- ^ The value the reference will resolve to.-  -> StructureMonad ()-addReference thisID value = StructureMonad$ do-  alreadySeen <- M.member thisID <$> lift get-  when alreadySeen$-    throwError.DuplicateRef$ "Duplicate definition of " <> (T.show thisID)-  lift.modify$ M.insert thisID (toDyn value)-  return ()---- | Run a 'StructureMonad', returning either an error or a value, and the--- cross reference table.-runStructure :: StructureMonad a -> (Either GDError a, M.Map GDXRefID Dynamic)-runStructure (StructureMonad m) = (flip runState) M.empty . runExceptT$ m-
− src/Data/Gedcom/Parser.hs
@@ -1,1123 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecursiveDo #-}-{-# LANGUAGE TupleSections #-}--{-|-Module: Data.Gedcom.Parser-Description: GEDCOM high level parsers-Copyright: (c) Callum Lowcay, 2017-License: BSD3-Maintainer: cwslowcay@gmail.com-Stability: experimental-Portability: GHC--These parsers extract the GEDCOM records from the raw syntax tree.---}-module Data.Gedcom.Parser (-  parseGedcom,-  parseHeader-) where--import Control.Applicative-import Control.Monad.Except-import Data.Bifunctor-import Data.Dynamic-import Data.Gedcom.Common-import Data.Gedcom.Internal.Common-import Data.Gedcom.LineParser-import Data.Gedcom.ParseMonads-import Data.Gedcom.Structure-import Data.Maybe-import Data.Monoid-import Data.Time.Calendar-import Data.Time.Clock-import qualified Data.Map.Lazy as M-import qualified Data.Text.All as T-import Text.Megaparsec---- | Parse a 'Gedcom' value from the raw GEDCOM syntax tree.-parseGedcom :: GDRoot -> (Either GDError Gedcom, M.Map GDXRefID Dynamic)-parseGedcom (GDRoot children) =-  runStructure.runMultiMonad children$ Gedcom-    <$> parseRequired (GDTag "HEAD") parseHeader-    <*> parseMulti parseFamily-    <*> parseMulti (parseIndividual (GDTag "INDI"))-    <*> parseMulti parseMultimediaRecord-    <*> parseMulti parseNote-    <*> parseMulti parseRepository-    <*> parseMulti parseSource-    <*> parseMulti (parseSubmitter (GDTag "SUBM"))---- | Parse a 'Header'.-parseHeader :: StructureParser Header-parseHeader = parseNoLinkTag (GDTag "HEAD")$ \(_, children) ->-  runMultiMonad children$ Header-    <$> parseRequired (GDTag "SOUR") parseHeaderSource-    <*> parseOptional (parseTextTag (GDTag "DEST"))-    <*> parseOptional parseExactDateTime-    <*> parseRequired (GDTag "SUBM") (parseSubmitter (GDTag "SUBM"))-    <*> parseOptional parseSubmission-    <*> parseOptional parseFile-    <*> parseOptional parseCopyright-    <*> parseRequired (GDTag "GEDC") parseGedcomFormat-    <*> parseRequired (GDTag "CHAR") parseCharset-    <*> parseOptional parseLanguage-    <*> parseOptional parsePlaceForm-    <*> parseOptional (parseTextTag (GDTag "NOTE"))---- | Parse a 'HeaderSource'.-parseHeaderSource :: StructureParser HeaderSource-parseHeaderSource = parseNoLinkTag (GDTag "SOUR")$ \(sid, children) ->-  runMultiMonad children$ HeaderSource (gdIgnoreEscapes sid)-    <$> parseOptional parseVersion-    <*> parseOptional parseName-    <*> parseOptional parseCorp-    <*> parseOptional parseHeaderSourceData---- | Parse a 'Corp'.-parseCorp :: StructureParser Corp-parseCorp = parseNoLinkTag (GDTag "COPR")$ \(name, children) ->-  runMultiMonad children$ Corp (gdIgnoreEscapes name)-    <$> (parseContactDetails >>= (parseOptional.parseAddress))---- | Parse a 'HeaderSourceData'.-parseHeaderSourceData :: StructureParser HeaderSourceData-parseHeaderSourceData = parseNoLinkTag (GDTag "DATA")$ \(name, children) ->-  runMultiMonad children$ HeaderSourceData (gdIgnoreEscapes name)-    <$> parseOptional parseExactDate-    <*> parseOptional parseCopyright---- | Parse a 'Family'.-parseFamily :: StructureParser (GDRef Family)-parseFamily = parseTag (GDTag "FAM")$ \(_, children) ->-  runMultiMonad children$ Family-    <$> parseOptional parseRestrictionNotice-    <*> parseFamilyEvent-    <*> parseOptional (parseIndividual (GDTag "HUSB"))-    <*> parseOptional (parseIndividual (GDTag "WIFE"))-    <*> parseMulti (parseIndividual (GDTag "CHIL"))-    <*> parseOptional (parseWordTag (GDTag "NCHI"))-    <*> parseMulti (parseSubmitter (GDTag "SUBM"))-    <*> parseMulti parseUserReference-    <*> parseOptional parseRIN-    <*> parseOptional parseChangeDate-    <*> parseMulti parseNote-    <*> parseMulti parseSourceCitation-    <*> parseMulti parseMultimedia---- | Parse an 'Individual'.-parseIndividual :: GDTag -> StructureParser (GDRef Individual)-parseIndividual tag = parseTag tag$ \(_, children) ->-  runMultiMonad children$ Individual-    <$> parseOptional parseRestrictionNotice-    <*> parseOptional parsePersonalName-    <*> parseOptional parseSex-    <*> parseIndividualEvent-    <*> parseIndividualAttribute-    <*> parseMulti parseChildToFamilyLink-    <*> parseMulti parseSpouseToFamilyLink-    <*> parseMulti (parseSubmitter (GDTag "SUBM"))-    <*> parseMulti parseAssociation-    <*> parseMulti (parseIndividual (GDTag "ALIA"))-    <*> parseMulti (parseSubmitter (GDTag "ANCI"))-    <*> parseMulti (parseSubmitter (GDTag "DECI"))-    <*> parseOptional parseRFN-    <*> parseOptional parseAFN-    <*> parseMulti parseUserReference-    <*> parseOptional parseRIN-    <*> parseOptional parseChangeDate-    <*> parseMulti parseNote-    <*> parseMulti parseSourceCitation-    <*> parseMulti parseMultimedia---- | Parse a 'Node'.-parseNote :: StructureParser (GDRef Note)-parseNote = parseTag (GDTag "NOTE")$ \(t, children) ->-  runMultiMonad children$ Note (gdIgnoreEscapes t)-    <$> parseMulti parseUserReference-    <*> parseOptional parseRIN-    <*> parseMulti parseSourceCitation-    <*> parseOptional parseChangeDate---- | Parse a 'Repository'.-parseRepository :: StructureParser (GDRef Repository)-parseRepository = parseTag (GDTag "REPO")$ \(_, children) ->-  runMultiMonad children$ Repository-    <$> parseRequired (GDTag "NAME") parseName-    <*> (parseContactDetails >>= (parseOptional.parseAddress))-    <*> parseMulti parseNote-    <*> parseMulti parseUserReference-    <*> parseOptional parseRIN-    <*> parseOptional parseChangeDate---- | Parse a 'Source'.-parseSource :: StructureParser (GDRef Source)-parseSource = parseTag (GDTag "SOUR")$ \(_, children) ->-  runMultiMonad children$ Source-    <$> parseOptional parseSourceData-    <*> parseOptional (parseTextTag (GDTag "AUTH"))-    <*> parseOptional (parseTextTag (GDTag "TITL"))-    <*> parseOptional (parseTextTag (GDTag "ABBR"))-    <*> parseOptional (parseTextTag (GDTag "PUBL"))-    <*> parseOptional (parseTextTag (GDTag "TEXT"))-    <*> parseMulti parseRepositoryCitation-    <*> parseMulti parseUserReference-    <*> parseOptional parseRIN-    <*> parseOptional parseChangeDate-    <*> parseMulti parseNote-    <*> parseMulti parseMultimedia---- | Parse a 'Submitter'.-parseSubmitter :: GDTag -> StructureParser (GDRef Submitter)-parseSubmitter tag = parseTag tag$ \(_, children) ->-  runMultiMonad children$ Submitter-    <$> parseRequired (GDTag "NAME")-      ((fmap.fmap.fmap) getPersonalName parseName)-    <*> (parseContactDetails >>= (parseOptional.parseAddress))-    <*> parseOptional parseMultimedia-    <*> parseMulti parseLanguage-    <*> parseOptional parseRFN-    <*> parseOptional parseRIN-    <*> parseMulti parseNote-    <*> parseOptional parseChangeDate---- | Parse a 'Submission'.-parseSubmission :: StructureParser (GDRef Submission)-parseSubmission = parseTag (GDTag "SUBN")$ \(_, children) ->-  runMultiMonad children$ Submission-    <$> parseOptional (parseSubmitter (GDTag "SUBM"))-    <*> parseOptional (parseTextTag (GDTag "FAMF"))-    <*> parseOptional (parseTextTag (GDTag "TEMP"))-    <*> parseOptional (parseWordTag (GDTag "ANCE"))-    <*> parseOptional (parseWordTag (GDTag "DESC"))-    <*> parseOptional (parseBoolTag (GDTag "ORDI"))-    <*> parseOptional parseRIN-    <*> parseMulti parseNote-    <*> parseOptional parseChangeDate---- | Parse a 'RestrictionNotice'.-parseRestrictionNotice :: StructureParser RestrictionNotice-parseRestrictionNotice = parseNoLinkTag (GDTag "RESN")$ \(t, _) ->-  case parseMaybe parser (gdIgnoreEscapes t) of-    Nothing -> throwError.FormatError$-      "Bad restriction notice " <> (T.show t)-    Just r -> return r-  where parser :: Parser RestrictionNotice-        parser =     (Confidential <$ string' "confidential")-                 <|> (Locked <$ string' "locked")-                 <|> (Privacy <$ string' "privacy")---- | Parse a list of 'FamilyEvent's.-parseFamilyEvent :: MultiMonad [FamilyEvent]-parseFamilyEvent = do-    concat <$> mapM (parseMulti.familyEventTag) [-      (GDTag "ANUL", const Annuled),-      (GDTag "CENS", const FamCensus),-      (GDTag "DIV",  const Divorce),-      (GDTag "DIVF", const DivorceFiled),-      (GDTag "ENGA", const Engagement),-      (GDTag "MARB", const MarriageBann),-      (GDTag "MARC", const MarriageContract),-      (GDTag "MARR", const Marriage),-      (GDTag "MARL", const MarriageLicense),-      (GDTag "MARS", const MarriageSettlement),-      (GDTag "RESI", const Residence),-      (GDTag "EVEN", FamilyEventType)]-  where-    familyEventTag (tag, mkType) = parseNoLinkTag tag$ \(t, children) ->-      runMultiMonad children$ FamilyEvent (mkType$ gdIgnoreEscapes t)-        <$> parseFamilyEventDetail---- | Parse a 'FamiltyEventDetail'.-parseFamilyEventDetail :: MultiMonad FamilyEventDetail-parseFamilyEventDetail = FamilyEventDetail-  <$> parseOptional (parseAge (GDTag "HUSB"))-  <*> parseOptional (parseAge (GDTag "WIFE"))-  <*> parseEventDetail---- | Parse an 'EventDetail'.-parseEventDetail :: MultiMonad EventDetail-parseEventDetail = EventDetail-  <$> parseOptional (parseTextTag (GDTag "TYPE"))-  <*> parseOptional parseDateValue-  <*> parseOptional parsePlace-  <*> (parseContactDetails >>= (parseOptional.parseAddress))-  <*> parseOptional (parseTextTag (GDTag "AGNC"))-  <*> parseOptional (parseTextTag (GDTag "RELI"))-  <*> parseOptional (parseTextTag (GDTag "CAUS"))-  <*> parseOptional parseRestrictionNotice-  <*> parseMulti parseNote-  <*> parseMulti parseSourceCitation-  <*> parseMulti parseMultimedia---- | Parse an AGE tag.-parseAge :: GDTag -> StructureParser Word-parseAge tag = parseNoLinkTag tag$ \(_, children) ->-  runMultiMonad children$-    parseRequired (GDTag "AGE") (parseWordTag (GDTag "AGE"))---- | Parse a 'SourceData'.-parseSourceData :: StructureParser SourceData-parseSourceData = parseNoLinkTag (GDTag "DATA")$ \(_, children) ->-  runMultiMonad children$ SourceData-    <$> parseMulti parseSourceRecordedEvent-    <*> parseOptional (parseTextTag (GDTag "AGNC"))-    <*> parseMulti parseNote---- | Parse a 'Place'.-parsePlace :: StructureParser Place-parsePlace = parseNoLinkTag (GDTag "PLAC")$ \(t, children) ->-  runMultiMonad children$ Place-    <$> (pure$ T.splitOn "," . gdIgnoreEscapes$ t)-    <*> parseOptional (parseListTag (GDTag "FORM"))-    <*> parseOptional parsePhoneticPlaceName-    <*> parseOptional parseRomanPlaceName-    <*> parseOptional parseMapCoord-    <*> parseMulti parseNote---- | Parse a 'PhoneticPlaceName'.-parsePhoneticPlaceName :: StructureParser PhoneticPlaceName-parsePhoneticPlaceName = parseNoLinkTag (GDTag "FONE")$ \(t, children) ->-  runMultiMonad children$ PhoneticPlaceName-    <$> parseRequired (GDTag "TYPE") parsePhoneticType-    <*> (pure . T.splitOn "," . gdIgnoreEscapes$ t)---- | Parse a 'RomanPlaceName'.-parseRomanPlaceName :: StructureParser RomanPlaceName-parseRomanPlaceName = parseNoLinkTag (GDTag "ROMN")$ \(t, children) ->-  runMultiMonad children$ RomanPlaceName-    <$> parseRequired (GDTag "TYPE") parseRomanType-    <*> (pure . T.splitOn "," . gdIgnoreEscapes$ t)---- | Parse a 'PhoneticType'.-parsePhoneticType :: StructureParser PhoneticType-parsePhoneticType = parseNoLinkTag (GDTag "TYPE")$ \(t, _) ->-  return$ case trim . T.toUpper . gdIgnoreEscapes$ t of-    "HANGUL" -> Hangul-    "KANA" -> Kana-    v -> PhoneticType v---- | Parse a 'RomanType'.-parseRomanType :: StructureParser RomanType-parseRomanType = parseNoLinkTag (GDTag "TYPE")$ \(t, _) ->-  return$ case trim . T.toUpper . gdIgnoreEscapes$ t of-    "PINYIN" -> Pinyin-    "ROMAJI" -> Romaji-    "WADEGILES" -> WadeGiles-    v -> RomanType v---- | Parse a 'MapCoord'.-parseMapCoord :: StructureParser MapCoord-parseMapCoord = parseNoLinkTag (GDTag "MAP")$ \(_, children) ->-  runMultiMonad children$ MapCoord-    <$> parseRequired (GDTag "LATI") ((fmap.fmap.fmap) Longitude$-      parseLongLat (GDTag "LATI") 'N' 'S')-    <*> parseRequired (GDTag "LONG") ((fmap.fmap.fmap) Latitude$-      parseLongLat (GDTag "LONG") 'E' 'W')---- | Parse a 'Longitude' or 'Latitude' value.-parseLongLat ::-     GDTag -- ^ The tag to parse-  -> Char  -- ^ The single character prefix that indicates a positive value.  -  -> Char  -- ^ The single character prefix that indicates a negative value.-  -> StructureParser Double-parseLongLat tag p n = parseNoLinkTag tag$ \(t, _) ->-  case T.uncons . T.toUpper . gdIgnoreEscapes$ t of-    Nothing -> throwError.FormatError$-      "Badly formatted longitude/latitude " <> (T.show t)-    Just (i, r) ->-      if i == p then return$ read . T.unpack$ r-      else if i == n then return$ negate . read . T.unpack$ r-      else throwError.FormatError$-        "Badly formatted longitude/latitude" <> (T.show t)---- | Parse a 'PersonalName'.-parsePersonalName :: StructureParser PersonalName-parsePersonalName = parseNoLinkTag (GDTag "NAME")$ \(n, children) ->-  runMultiMonad children$ PersonalName-    <$> (pure.getPersonalName.gdIgnoreEscapes$ n)-    <*> parseOptional parseNameType-    <*> parseNamePieces-    <*> parseMulti parsePhoneticName-    <*> parseMulti parseRomanName-    --- | Extract a 'Name' from a string.-getPersonalName :: T.Text -> Name-getPersonalName = Name <$> reformat <*> (getMiddle . T.splitOn "/")-  where-   reformat = T.unwords . T.words . T.map (\c -> if c == '/' then ' ' else c)-   getMiddle [_, m, _] = Just$ trim m-   getMiddle _ = Nothing---- | Parse a 'NameType'.-parseNameType :: StructureParser NameType-parseNameType = parseNoLinkTag (GDTag "TYPE")$ \(t', _) ->-  let t = gdIgnoreEscapes t'-  in return . fromMaybe (NameType t) . parseMaybe parser $ t-  where parser :: Parser NameType-        parser =     (AKA <$ string' "aka")-                 <|> (BirthName <$ string' "birth")-                 <|> (Immigrant <$ string' "immigrant")-                 <|> (Maiden <$ string' "maiden")-                 <|> (Married <$ string' "married")---- | Parse a 'PersonalNamePieces' structure.-parseNamePieces :: MultiMonad PersonalNamePieces-parseNamePieces = PersonalNamePieces-  <$> (fromMaybe [] <$> parseOptional (parseListTag (GDTag "NPFX")))-  <*> (fromMaybe [] <$> parseOptional (parseListTag (GDTag "GIVN")))-  <*> (fromMaybe [] <$> parseOptional (parseListTag (GDTag "NICK")))-  <*> (fromMaybe [] <$> parseOptional (parseListTag (GDTag "SPFX")))-  <*> (fromMaybe [] <$> parseOptional (parseListTag (GDTag "SURN")))-  <*> (fromMaybe [] <$> parseOptional (parseListTag (GDTag "NSFX")))-  <*> parseMulti parseNote-  <*> parseMulti parseSourceCitation---- | Parse a 'PhoneticName'.-parsePhoneticName :: StructureParser PhoneticName-parsePhoneticName = parseNoLinkTag (GDTag "FONE")$ \(t, children) ->-  runMultiMonad children$ PhoneticName-    <$> (pure.getPersonalName.gdIgnoreEscapes$ t)-    <*> parseRequired (GDTag "TYPE") parsePhoneticType-    <*> parseNamePieces---- | Parse a 'RomanizedName'.-parseRomanName :: StructureParser RomanizedName-parseRomanName = parseNoLinkTag (GDTag "FONE")$ \(t, children) ->-  runMultiMonad children$ RomanizedName-    <$> (pure.getPersonalName.gdIgnoreEscapes$ t)-    <*> parseRequired (GDTag "TYPE") parseRomanType-    <*> parseNamePieces---- | Parse a 'Sex'.-parseSex :: StructureParser Sex-parseSex = parseNoLinkTag (GDTag "SEX")$ \(t, _) ->-  case trim . T.toUpper . gdIgnoreEscapes $ t of-    "M" -> return Male-    "F" -> return Female-    "U" -> return Undetermined-    _ -> throwError.FormatError$ "Unknown sex code " <> (T.show t)-  --- | Parse a list of 'IndividualAttribute's.-parseIndividualAttribute :: MultiMonad [IndividualAttribute]-parseIndividualAttribute = do-    concat <$> mapM (parseMulti.attributeTag) [-      (GDTag "CAST", Caste),-      (GDTag "DSCR", PhysicalDescription),-      (GDTag "EDUC",  Education),-      (GDTag "IPNO", NationalID),-      (GDTag "NATI", NationalOrigin),-      (GDTag "NCHI", NChildren . read . T.unpack),-      (GDTag "NMR", NMarriages . read . T.unpack),-      (GDTag "OCCU", Occupation),-      (GDTag "PROP", Possessions),-      (GDTag "RELI", Religion),-      (GDTag "RESI", const ResidesAt),-      (GDTag "SSN", SocialSecurity),-      (GDTag "TITL", Title),-      (GDTag "FACT", Fact)]-  where-    attributeTag (tag, mkType) = parseNoLinkTag tag$ \(t, children) ->-      runMultiMonad children$ IndividualAttribute (mkType$ gdIgnoreEscapes t)-        <$> parseIndividualEventDetail---- | Parse a list of 'IndividualEvent's-parseIndividualEvent :: MultiMonad [IndividualEvent]-parseIndividualEvent = do-    famc <- concat <$> mapM (parseMulti.famcTag)-      [(GDTag "BIRT", Birth), (GDTag "CHR", Christening)]-    adop <- parseMulti.parseNoLinkTag (GDTag "ADOP")$ \(_, children) ->-      runMultiMonad children$ IndividualEvent-        <$> (Adoption <$> parseOptional parseAdopFamilyRef)-        <*> parseIndividualEventDetail-    simple <- concat <$> mapM (parseMulti.eventTag) [-      (GDTag "DEAT", const Death),-      (GDTag "BURI", const Burial),-      (GDTag "CREM", const Cremation),-      (GDTag "BAPM", const Baptism),-      (GDTag "BARM", const BarMitzvah),-      (GDTag "BASM", const BasMitzvah),-      (GDTag "BLES", const Blessing),-      (GDTag "CHRA", const ChristeningAdult),-      (GDTag "CONF", const Confirmation),-      (GDTag "FCOM", const FirstCommunion),-      (GDTag "ORDN", const Ordination),-      (GDTag "NATU", const Naturalization),-      (GDTag "EMIG", const Emigration),-      (GDTag "IMMI", const Immigration),-      (GDTag "CENS", const IndvCensus),-      (GDTag "PROB", const Probate),-      (GDTag "WILL", const Will),-      (GDTag "GRAD", const Graduation),-      (GDTag "RETI", const Retirement),-      (GDTag "EVEN", IndividualEventType)]-    return$ famc ++ adop ++ simple-  where-    eventTag (tag, mkType) = parseNoLinkTag tag$ \(t, children) ->-      runMultiMonad children$ IndividualEvent (mkType$ gdIgnoreEscapes t)-        <$> parseIndividualEventDetail-    famcTag (tag, mkType) = parseNoLinkTag tag$ \(_, children) ->-      runMultiMonad children$ IndividualEvent-        <$> (mkType <$> parseOptional parseFamilyRef)-        <*> parseIndividualEventDetail-    parseFamilyRef = parseLinkTag (GDTag "FAMC") -    parseAdopFamilyRef = parseTagFull (GDTag "FAMC") nullrref$ \(lb, children) ->-      case lb of-        Right _ -> throwError.RequiredRef$ "Missing link in FAMC"-        Left f -> runMultiMonad children$-          AdoptionDetail f <$> parseOptional parseParent-    parseParent = parseNoLinkTag (GDTag "ADOP")$ \(t, _) ->-      case trim . T.toUpper . gdIgnoreEscapes $ t of-        "HUSB" -> return Husband-        "WIFE" -> return Wife-        "BOTH" -> return BothParents-        _ -> throwError.FormatError$ "Invalid parent " <> (T.show t)---- | Parse an 'IndividualEventDetail'.-parseIndividualEventDetail :: MultiMonad IndividualEventDetail-parseIndividualEventDetail = IndividualEventDetail-  <$> parseEventDetail-  <*> parseOptional (parseWordTag (GDTag "AGE"))---- | Parse a 'ChildToFamilyLink'.-parseChildToFamilyLink :: StructureParser ChildToFamilyLink-parseChildToFamilyLink = parseTagFull (GDTag "FAMC") nullrref$ \(lb, children) ->-  case lb of-    Right _ -> throwError.RequiredRef$ "Missing link in FAMC"-    Left f -> runMultiMonad children$ ChildToFamilyLink f-      <$> parseOptional parsePedigree-      <*> parseOptional parseChildLinkStatus-      <*> parseMulti parseNote---- | Parse a 'Pedigree'.-parsePedigree :: StructureParser Pedigree-parsePedigree = parseNoLinkTag (GDTag "PEDI")$ \(t, _) ->-  case trim . T.toUpper . gdIgnoreEscapes$ t of-    "ADOPTED" -> return Adopted-    "BIRTH" -> return ByBirth-    "FOSTER" -> return Foster-    "SEALING" -> return Sealing-    _ -> throwError.FormatError$ "Invalid pedigree code " <> (T.show t)---- | Parse a 'ChildLinkStatus'.-parseChildLinkStatus :: StructureParser ChildLinkStatus-parseChildLinkStatus = parseNoLinkTag (GDTag "STAT")$ \(t, _) ->-  case trim . T.toUpper . gdIgnoreEscapes$ t of-    "CHALLENGED" -> return Challenged-    "DISPROVEN" -> return Disproved-    "PROVEN" -> return Proven-    _ -> throwError.FormatError$ "Invalid child link status " <> (T.show t)---- | Parse a 'SpouseToFamilyLink'.-parseSpouseToFamilyLink :: StructureParser SpouseToFamilyLink-parseSpouseToFamilyLink = parseTagFull (GDTag "FAMS") nullrref$-  \(lb, children) ->-    case lb of-      Right _ -> throwError.RequiredRef$ "Missing link in FAMS"-      Left f -> runMultiMonad children$ SpouseToFamilyLink f-        <$> parseMulti parseNote---- | Parse an 'Association'.-parseAssociation :: StructureParser Association-parseAssociation = parseTagFull (GDTag "ASSO") nullrref$ \(lb, children) ->-  case lb of-    Right _ -> throwError.RequiredRef$ "Missing link in ASSO"-    Left i -> runMultiMonad children$ Association i-      <$> parseRequired (GDTag "RELA") (parseTextTag (GDTag "RELA"))-      <*> parseMulti parseSourceCitation-      <*> parseMulti parseNote---- | Parse a 'SourceRecordedEvent'.-parseSourceRecordedEvent :: StructureParser SourceRecordedEvent-parseSourceRecordedEvent = parseNoLinkTag (GDTag "EVEN")$-  \(recorded, children) ->-   runMultiMonad children$ SourceRecordedEvent-     <$> (pure . catMaybes . fmap getEventType-       . T.splitOn "," . gdIgnoreEscapes$ recorded)-     <*> parseOptional fullParseDatePeriod-     <*> parseOptional (parseListTag (GDTag "PLAC"))-     where-      fullParseDatePeriod = parseNoLinkTag (GDTag "DATE")$ \(date, _) ->-        case parseDatePeriod date of-          Just v -> return v-          Nothing -> throwError.FormatError$-            "Badly formatted date period: " <> (T.show date)---- | Parse a 'RepositoryCitation'.-parseRepositoryCitation :: StructureParser RepositoryCitation-parseRepositoryCitation = parseTagFull (GDTag "REPO") nullrref$-  \(lb, children) ->-    let repo = case lb of-                 Left v -> Just v-                 Right _ -> Nothing-    in runMultiMonad children$ RepositoryCitation repo-      <$> parseMulti parseNote-      <*> parseOptional parseCallNumber---- | Parse a 'CallNumber'.-parseCallNumber :: StructureParser CallNumber-parseCallNumber = parseNoLinkTag (GDTag "CALN")$ \(n, children) ->-  runMultiMonad children$ CallNumber (gdIgnoreEscapes n)-    <$> parseOptional (parseMultimediaType (GDTag "MEDI"))---- | Parse a 'SourceCitation'.-parseSourceCitation :: StructureParser SourceCitation-parseSourceCitation = parseTagFull (GDTag "SOUR") nullrref$-  \(lb, children) ->-    case lb of-      Left source ->-        runMultiMonad children$ SourceCitation (Right source)-          <$> parseOptional (parseTextTag (GDTag "PAGE"))-          <*> parseMulti parseMultimedia-          <*> parseMulti parseNote-          <*> parseOptional parseQuality-      Right description ->-        runMultiMonad children$ SourceCitation-          <$> (Left . SourceDescription (gdIgnoreEscapes description)-            <$> parseMulti (parseTextTag (GDTag "TEXT")))-          <*> pure Nothing-          <*> parseMulti parseMultimedia-          <*> parseMulti parseNote-          <*> parseOptional parseQuality---- | Parse a 'GedcomFormat'.-parseGedcomFormat :: StructureParser GedcomFormat-parseGedcomFormat = parseNoLinkTag (GDTag "GEDC")$ \(_, children) ->-  runMultiMonad children$ GedcomFormat-    <$> parseRequired (GDTag "VERS") parseVersion-    <*> parseRequired (GDTag "FORM") parseGedcomForm---- | Parse a 'GedcomForm'.-parseGedcomForm :: StructureParser GedcomForm-parseGedcomForm = parseNoLinkTag (GDTag "FORM")$ \(t, _) ->-  return$ if (T.toUpper . gdIgnoreEscapes$ t) == "LINEAGE-LINKED"-    then GedcomLineageLinked-    else GedcomUnsupported (gdIgnoreEscapes t)---- | Parse a 'Charset'.-parseCharset :: StructureParser Charset-parseCharset = parseNoLinkTag (GDTag "CHAR")$ \(cs, children) ->-  runMultiMonad children$ Charset (gdIgnoreEscapes cs)-    <$> parseOptional parseVersion---- | Parse a 'ChangeDate'.-parseChangeDate :: StructureParser ChangeDate-parseChangeDate = parseNoLinkTag (GDTag "CHAN")$ \(_, children) ->-  runMultiMonad children$ ChangeDate-    <$> parseRequired (GDTag "DATE") parseExactDateTime-    <*> parseOptional parseNote---- | Parse 'ContactDetails'.-parseContactDetails :: MultiMonad ContactDetails-parseContactDetails = ContactDetails-  <$> parseMulti (parseTextTag (GDTag "PHON"))-  <*> parseMulti (parseTextTag (GDTag "EMAIL"))-  <*> parseMulti (parseTextTag (GDTag "FAX"))-  <*> parseMulti (parseTextTag (GDTag "WWW"))---- | Parse an 'Address'.-parseAddress :: ContactDetails -> StructureParser Address-parseAddress contacts = parseNoLinkTag (GDTag "ADDR")$ \(addr, children) ->-  runMultiMonad children$ Address (gdIgnoreEscapes addr)-    <$> parseOptional (parseTextTag (GDTag "CITY"))-    <*> parseOptional (parseTextTag (GDTag "STAE"))-    <*> parseOptional (parseTextTag (GDTag "POS"))-    <*> parseOptional (parseTextTag (GDTag "CTRY"))-    <*> pure contacts---- | Parse a 'DateValue'.-parseDateValue :: StructureParser DateValue-parseDateValue = parseNoLinkTag (GDTag "DATE")$ \(t, _) ->-  let date = (DateApproxV <$> parseDateApprox t)-         <|> (DateRangeV <$> parseDateRange t)-         <|> (DatePeriodV <$> parseDatePeriod t)-         <|> (parseDatePhrase t)-         <|> (DateV <$> parseDate t)-  in case date of-    Just x -> return x-    Nothing -> throwError.FormatError$ "Invalid date format " <> (T.show t)---- | Decode a calendar escape sequence to a 'Calendar'.-decodeCalendarEscape :: Maybe GDEscape -> Calendar-decodeCalendarEscape Nothing = Gregorian-decodeCalendarEscape (Just (GDEscape c)) = case T.toUpper c of-                                             "DGREGORIAN" -> Gregorian-                                             "DJULIAN" -> Julian-                                             "DHEBREW" -> Hebrew-                                             "DFRENCH" -> French-                                             "DROMAN" -> Julian-                                             "DUNKNOWN" -> Gregorian-                                             _ -> Gregorian---- | Prepare text for parsing a 'DateValue'.-prepareDateText :: [(Maybe GDEscape, T.Text)] -> [(Maybe GDEscape, T.Text)]-prepareDateText = gdFilterEscapes [-                    GDEscape "DGREGORIAN",-                    GDEscape "DJULIAN",-                    GDEscape "DHEBREW",-                    GDEscape "DFRENCH",-                    GDEscape "DROMAN",-                    GDEscape "DUNKNOWN"]---- | Attempt to extract a 'DatePeriod' from a string with escape sequences.-parseDatePeriod :: [(Maybe GDEscape, T.Text)] -> Maybe DatePeriod-parseDatePeriod t = case prepareDateText t of-  ((mCalendarEscape1, t1'):rest) ->-    let-      calendar1 = decodeCalendarEscape mCalendarEscape1-      t1 = trim$ T.toUpper t1'-      from = trim <$> T.stripPrefix "FROM" t1-      to = trim <$> T.stripPrefix "TO" t1-    in case to of-      Just r -> DateTo <$> getDate calendar1 r-      Nothing -> case from of-        Nothing -> Nothing-        Just r ->-          let topcs = T.splitOn "TO"$ r-          in case topcs of-            [mfdate, mto] -> DateFrom-                <$> getDate calendar1 (trim mfdate)-                <*> (pure$ getDate calendar1 (trim mto))-            [mfdate] -> case rest of-                [] -> DateFrom-                  <$> getDate calendar1 (trim mfdate) <*> (pure Nothing)-                ((mCalendarEscape2, t2'):_) ->-                  let-                    calendar2 = decodeCalendarEscape mCalendarEscape2-                    t2 = trim$ T.toUpper t2'-                    to2 = trim <$> T.stripPrefix "TO" t2-                  in case to2 of-                    Nothing -> Nothing-                    Just r2 -> DateFrom-                      <$> getDate calendar1 (trim mfdate)-                      <*> (pure$ getDate calendar2 (trim r2))-            _ -> Nothing-  _ -> Nothing---- | Attempt to extract a 'DateRange' from a string with escape sequences.-parseDateRange :: [(Maybe GDEscape, T.Text)] -> Maybe DateRange-parseDateRange t = case prepareDateText t of-  ((mCalendarEscape1, t1):rest) ->-    let-      calendar1 = decodeCalendarEscape mCalendarEscape1-      (pref, date1) = second trim . T.splitAt 3 . T.toUpper . trim $ t1-    in case pref of-      "BEF" -> DateBefore <$> getDate calendar1 date1-      "AFT" -> DateAfter <$> getDate calendar1 date1-      "BET" -> case T.splitOn "AND" date1 of-        [d1, date2'] -> DateBetween-          <$> getDate calendar1 d1-          <*> getDate calendar1 (trim date2')-        [d1] -> case rest of-          [] -> Nothing-          ((mCalendarEscape2, t2):_) ->-            let calendar2 = decodeCalendarEscape mCalendarEscape2-            in DateBetween-              <$> getDate calendar1 d1-              <*> getDate calendar2 (trim t2)-        _ -> Nothing-      _ -> Nothing-  _ -> Nothing---- | Attempt to extract a 'DateApprox' from a string with escape sequences.-parseDateApprox :: [(Maybe GDEscape, T.Text)] -> Maybe DateApprox-parseDateApprox t = case prepareDateText t of-  ((mCalendarEscape1, t1):_) ->-    let-      calendar1 = decodeCalendarEscape mCalendarEscape1-      (pref, date) = second trim . T.splitAt 3 . T.toUpper . trim $ t1-      cons = case pref of-        "ABT" -> Just DateAbout-        "CAL" -> Just DateCalculated-        "EST" -> Just DateEstimated-        _ -> Nothing-    in cons <*> getDate calendar1 date-  _ -> Nothing---- | Attempt to extract a 'DatePhrase' from a string with escape sequences.-parseDatePhrase :: [(Maybe GDEscape, T.Text)] -> Maybe DateValue-parseDatePhrase t = case prepareDateText t of-  ((mCalendarEscape1, t1):_) ->-    let-      calendar1 = decodeCalendarEscape mCalendarEscape1-      int = trim <$> T.stripPrefix "INT" t1-      opp = trim <$> T.stripPrefix "(" t1-    in case int of-      Nothing -> case opp of-        Nothing -> Nothing-        Just phrase -> Just$-          DatePhrase Nothing (trim . T.dropEnd 1$ phrase)-      Just rest -> case trim <$> T.splitOn "(" rest of-        [date, phrase] -> Just$ -          DatePhrase (getDate calendar1 date) (trim . T.dropEnd 1$ phrase)-        _ -> Nothing-  _ -> Nothing---- | Attempt to extract a 'Date' from a string with escape sequences.-parseDate :: [(Maybe GDEscape, T.Text)] -> Maybe Date-parseDate t = case prepareDateText t of-    ((mCalendarEscape, cal):rest) ->-      let calendar = decodeCalendarEscape mCalendarEscape-      in getDate calendar (cal <> gdIgnoreEscapes rest)-    _ -> Nothing---- | Parse a 'Date' from a given string assuming the given 'Calendar'.-getDate :: Calendar -> T.Text -> Maybe Date-getDate calendar = parseMaybe parser-  where-    yearParser = case calendar of-      Gregorian -> yearGreg-      _ -> read <$> count' 1 4 digitChar-    parseYear = (\y bc -> Year$ if bc then (0 - y) else y)-      <$> yearParser <*> ((True <$ string' "B.C.") <|> pure False)-    parser :: Parser Date-    parser =-      (try$ Date calendar-          <$> (Just . read <$> count' 1 2 digitChar)-          <*> (gdDelim >> (Just <$> parseMonth))-          <*> (gdDelim >> parseYear))-      <|> (try$ Date calendar Nothing-          <$> (gdDelim >> (Just <$> parseMonth))-          <*> (gdDelim >> parseYear))-      <|> (Date calendar Nothing Nothing-          <$> (gdDelim >> parseYear))-    parseMonth = case calendar of-                   Gregorian -> month-                   Julian -> month-                   Hebrew -> monthHeb-                   French -> monthFr-      --- | Parse an exact date.-parseExactDate :: StructureParser UTCTime-parseExactDate = parseNoLinkTag (GDTag "DATE")$ \(date, _) ->-  case parseMaybe dateExact (gdIgnoreEscapes date) of-    Nothing -> throwError.FormatError$ "Bad date \"" <> (T.show date) <> "\""-    Just (d, m, y) ->-      return$ UTCTime-        (fromGregorian (fromIntegral y) (fromIntegral m) d)-        (secondsToDiffTime 0)---- | Parse an exact date and time.-parseExactDateTime :: StructureParser UTCTime-parseExactDateTime = parseNoLinkTag (GDTag "DATE")$ \(date, children) -> do-  mtime <- runMultiMonad children$ parseOptional (parseTextTag (GDTag "TIME"))--  dt <- case mtime of-    Nothing -> return$ secondsToDiffTime 0-    Just t -> case parseMaybe timeValue t of-      Nothing -> throwError.FormatError$ "Bad time \"" <> (T.show t) <> "\""-      Just Nothing -> return$ secondsToDiffTime 0-      Just (Just time) -> return$ timeToPicos time--  case parseMaybe dateExact (gdIgnoreEscapes date) of-    Nothing -> throwError.FormatError$ "Bad date \"" <> (T.show date) <> "\""-    Just (d, m, y) -> return$ UTCTime-      (fromGregorian (fromIntegral y) (fromIntegral m) d) dt---- | Parse a 'Multimedia' record.-parseMultimediaRecord :: StructureParser (GDRef Multimedia)-parseMultimediaRecord = parseMultimediaRaw (GDTag "TYPE")---- | Parse a 'Multimedia' link.-parseMultimedia :: StructureParser (GDRef Multimedia)-parseMultimedia = parseMultimediaRaw (GDTag "MEDI")---- | Actual parser for 'Multimedia' values.-parseMultimediaRaw :: GDTag -> StructureParser (GDRef Multimedia)-parseMultimediaRaw typeTag = parseTag (GDTag "OBJE")$ \(_, children) ->-  runMultiMonad children$ Multimedia-    <$> ((parseOptional (parseMultimediaFormat typeTag)) >>=-      (parseMulti.(parseMultimediaFile typeTag)))-    <*> parseOptional (parseTextTag (GDTag "TITL"))-    <*> parseMulti parseUserReference-    <*> parseOptional parseRIN-    <*> parseMulti parseNote-    <*> parseMulti parseSourceCitation-    <*> parseOptional parseChangeDate---- | Parse a 'MultimediaFile'.-parseMultimediaFile ::-  GDTag -> Maybe MultimediaFormat ->-  StructureParser MultimediaFile-parseMultimediaFile typeTag mf = parseNoLinkTag (GDTag "FILE")$-  \(name, children) -> do-    (mc, title) <- runMultiMonad children$ (,)-      <$> parseOptional (parseMultimediaFormat typeTag)-      <*> parseOptional (parseTextTag (GDTag "TITL"))-    case mc <|> mf of-      Nothing -> throwError.TagError$ "Missing FORM tag for file format"-      Just c -> return$ MultimediaFile (gdIgnoreEscapes name) c title---- | Parse a 'MultimediaFormat'.-parseMultimediaFormat :: GDTag -> StructureParser MultimediaFormat-parseMultimediaFormat tag = parseNoLinkTag (GDTag "FORM")$ \(v', children) ->-  let v = gdIgnoreEscapes v'-  in runMultiMonad children$ MultimediaFormat-    (fromMaybe (MF_OTHER v)$ parseMaybe parser v)-    <$> parseOptional (parseMultimediaType tag)--  where-    parser :: Parser MultimediaFileFormat-    parser =     (MF_BMP <$ string' "bmp")-             <|> (MF_GIF <$ string' "gif")-             <|> (MF_JPG <$ string' "jpg")-             <|> (MF_OLE <$ string' "ole")-             <|> (MF_PCX <$ string' "pcx")-             <|> (MF_TIF <$ string' "tif")-             <|> (MF_WAV <$ string' "wav")---- | Parse a 'MultimediaType'.-parseMultimediaType :: GDTag -> StructureParser MultimediaType-parseMultimediaType tag = parseNoLinkTag tag$ \(v', _) ->-  let v = gdIgnoreEscapes v'-  in return.fromMaybe (MT_OTHER v)$ parseMaybe parser v-  where-    parser :: Parser MultimediaType-    parser =     (MT_AUDIO <$ string' "audio")-             <|> (MT_BOOK <$ string' "book")-             <|> (MT_CARD <$ string' "card")-             <|> (MT_ELECTRONIC <$ string' "electronic")-             <|> (MT_FICHE <$ string' "fiche")-             <|> (MT_FILM <$ string' "film")-             <|> (MT_MAGAZINE <$ string' "magazine")-             <|> (MT_MANUSCRIPT <$ string' "manuscript")-             <|> (MT_MAP <$ string' "map")-             <|> (MT_NEWSPAPER <$ string' "newspaper")-             <|> (MT_PHOTO <$ string' "photo")-             <|> (MT_TOMBSTONE <$ string' "tombstone")-             <|> (MT_VIDEO <$ string' "video")---- | Parse a 'FamilyEventType'.-getFamilyEventType :: T.Text -> Maybe FamilyEventType-getFamilyEventType = parseMaybe parser-  where-    parser :: Parser FamilyEventType-    parser =     (Annuled <$ string' "ANUL")-             <|> (FamCensus <$ string' "CENS")-             <|> (Divorce <$ string' "DIV")-             <|> (DivorceFiled <$ string' "DIVF")-             <|> (Engagement <$ string' "ENGA")-             <|> (MarriageBann <$ string' "MARB")-             <|> (MarriageContract <$ string' "MARC")-             <|> (Marriage <$ string' "MARR")-             <|> (MarriageLicense <$ string' "MARL")-             <|> (MarriageSettlement <$ string' "MARS")-             <|> (Residence <$ string' "RESI")-             <|> (FamilyEventType . T.pack <$>-               (string' "EVEN" *> gdDelim *> many anyChar))---- | Parse an 'IndividualEventType'.-getIndividualEventType :: T.Text -> Maybe IndividualEventType-getIndividualEventType = parseMaybe parser-  where-    parser :: Parser IndividualEventType-    parser =     (Birth Nothing <$ (string' "BIRTH"-                    *> optional (gdDelim >> string' "Y")))-             <|> (Christening Nothing <$ (string' "CHR"-                    *> optional (gdDelim >> string' "Y")))-             <|> (Death <$ (string' "DEAT"-                    *> optional (gdDelim >> string' "Y")))-             <|> (Burial <$ string' "BURI")-             <|> (Cremation <$ string' "CREM")-             <|> (Adoption Nothing <$ string' "ADOP")-             <|> (Baptism <$ string' "BAPM")-             <|> (BarMitzvah <$ string' "BARM")-             <|> (BasMitzvah <$ string' "BASM")-             <|> (Blessing <$ string' "BLES")-             <|> (ChristeningAdult <$ string' "CHRA")-             <|> (Confirmation <$ string' "CONF")-             <|> (FirstCommunion <$ string' "FCOM")-             <|> (Ordination <$ string' "ORDN")-             <|> (Naturalization <$ string' "NATU")-             <|> (Emigration <$ string' "EMIG")-             <|> (Immigration <$ string' "IMMI")-             <|> (IndvCensus <$ string' "CENS")-             <|> (Probate <$ string' "PROB")-             <|> (Will <$ string' "WILL")-             <|> (Graduation <$ string' "GRAD")-             <|> (Retirement <$ string' "RETI")-             <|> (IndividualEventType . T.pack <$>-               (string' "EVEN" *> gdDelim *> many anyChar))---- | Parse an 'EventType'.-getEventType :: T.Text -> Maybe EventType-getEventType et =-  let-    t = trim$ T.toUpper et-    fam = getFamilyEventType et-    indv = getIndividualEventType et-  in-    if t == "CENS" then Just Census-    else if (T.take 4 t) == "EVEN" then-      Just . EventType . trim . T.drop 4$ et-    else fmap FamilyEventTypeV fam <|> fmap IndividualEventTypeV indv---- | Parse a place form structure.-parsePlaceForm :: StructureParser [T.Text]-parsePlaceForm = parseNoLinkTag (GDTag "PLAC")$ \(_, children) ->-  runMultiMonad children$ fromMaybe [].(fmap$ T.splitOn ",") <$>-    parseOptional (parseTextTag (GDTag "FORM"))---- | Parse a 'UserReference'.-parseUserReference :: StructureParser UserReference-parseUserReference = parseNoLinkTag (GDTag "REFN")$ \(i, children) ->-  runMultiMonad children$ UserReference (gdIgnoreEscapes i)-    <$> parseOptional (parseTextTag (GDTag "TYPE"))---- | Parse a version structure.-parseVersion :: StructureParser T.Text-parseVersion = parseTextTag (GDTag "VERS")---- | Parse a NAME tag.-parseName :: StructureParser T.Text-parseName = parseTextTag (GDTag "NAME")---- | Parse a copyright tag.-parseCopyright :: StructureParser T.Text-parseCopyright = parseTextTag (GDTag "COPR")---- | Parse a file name.-parseFile :: StructureParser FilePath-parseFile = (fmap.fmap.fmap) T.unpack$ parseTextTag (GDTag "FILE")---- | Parse an 'AFN'.-parseAFN :: StructureParser AFN-parseAFN = (fmap.fmap.fmap) AFN$ parseTextTag (GDTag "AFN")---- | Parse a 'RFN'.-parseRFN :: StructureParser RFN-parseRFN = (fmap.fmap.fmap) RFN$ parseTextTag (GDTag "RFN")---- | Parse a 'RIN'.-parseRIN :: StructureParser RIN-parseRIN = (fmap.fmap.fmap) RIN$ parseTextTag (GDTag "RIN")---- | Parse a 'Language'.-parseLanguage :: StructureParser Language-parseLanguage = (fmap.fmap.fmap) (Language) $ parseTextTag (GDTag "LANG")---- | Parse a 'QualityAssessment'.-parseQuality :: StructureParser QualityAssessment-parseQuality = (fmap.fmap.fmap) QualityAssessment $ parseWordTag (GDTag "QUAY")---- | Parse a boolean value.-parseBoolTag :: GDTag -> StructureParser Bool-parseBoolTag tag = parseNoLinkTag tag$ \(v, _) ->-  case parseMaybe ynParser (gdIgnoreEscapes v) of-    Nothing -> throwError.FormatError$ "Expected boolean, saw " <> (T.show v)-    Just yn -> return yn-  where-    ynParser :: Parser Bool-    ynParser = (True <$ string' "yes") <|> (False <$ string' "no")---- | Parse a Word value.-parseWordTag :: GDTag -> StructureParser Word-parseWordTag tag = parseNoLinkTag tag$ \(v, _) ->-  case parseMaybe parser (gdIgnoreEscapes v) of-    Nothing -> throwError.FormatError$ "Expected number, saw " <> (T.show v)-    Just n -> return . read $ n-  where-    parser :: Parser String-    parser = many digitChar---- | Extract the text from a tag.-parseTextTag :: GDTag -> StructureParser T.Text-parseTextTag tag = parseNoLinkTag tag (return.gdIgnoreEscapes.fst)---- | Extract a list of comma separated values from a tag.-parseListTag :: GDTag -> StructureParser [T.Text]-parseListTag tag =-  parseNoLinkTag tag (return . T.splitOn "," . gdIgnoreEscapes . fst)---- | Handler for tags that cannot contain cross references.-type NoLinkHandler a =-  ([(Maybe GDEscape, T.Text)], [GDTree]) -> StructureMonad a---- | Handler for general tags.-type TagHandler b a =-  (Either (GDRef b) [(Maybe GDEscape, T.Text)], [GDTree])-  -> StructureMonad a---- | A function that adds references to the cross reference table.-type RegisterRef a = GDTag -> GDXRefID -> a -> StructureMonad ()---- | Don't add any references.-nullrref :: Typeable a => RegisterRef a-nullrref _ _ _ = return ()---- | Add direct references only.-defrref :: Typeable a => RegisterRef (GDRef a)-defrref _ thisID (GDStructure a) = addReference thisID a-defrref tag _ _ = throwError.UnexpectedRef$-  "Referenced structure references another structure " <> (T.show tag)---- | Parse a tag which is either a GEDCOM structure, or a reference to the--- expected GEDCOM structure.-parseTag :: Typeable a-  => GDTag            -- ^ The tag to parse.-  -> NoLinkHandler a  -- ^ A handler for the tag-  -> StructureParser (GDRef a)-parseTag tag handler = parseTagFull tag defrref$ \(lb, children) ->-  case lb of-    Left ref -> return ref-    Right text -> GDStructure <$> handler (text, children)---- | Parse a tag which cannot contain a cross reference (i.e. the tag must--- contain the structure itself, not a reference to another structure).-parseNoLinkTag :: Typeable a-  => GDTag            -- ^ The tag to parse.-  -> NoLinkHandler a  -- ^ A handler for the tag.-  -> StructureParser a-parseNoLinkTag tag handler = parseTagFull tag nullrref$ \(lb, children) ->-  case lb of-    Left _ -> throwError.UnexpectedRef$-      "Cannot follow cross references on " <> (T.show tag)-    Right text -> handler (text, children)---- | Parse a tag which must contain a cross reference to another structure, not--- the structure itself.-parseLinkTag :: Typeable a => GDTag -> StructureParser (GDRef a)-parseLinkTag tag = parseTagFull tag nullrref$ \(lb, _) ->-  case lb of-    Left ref -> return ref-    Right _ -> throwError.RequiredRef$-      "Expected cross reference was missing in " <> (T.show tag)---- | The most general tag parsing function.-parseTagFull :: Typeable a-  => GDTag             -- ^ The tag to parse.-  -> RegisterRef a     -- ^ How to register cross references.-  -> TagHandler b a    -- ^ How to convert the tag into a GEDCOM structure.-  -> StructureParser a-parseTagFull tag rref handler t@(GDTree (GDLine _ mthisID tag' v) children) =-  if tag /= tag' then return$ Left t else do-    r <- case v of-      Nothing -> Right <$> (handler.(first Right)$ parseCont mempty children)-      Just (GDXRefIDV xref) -> do-        Right <$> (handler (Left (GDXRef xref), children))-      Just (GDLineItemV l1) ->-        Right <$> (handler.(first Right)$ parseCont l1 children)-    case (mthisID, r) of-      (Just thisID, Right rv) -> rref tag thisID rv-      _ -> return ()-    return r---- | Handle CONT and CONC tags.-parseCont ::-     GDLineItem -- ^ The value of the first line-  -> [GDTree]   -- ^ The sub tree-  -> ([(Maybe GDEscape, T.Text)], [GDTree])  -- ^ The concatenation of the values of all the CONT and CONC tags, and the remaining tags.-parseCont l1 children =-    bimap assemble (fmap snd).span (isJust.fst)$-      zipWith (\l r -> (cont l <|> conc l, r)) children children-  where-    assemble = gdLineData . mconcat . (l1:) . catMaybes . fmap fst-    cont (GDTree (GDLine _ _ (GDTag "CONT") (Just (GDLineItemV l))) _) =-      Just$ GDLineItem [(Nothing, "\r\n")] <> l-    cont _ = Nothing-    conc (GDTree (GDLine _ _ (GDTag "CONC") (Just (GDLineItemV l))) _) =-      Just$ gdTrimLineItem l-    conc _ = Nothing-
src/Data/Gedcom/Structure.hs view
@@ -96,7 +96,7 @@ Year (..) ) where -import Data.Gedcom.Common+import Data.Gedcom.Internal.CoreTypes import Data.Time.Clock import qualified Data.Text.All as T 
test/Spec.hs view
@@ -1,2 +1,153 @@+{-# LANGUAGE OverloadedStrings #-}++import Data.Gedcom.Internal.CoreTypes+import Data.Gedcom.Internal.LineParser+import Data.Gedcom.Internal.ParseMonads+import Data.Gedcom.Internal.Parser+import Data.Monoid+import Data.Void+import qualified Data.Text.All as T+import Test.Hspec+import Text.Megaparsec++testTagData :: T.Text+testTagData = "some test data"++testTag :: T.Text -> Maybe GDLine+testTag d = do+  (GDRoot [GDTree t []]) <- parseMaybe gdRoot$ "0 TEST " <> d <> "\n"+  return t++emptyTag :: Maybe GDLine+emptyTag = do+  (GDRoot [GDTree t []]) <- parseMaybe gdRoot$ "0 TEST\n"+  return t++ref1 :: GDXRefID+ref1 = GDXRefID "1"++linkTag :: Maybe GDLine+linkTag = do+  (GDRoot [GDTree t []]) <- parseMaybe gdRoot$ "0 TEST @1@\n"+  return t++linkLinkTag :: Maybe GDLine+linkLinkTag = do+  (GDRoot [GDTree t []]) <- parseMaybe gdRoot$ "0 @2@ TEST @1@\n"+  return t++crdTag :: Maybe GDLine+crdTag = do+  (GDRoot [GDTree t []]) <-+    parseMaybe gdRoot$ "0 @1@ TEST " <> testTagData <> "\n"+  return t++data ParseReturn a =+  Error T.Text | NoMatch | Match a deriving (Show, Eq)++isError :: ParseReturn a -> Bool+isError (Error _) = True+isError _ = False++parseStructure :: Maybe GDTree -> StructureParser a -> ParseReturn a+parseStructure Nothing p = Error "Line parse error"+parseStructure (Just v) p = case runStructure (p v) of+    (Right (Left _), _) -> NoMatch+    (Right (Right m), _) -> Match m+    (Left err, _) -> Error$ T.show err++noEscapes :: T.Text -> [(Maybe GDEscape, T.Text)]+noEscapes v = [(Nothing, v)]+ main :: IO ()-main = putStrLn "Test suite not yet implemented"+main = hspec$ do+  describe "gdRoot"$ do+    it "parses a simple line with no children"$+      (testTag testTagData) `shouldBe`+        (Just$ GDLine (GDLevel 0) Nothing (GDTag "TEST")+          (Just . GDLineItemV . GDLineItem . noEscapes$ testTagData))+    it "parses a simple cross referenced line"$+      crdTag `shouldBe` (Just$ GDLine (GDLevel 0) (Just ref1) (GDTag "TEST")+        (Just . GDLineItemV . GDLineItem . noEscapes$ testTagData))+    it "parses a simple line cross referencing line"$+      linkTag `shouldBe` (Just$ GDLine (GDLevel 0) Nothing (GDTag "TEST")+        (Just . GDXRefIDV$  ref1))+    it "parses an empty tag with no children"$+      emptyTag `shouldBe`+        (Just$ GDLine (GDLevel 0) Nothing (GDTag "TEST") Nothing)++  describe "parseNoLinkTag"$ do+    it "matches the specified tag"$+      testLine (testTag testTagData) (parseNoLinkTag (GDTag "TEST") pure)+        `shouldBe` (Match (noEscapes testTagData, []))+    it "matches the specified tag (with a cross reference)" $+      testLine crdTag (parseNoLinkTag (GDTag "TEST") pure)+        `shouldBe` (Match (noEscapes testTagData, []))+    it "doesn't match other tags"$+      testLine (testTag testTagData) (parseNoLinkTag (GDTag "OTHER") pure)+        `shouldBe` NoMatch+    it "doesn't parse links"$+      isError$ testLine linkTag (parseNoLinkTag (GDTag "TEST") pure)++  describe "parseTag"$ do+    it "matches the specified tag"$+      testLine (testTag testTagData) (parseTag (GDTag "TEST") pure)+        `shouldBe` (Match . GDStructure$ (noEscapes testTagData, []))+    it "matches the specified tag (with a cross reference)" $+      testLine crdTag (parseTag (GDTag "TEST") pure)+        `shouldBe` (Match . GDStructure$ (noEscapes testTagData, []))+    it "doesn't match other tags"$+      testLine (testTag testTagData) (parseTag (GDTag "OTHER") pure)+        `shouldBe` NoMatch+    it "parses links"$+      testLine linkTag (parseTag (GDTag "TEST") pure)+        `shouldBe` (Match$ GDXRef ref1)+    it "doesn't parse links to links"$+      isError$ testLine linkLinkTag (parseTag (GDTag "TEST") pure)++  describe "parseLinkTag"$ do+    it "parses link tags"$+      testLine linkTag (parseLinkTag (GDTag "TEST")) `shouldBe`+        (Match$ (GDXRef ref1 :: GDRef Void))+    it "doesn't parse other tags"$+      isError$ testLine (testTag testTagData)+        (parseLinkTag (GDTag "TEST") :: StructureParser (GDRef Void))++  describe "parseTextTag"$ do+    it "matches the specified tag" $+      testLine (testTag testTagData) (parseTextTag (GDTag "TEST"))+        `shouldBe` (Match testTagData)++  describe "parseListTag"$ do+    it "splits lists"$+      testLine (testTag "one,,two,three,four") (parseListTag (GDTag "TEST"))+        `shouldBe` (Match ["one", "", "two", "three", "four"])+    it "handles the empty list"$+      testLine emptyTag (parseListTag (GDTag "TEST")) `shouldBe` (Match [])++  describe "parseWordTag"$ do+    it "parses numbers"$+      testLine (testTag "42") (parseWordTag (GDTag "TEST")) `shouldBe` (Match 42)+    it "doesn't parse negative numbers"$+      isError$ testLine (testTag "-42") (parseWordTag (GDTag "TEST"))+    it "doesn't parse empty strings"$+      isError$ testLine (testTag "") (parseWordTag (GDTag "TEST"))++  describe "parseBoolTag"$ do+    it "parses yes and no"$ do+      testLine (testTag "yes") (parseBoolTag (GDTag "TEST"))+        `shouldBe` (Match True)+      testLine (testTag "no") (parseBoolTag (GDTag "TEST"))+        `shouldBe` (Match False)+    it "parses case insensitive"$ do+      testLine (testTag "Yes") (parseBoolTag (GDTag "TEST"))+        `shouldBe` (Match True)+      testLine (testTag "nO") (parseBoolTag (GDTag "TEST"))+        `shouldBe` (Match False)+    it "doesn't parse anything else"$+      (isError$ testLine (testTag "true") (parseBoolTag (GDTag "TEST")))+      && (isError$ testLine (testTag "false") (parseBoolTag (GDTag "TEST")))++  where+    testLine l = parseStructure (GDTree <$> l <*> pure [])+