# - - - T x n y . _ _ s c a n C o l l i s i o n A l t
def __scanCollisionAlt ( self, scan, code ):
'''Scan an alt forms line describing a collision group.
[ (scan is a Scan instance) and
(code is a bird code) ->
if (code+ALT_COLLISION+(rest of line in scan)) is
a valid collision alt forms line ->
scan := scan advanced to end of line
self.abTab +:= bindings from that line
else ->
scan := scan advanced no further than end of line
Log() +:= error message(s)
raise SyntaxError ]
'''
Here's a typical alt forms file collision line. This
one says that code PASSER is a collision form,
and the preferred alternatives are PASR, PASINA, and PASINE.
passer?pasr :pasina:pasine
We'll build a set named codeSet containing the
preferred codes. Technically, each of the codes should
be right-blank-padded to length, but the parsing logic
will not enforce this.
#-- 1 --
# [ if scan starts with a bird code ->
# scan := scan advanced past that code and any
# trailing blanks
# codeSet := a set containing that code, uppercased
# else ->
# Log() +:= error message(s)
# raise SyntaxError ]
m = scan.tabReMatch ( abbrMod.RE_ABBR )
if m is None:
scan.syntax ( "Expecting a bird code." )
else:
codeSet = set ( [m.group().upper()] )
scan.deblankLine()
So long as the next character in scan is the delimiter
that separates codes (see Section 6.18, “COLL_SEP”),
advance past that delimiter, require another code,
and append the code to codeSet.
#-- 2 --
# [ if scan starts with a sequence of COLL_SEP
# characters alternating with bird codes ->
# scan := scan advanced past all that
# codeSet := codeSet with those codes added
# else if any COLL_SEP character is not followed
# by a bird code ->
# Log() +:= error message(s)
# raise SyntaxError ]
# else -> I ]
while scan.tabMatch ( COLL_SEP ):
#-- 2 body --
# [ if scan starts with a bird code ->
# scan := scan advanced past that code and
# any trailing spaces
# codeSet := codeSet + (that code, uppercased)
# else ->
# Log() +:= error message(s)
# raise SyntaxError ]
m = scan.tabReMatch ( abbrMod.RE_ABBR )
if m is None:
scan.syntax ( "Expecting a bird code." )
else:
codeSet.add ( m.group().upper() )
scan.deblankLine()
We should be at end of line now, or it's an error. Also,
there must be at least two codes in codeSet.
Having checked that, try to add bindings for all the relevant
codes; this logic is in Section 17.26, “Txny.__bindCollision()”.
#-- 3 --
# [ if scan is at end of line -> I
# else ->
# Log() +:= error message(s)
# raise SyntaxError ]
if not scan.atEndLine():
scan.syntax ( "Unrecognized characters" )
#-- 4 --
# [ if codeSet has two or more elements ->
# I
# else ->
# Log() +:= error message(s)
# raise SyntaxError ]
if len(codeSet) < 2:
scan.syntax ( "There must be at least two codes past "
"the '%s' character." % ALT_COLLISION )
#-- 5 --
# [ if self is compatible with (code) as a collision
# form and the forms in (codeSet) as disambiguations ->
# self.abTab +:= a collision binding from code
# to codeSet
# else ->
# Log() +:= error message(s)
# raise SyntaxError ]
self.__bindCollision ( scan, code, codeSet )