Next / Previous / Contents / Shipman's homepage

17.25. Txny.__scanCollisionAlt(): Scan a higher-taxon line

nomcompile3
# - - -   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.

nomcompile3
        #-- 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.

nomcompile3
        #-- 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().

nomcompile3
        #-- 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 )