Next / Previous / Contents / Shipman's homepage

17.11. Txny.__addSpecies(): Add a new species and its bindings

nomcompile3
# - - -   T x n y . _ _ a d d S p e c i e s

    def __addSpecies ( self, scan, stdHead, spTail ):
        '''Add a new species taxon and its bindings.

          [ (scan is a Scan instance) and
            (stdHead is a StdHead instance) and
            (spTail is an SpTail instance) ->
              if (stdHead, spTail) names a species that can be appended
              to self.taxaTree ->
                self.taxaTree  +:=  a new Taxon for that species
                self.abTab  +:=  bindings from (stdHead, spTail)
              else ->
                self.taxaTree  +:=  a new Taxon for that species,
                                    if valid
                Log()  +:=  error message(s)
                raise SyntaxError ]
        '''

There is one subtle input error that we need to detect. Suppose someone prepares a standard forms file in which the species in a particular genus are not all together in sequence, like this:

f  Famiday
   Ardea cinerea/...
   Egretta thula/...
   Ardea herodias/...

If we use the standard placement rules, species herodias would be placed in the wrong genus, Egretta, because that genus is the growing point for adding new species! There is a parallel problem for subgenera.

The solution is to calculate the genus or subgenus parent of the species using Section 18.3, “TaxaTree.rankParent(): Under what parent does a new taxon go?”. If the parent is a genus, its name must match spTail.genus; if the parent is a subgenus, its name must match spTail.subgenus. For the relevant intended function, see Section 7.9, “rank-parent: What taxon is the parent of a new taxon of a given rank?”.

nomcompile3
        #-- 1 --
        # [ parent  :=  rank-parent ( self.taxaTree, SPECIES_CODE )
        #   sci  :=  spTail.genus + " " + spTail.species ]
        parent = self.taxaTree.rankParent ( SPECIES_CODE )
        sci = "%s %s" % (spTail.genus, spTail.species)

        #-- 2 --
        # [ if parent matches genus or subgenus from spTail ->
        #     I
        #   else ->
        #     Log()  +:=  error message(s)
        #     raise SyntaxError ]
        if parent.rank.code == GENUS_CODE:
            expectSci = spTail.genus
        else:
            expectSci = "%s (%s)" % (spTail.genus, spTail.subgenus)
        if parent.sci != expectSci:
            scan.syntax ( "One expects to place this species in '%s', "
                "but you have it in '%s'." %
                (parent.sci, expectSci) )

Assemble the new species's attributes into a RawTaxon instance, then append it to the tree (assuming that it fits). See Section 23, “class RawTaxon: Temporary container for taxon attributes” and Section 17.7, “Txny.__appendTaxon(): Try to append this taxon to the tree”.

nomcompile3
        #-- 3 --
        # [ rawSpecies  :=  a new RawTaxon instance with rank code
        #       SPECIES_CODE; scientific name (sci); English name
        #       (spTail.eng); status (spTail.status);
        #       canon (spTail.canonical); and disambiguation
        #       (spTail.disamb) ]
        rawSpecies = RawTaxon ( SPECIES_CODE, sci, spTail.eng,
            stdHead.status, spTail.canonical, spTail.disamb )

        #-- 4 --
        # [ if rawSpecies can be appended to self.taxaTree ->
        #     self.taxaTree  +:=  a new Taxon instance made from rawTaxon
        #     taxon  :=  that new Taxon
        #   else ->
        #     Log()  +:=  error message(s)
        #     raise SyntaxError ]
        taxon = self.__appendTaxon ( scan, rawSpecies )

Unlike the genus and subgenus case, a species can carry one or two new bird code bindings; add them to the symbol table.

nomcompile3
        #-- 5 --
        # [ if the bindings for taxon are consistent with self.abTab ->
        #     self.abTab  +:=  those bindings
        #   else ->
        #     Log()  +:=  error message(s)
        #     raise SyntaxError ]
        self.__addCodes ( scan, taxon )