### 11.14. `BirdId.scanFlat()`

This is similar to the `.scan()` method, but assumes a fixed-field format.

abbr.py
```# - - -   B i r d I d . s c a n F l a t   - - -

def scanFlat ( txny, scan ):
"""Scan a flat-field compound bird code.
"""
```

First we require a bird code, followed by enough spaces to make it length `ABBR_L`.

abbr.py
```        #-- 1 --
# [ if scan starts with a bird code as a flat field ->
#     scan  :=  scan advanced past that code
#     abbr  :=  that code
#   else ->
#     scan  +:=  error message
#     raise ValueError ]
abbr = BirdId.scanAbbrFlat ( txny, scan )
```

Next comes the relationship code.

abbr.py
```        #-- 2 --
# [ if scan starts with REL_SIMPLE followed by BLANK_ABBR ->
#     scan  :=  scan advanced past all that
#     return a new BirdId made from txny and abbr
#   else -> I ]
m = scan.tabMatch ( REL_SIMPLE )
if  m is not None:
abbr2 = scan.tabMatch ( BLANK_ABBR )
if  abbr2 is not None:
return BirdId ( txny, abbr )
else:
message = ( "The second bird code must be blank when "
"the rel-code is blank." )
scan.error ( message )
raise ValueError, message
```

Since the rel-code isn't blank, we must now parse a valid rel-code followed by a valid bird code.

abbr.py
```        #-- 3 --
# [ if scan starts with a rel-code followed by a bird code ->
#     scan   :=  scan advanced past all that
#     rel    :=  the rel-code
#     abbr2  :=  the bird code
#   else ->
#     scan  +:=  error message
#     raise ValueError ]
m = scan.tabReMatch ( RE_REL )
if  m is None:
message = "Expecting a relationship code."
scan.error ( message )
raise ValueError, message
rel = m.group()
abbr2 = BirdId.scanAbbrFlat ( txny, scan )

#-- 3 --
return BirdId ( txny, abbr, rel, abbr2 )

scanFlat = staticmethod(scanFlat)
```