Next / Previous / Contents / Shipman's homepage

19.9. BaseCompiler.__iter__(): Iterator

Normally, the .__iter__ method of a class is supposed to return an object that has a .next() method that can be called to return each generated value. However, the .__iter__() method itself can be a generator, and that is the approach we take.

Basically, this method is the main loop that reads through the lines of the input file.

baseclasses.py
# - - -   B a s e C o m p i l e r . _ _ i t e r _ _   - - -

    def __iter__(self):
        '''Iterator for BaseCompiler: generate all BaseEncounter records
        '''

Lines are classified as one of four types; see the specification.

  1. Empty lines, or lines containing only whitespace, are ignored.

  2. Lines starting with “@” (PAGE_SYMBOL) are page header lines. Assuming the line has a valid format, it is converted into a PageHeader object and stored in self.pageHeader.

  3. Lines starting with “#” (PREFIX_SYMBOL) are new band prefix lines. If it is valid, it is stored in self.prefix as a Prefix object.

  4. All other lines are assumed to be encounter lines. Each line that is valid causes the generation of one BaseEncounter object using the Python yield statement.

So that this method can generate values, we must call the self.classify() function in a for loop, and yield any values it generates. See Section 19.10, “BaseCompiler.classify(): Which kind of line is it?”.

baseclasses.py
        #-- 1 --
        while  not self.scan.atEndFile:
            #-- 1 body --
            # [ if the line in self.scan is empty or contains only
            #   whitespace ->
            #     I
            #   else if the line in self.scan is a valid new page
            #   header ->
            #     self.pageHeader  :=  a PageHeader object representing
            #         that line
            #   else if the line in self.scan is a valid band prefix line
            #   in the context of self ->
            #     self.prefix  :=  a Prefix object representing that line
            #   else if the line in self.scan is a valid encounter line
            #   in the context of self ->
            #     yield a BaseEncounter object representing that line
            #   else ->
            #     Log()  +:=  error message(s)
            #   In any case ->
            #     self.scan  :=  self.scan advanced to the start of the
            #                    next line ]
            for x in self.classify():
                yield x
            self.scan.nextLine()

When the file is exhausted, we close self.scan object and raise StopIteration to signal the end of the iterator.

baseclasses.py
        #-- 2 --
        self.scan.close()
        raise StopIteration