# - - - 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?”.
#-- 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”.
#-- 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.
#-- 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 )