#########################################
##  NzGrammar.txt
##  Standardise New Zealand Addresses
#########################################

#	Generic file, to be included by other grammar files.
#	The New Zealand equivalent of DpidGrammar.txt
#	Created Aug06

#	The includer file needs to set these variables:
#		sDatabase - name of the NZ ARF to use
#		sGIFields - GIF fields to return with address
#		sOldPostcodeGif - GIF field containing old postcodes
#		sPOI - Point of Interest files to use (if NZ_POI defined)
#
#	The includer file may define these values:
#		sARF_NAME - name of ARF to keep open
#		NZ_RD_NUMBER_GIF_FIELD - which GIF field contains the RD number
#		NZ_VALIDATE_CORRECTED - return a validFlag for the corrected address
#			(only use if using the Address1_/2_/3_ address lines)
#		NZ_UNIT_NUMBER_WITHOUT_SLASH - "1 5 Main St" -> "1/5 Main St"
#		NZ_UNIT_SPACE_SUFFIX - allow space between unit number and its suffix
#		NZ_SKIP_VALIDATION - only parse address, don't validate it
#		LOOKUPFLAG - which address items to leave unchanged (see DpidGrammar)
#		NZ_LOOKUPFLAG - overrides the above flag [Dec11]
#		NZ_VALIDATE_LOOKUPFLAG - overrides the above flag if NZ_VALIDATE defined
#		NZ_VALIDATE - called by ValidateAddress (_NzAddress.grm); see above
#		NZ_CNAR_INCLUDES - include CNAR versions of suburb & city tables
#		NZ_LOBBY_IN_LOCALITY_FIELD - instead of building field [Sep12]
#		NZ_ABBREVIATE_TYPES - street types etc are abbreviated
#		NZ_RD_IN_LOCALITY_FIELD - instead of address line [Oct12]
#		NZ_RANGE_TO_UNIT_FIX_DIFF [Jul13]
#		NZ_PARSE_BUILDING_NAME_IN_QUOTES [Mar14]
#		NZ_REMOVE_PARENTHESIS [Oct14]
#		NZ_REMOVE_JUNK [Oct14]

\DEFINE NZ_LOBBY_IN_LOCALITY_FIELD
\DEFINE MRL
\DEFINE NZPOST_TEST

\VARIABLES
999	sTemp
100	sId
	sTempPoNum
	sTempRD
	sTempStName
	sTempStName2
	sUserStName
	sUserStType
	sUserLevel
	sUserFlat
	sUserStSuf
	sTempUnit1
	sTempUnit2
	sTempLot
	sTrim
	dummy
	sRdNumberLookedUp
	sUser
	sAbbr
	sRegion
	sDistrict
	sCorner
	sTempFlat
	sTempUserFlat
1	sDelim
50	sBuildingName
150	sPreAddress
255	sFullPaf
255	sFullPafForFormat
60	sStreetName
60	sLocality
60	sSuburbExtracted
60	sPostshop
	sDummy
50	sLobbyName
10	sSaveFlag
30	sAmendFlag1
30	sAmendFlag2
10	sFlagTemp
	sSuburb2
50	sSaveLobby
	StreetName_Save
	StreetType_Save
	StreetSuffix_Save
	sFullStreetName_Save
	sUserStName_Save
	sUserStType_Save
	sUserStSuf_Save
	sFullStreetName2
2	s2
	sCity
	sTempCity

# input to iPaf32 & output
30	State_	# (for NZ, this is the city)
4 	Pcode_
46 	Locality_
50	StreetName_
12	StreetType_
10	StreetSuffix_
16	PostalType_
14	AddressId_
10	HouseNo1_
1	HouseSuffix1_
10	HouseNo2_
1	HouseSuffix2_
10	FlatType_
10	FlatNo_
15	LevelType_
10	LevelNo_
50	BuildingName1_
30	BuildingName2_
10	LotNo_
10	PostalNo_
3	PostalPrefix_
3	PostalSuffix_
# (these are only in output)
1	PrimaryPointFlag_
1	SynonymFlag_
46	Synonym_
1	FinalAddressFlag_
46	BorderName_
4	BorderPostcode_
30	AltStName_
4	AltStType_
2	AltStSuf_
8	LocalityDID_
8	GroupDID_
10	Flag_	# amended or error and why
30	AmendedFlag_	# how amended (or more detail on error flag)
100	DummyPre		# returned from ArfEnhancer, not returned from iPaf32
100	DummyPost		# "
1	Dummy3
1	Dummy4
12	Latitude_	# this is no longer populated
12	Longitude_	# "
15	GIFlags_	# from where GIF fields taken
20	GIField1
20	GIField2
20	GIField3
20	GIField4
20	GIField5
20	GIField6
20	GIField7
20	GIField8
20	GIField9
20	GIField10
20	GIField11
20	GIField12
20	GIField13
20	GIField14
20	GIField15

#others cont.
100	PreAddress1_
100	PreAddress2_
50	Address1_	# formatted address. 3-field array [Feb08]
50	Address2_	# "
50	Address3_	# "
100	PostAddress_
100	FoundFullLocality
30	sPafError
10	sInputFlatType
10	sInputFlatNo
10	HousePrefix_
2	Country_
10	NzPostValidFlag_
10	CorrectedValidFlag_
160	FlagString_

# fields as parsed. ie. before corrected.
30	sInputCity
4 	sInputPcode
46 	sInputSuburb
30	sInputStreetName
12	sInputStreetType
10	sInputStreetSuffix
10	sInputRdNumber

# other inputs to iPaf32, JOINed separately
1	ExtraInputs # dummy positioner for array begining
10	sFlag
	sLocality2
	sStreetType2
	sFullStreetName
	sOtherOptions
	sStreet2Name
	sStreet2Type
	sRdNumber	#[Apr09:] passed to iPaf32 (from version 5.4.145)
50	sLobby
50	sLobbyTemp

\NUMERIC_VARIABLES
i
j
iPafError
bFormatError
iFlag
bStreetAndPostalError
bAmended
bOtherError
iStreetAddr
iPostalAddr
iSureUnit
iLastLine
bBuildingExtracted
iSuburbErrorFlag
iBuildingPos
bExtraLevel
iPos
iPos2
iPos3
bDoRD
bRemovedStreet
bDashToSlash
bDllReturnedAddress
bSecondStreet
bLobbyInLocalityField

################ Tables ###################33

\TABLE flagTable
	\INCLUDE DpidErrorCodes.txt
\TABLE amendedFlagTable
	\INCLUDE NzAmendedFlagCodes.txt

# Table Not Used
\TABLE BigCityTable # from wikipedia
AUCKLAND
CHRISTCHURCH
DUNEDIN
HAMILTON
INVERCARGILL
LOWER HUTT
MANUKAU
NAPIER
NELSON
NORTH SHORE
PALMERSTON NORTH
PORIRUA
TAURANGA
UPPER HUTT
WAITAKERE
WELLINGTON

# Table Not Used
\TABLE DistrictTable # from wikipedia
ASHBURTON
BULLER
CARTERTON
CENTRAL HAWKE'S BAY
CENTRAL OTAGO
CHATHAM ISLANDS 
CLUTHA
FAR NORTH
FRANKLIN
GISBORNE
GORE
GREY
HASTINGS
HAURAKI
HOROWHENUA
HURUNUI
KAIKOURA
KAIPARA
KAPITI COAST
KAWERA
MACKENZIE
MANAWATU
MARLBOROUGH
MASTERTON
MATAMATA-PIAKO
NEW PLYMOUTH
OPOTIKI
OTOROHANGA
PAPAKURA
QUEENSTOWN-LAKES
RANGITIKEI
RODNEY
ROTORUA
RUAPEHU
SELWYN
SOUTH TARANAKI
SOUTH WAIKATO
SOUTH WAIRARAPA 
SOUTHLAND 
STRATFORD
TARARUA
TASMAN
TAUPO
THAMES-COROMANDEL
TIMARU
WAIKATO
WAIMAKARIRI
WAIMATE
WAIPA
WAIROA
WAITAKI
WAITOMO
WANGANUI
WESTERN BAY OF PLENTY
WESTLAND
WHAKATANE
WHANGAREI

# Table Not Used
\TABLE RegionTable1 # from whitepages.co.nz
NORTH ISLAND
SOUTH ISLAND
AUCKLAND
BAY OF PLENTY
CANTERBURY
GISBORNE
HAWKE'S BAY
MANAWATU
MARLBOROUGH
NELSON & BAYS
NORTHLAND
OTAGO
SOUTHLAND
TARANAKI
TIMARU & OAMARU
WAIKATO
WAIRARAPA
WANGANUI
WELLINGTON
WEST COAST

\TABLE RegionTable # from wikipedia
AUCKLAND
BAY OF PLENTY
CANTERBURY
GISBORNE
HAWKES BAY
MANAWATU-WANGANUI
MANAWATU
MARLBOROUGH
NELSON
NORTHLAND
OTAGO
SOUTHLAND
TARANAKI
TASMAN
WAIKATO
WANGANUI
WELLINGTON
WEST COAST
# "greaters"
GREATER AUCKLAND
GREATER WELLINGTON
SOUTH AUCKLAND

\TABLE PostalType1Table # requires a postal number
PO BOX
C/ P O BOX=PO BOX
C/ PO BOX=PO BOX
C/- P O BOX=PO BOX
C/- PO BOX=PO BOX
C/-PO BOX=PO BOX
CARA PO BOX=PO BOX
CARE PO BOX=PO BOX
MAIL BOX=PO BOX
P O BOX=PO BOX
POST BOX=PO BOX
POST OFFICE BOX=PO BOX
POBOX=PO BOX
POB=PO BOX
POBX=PO BOX
P B=PO BOX
P O B=PO BOX
BOX=PO BOX
CMB
COMMUNITY MAIL BOX=CMB
RESPONSE BAG
# [Jun11]
PRIVATE BOX=PO BOX

\TABLE PostalType2Table # doesn't require a postal number
COUNTER DELIVERY
POSTE RESTANTE

\TABLE PostalType3Table # sometimes requires a postal number
PRIVATE BAG
P BAG=PRIVATE BAG
PRIV BAG=PRIVATE BAG
PRIVATE BAG NO=PRIVATE BAG
PRIVATE MAIL BAG=PRIVATE BAG
PRIVATE MAIL BAG SERVICE=PRIVATE BAG
PVT BAG=PRIVATE BAG
PRVT BAG=PRIVATE BAG

\TABLE SuburbTable
	\IFDEF NZ_CNAR_INCLUDES
		\INCLUDE CnarNzSuburbs.txt
	\ELSE
		\IFDEF NZ_AND_CNAR_INCLUDES
			\INCLUDE CnarNzSuburbs.txt
		\ENDIF
		# from generated file: GnafLocalities.txt
		\INCLUDE NzSuburbs.txt
		# some synonyms added with MT->MOUNT (TODO: update)
		MOUNT ALBERT
		MOUNT COOK
		MOUNT EDEN
		MOUNT MAUNGANUI
		MOUNT PLEASANT
		MOUNT ROSKILL
		MOUNT VICTORIA
		MOUNT WELLINGTON
	\ENDIF
	
\INCLUDE NzCodes.txt

\TABLE StateHighwayTable
STATE HIGHWAY
SH=STATE HIGHWAY
S H=STATE HIGHWAY
STATE HWY=STATE HIGHWAY

\TABLE CityTable OVERWRITE_DUPLICATES
	\IFDEF NZ_CNAR_INCLUDES
		\INCLUDE CnarNzCities.txt
	\ELSE
		\IFDEF NZ_AND_CNAR_INCLUDES
			\INCLUDE CnarNzCities.txt
		\ENDIF
		\INCLUDE NzCities.txt
		#Some abbreviations
		AK=AUCKLAND
		AUCK=AUCKLAND
		AUKLND=AUCKLAND
		AKL=AUCKLAND
		AKLD=AUCKLAND
		#CHCH=CHRISTCHURCH - now in NzCities.txt
		CH CH=CHRISTCHURCH
		NN=NELSON
		P NORTH=PALMERSTON NORTH

		# TODO: this may give false positives for international grammar,
		#	where trying to decide if address is NZ [Apr14]
		NORTH SHORE=NORTH SHORE CITY

		#truncations to 10
		\IFDEF MRL
		CHRISTCHUR=CHRISTCHURCH
		INVERCARGI=INVERCARGILL
		NEW PLYMOU=NEW PLYMOUTH
		\ENDIF
	\ENDIF

\TABLE NumericStreetNamesTable
	\INCLUDE NzNumericStreetNames.txt

\TABLE OldAucklandCitiesTable #[Dec10]
AUCKLAND
MANUKAU
NORTH SHORE CITY
PAPAKURA
WAITAKERE

# otherwise these may get parsed as street plus suburb [Jun09]
# TODO: update with PAF
\TABLE UnusualStreetNameTable
MAIN ROAD HOPE
MAIN ROAD LOWER MOUTERE
MAIN ROAD RIWAKA
MAIN ROAD ST ARNAUD
MAIN ROAD STOKE
MAIN ROAD TAPAWERA
RUE DE LA MER

MAIN RD HOPE=MAIN ROAD HOPE
MAIN RD LOWER MOUTERE=MAIN ROAD LOWER MOUTERE
MAIN RD RIWAKA=MAIN ROAD RIWAKA
MAIN RD ST ARNAUD=MAIN ROAD ST ARNAUD
MAIN RD STOKE=MAIN ROAD STOKE
MAIN RD TAPAWERA=MAIN ROAD TAPAWERA

# "SOUTH INVERCARGILL" will prevent "INVERCARGILL" being picked up as locality
\TABLE BoxLobbyNamesTable
PORT FITZROY
SOUTH INVERCARGILL
	#\INCLUDE NzBoxLobbyNames.txt

\TABLE NzTable
NZ
N Z=NZ
NEW ZEALAND=NZ
N ZEALAND=NZ

\TABLE RuralDeliveryTable
RD
R D=RD
RURAL DELIVERY=RD
RURAL DEV=RD

\TABLE ordinals
1ST=FIRST
2ND=SECOND
3RD=THIRD
4TH=FOURTH
5TH=FIFTH
6TH=SIXTH
7TH=SEVENTH
8TH=EIGHTH
9TH=NINTH
10TH=TENTH
11TH=ELEVENTH
12TH=TWELFTH
13TH=THIRTEENTH
14TH=FOURTEENTH
15TH=FIFTEENTH
16TH=SIXTEENTH
17TH=SEVENTEENTH
18TH=EIGHTEENTH
19TH=NINTEENTH
20TH=TWENTIETH
21ST=TWENTYFIRST
22ND=TWENTYSECOND
23RD=TWENTYTHIRD
24TH=TWENTYFOURTH
25TH=TWENTYFIFTH
26TH=TWENTYSIXTH
27TH=TWENTYSEVENTH
28TH=TWENTYEIGHTH
29TH=TWENTYNINTH
30TH=THIRTIETH

\TABLE ordinals2
FIRST=1
SECOND=2
THIRD=3
FOURTH=4
FIFTH=5
SIXTH=6
SEVENTH=7
EIGHTH=8
NINTH=9
TENTH=10

\TABLE NumbersTable
ONE=1
TWO=2
THREE=3
FOUR=4
FIVE=5
SIX=6
SEVEN=7
EIGHT=8
NINE=9
TEN=10

\TABLE lot
LOT

\TABLE careof
CARE OF=C/-
C/O=C/-
C/=C/-
C-=C/-
C/-
\IFDEF NZ_EXTRA_CAREOF
C-/=C/-
C/=C/-
C /-=C/-
C/O-=C/-
C / O=C/-
C / -=C/-
C - O=C/-
CO/=C/-
CO/-=C/-
CO=C/-
C|O=C/-
C/0=C/-
C/ O=C/-
C.O=C/-
C /O=C/-
C /=C/-
C/ 0=C/-
\ENDIF

\TABLE CornerTable
CNR
CORNER
CORNER OF
CRNR
CRN

\TABLE PluralStTypeTable
STREETS=ST
ROADS=RD
AVENUES=AVE
DRIVES=DR
STS=ST

# building types (1-with name before, 2-without)
\TABLE BuildingType1Table
APARTMENT
APARTMENTS
APPARTMENTS
APTS
ARCADE
ARC=ARCADE
BUILDING
BLDG=BUILDING
CENTRE
CNTR=CENTRE
CHAMBERS
CIAO
CLUB
COMPLEX
COURT
COURTS
CT=COURT
ESTATE
FARM
FLATS
GARDENS
GDNS=GARDENS
HALL
HOME
HOSTEL
HOTEL
HOUSE
LODGE
MALL
MEWS
MOTEL
PARK
PLACE
PL=PLACE
PLAZA
RANCH
RESORT
RESTAURANT
STATION
S C=SHOPPING CENTRE
SHOPPING TOWN
TOWER
TOWERS
TWRS=TWRS
UNITS
VILLAGE
VILLAS
#NZ specific
#POSTSHOP   - removed [Sep12]
#POSTCENTRE - removed [Sep12]
#added
SHOPS
TERRACES
HOSPITAL
# POINT - for DIAC

\TABLE BuildingType2Table
HOUSE
VILLAGE
GLEN
LODGE
RANCH
RESIDENCE
BRAE
MEWS
BLK
PRINCESS WHARF

\TABLE PostshopTable
POST CENTRE
POSTCENTRE
POST SHOP
POSTSHOP
PAPER PLUS
PAPERPLUS
TAKE NOTE
# [Oct14]
POSTAL DELIVERY CENTRE
PDC
P D C=PDC

\TABLE CounterTable
COUNTER DELIVERY

# common street names without street types [Nov09]
# (don't need to include "The Avenue" as Avenue is a street type)
\TABLE StreetNameNoTypeTable
BRAESIDE
BROADWAY
BROOKSIDE
ESPLANADE
GATEWAY
HIGHGATE
PARKWAY
THE GLEBE
THE RIDGEWAY
THE ROCKS
WESTRIDGE
WESTERN
WESTWARD HO

\TABLE CommonStreetTypeTable
ROAD
STREET
PLACE
AVENUE
DRIVE
LANE
CRESCENT
TERRACE
GROVE

\TABLE junkTable

\CONSTANTS
		# TODO include \v
	allPunctuation = " `~!@#$%^&*()-_+=\\|{}[]:'\";<>?,./\t\n\r\f"
		# TODO - why don't allow these punctuation marks?
	baseDelimiters = allPunctuation - "`~_\\|"
	numbers = "1234567890"
	baseDelimitersNumbers = numbers + baseDelimiters
	wordDelimiters = " \t.-&'/" - expectedDivider
		# street number cannot use dash, as it's used between street numbers
	streetNumDelimiters = baseDelimiters - "-"
		# appostrophe and dash used in names
	nameDelimiters = baseDelimiters - "'-"
		# /- used in care of
\IFDEF NZ_EXTRA_CAREOF
	careofDelimiters = baseDelimiters - "/-|."
\ELSE
	careofDelimiters = baseDelimiters - "/-" + numbers
\ENDIF
		#
	streetAddressDelimiters = baseDelimiters - expectedDivider - "%&<>"
	streetAddressDelimiters2 = streetAddressDelimiters - ",;" # non-dividing
		# cannot have names divided over two lines
	nonDividingDelimiters = baseDelimiters - expectedDivider - ",;"
		# these two are used in post box type names (eg. C/- P O)
	pbtypeDelimiters = baseDelimitersNumbers - "/-"
		# character sets
	letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	pbtypeCharset = letters + "/-"
		# error codes for iPaf32.dll
	errNoIPaf32 = "iPaf32 not found"
	errOpenPaf = "in opening PAF files"
	errGetDpid = "in looking up address"
		#
	s22Tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
		# what's allowed between unit number and its suffix
\IFDEF NZ_UNIT_SPACE_SUFFIX
	unitNoDelimiters = " "
\ELSE
	unitNoDelimiters = ""
\ENDIF

\IFNDEF NZ_SKIP_VALIDATION
\DLL iPaf32.dll				ONLOADERROR CONTINUE
	CallPafFromStan			NONZERO_ERROR TO iPafError

\IFDEF NZ_VALIDATE_CORRECTED
	\SUB_GRAMMARS
	NzValidate NzValidate.grm
\ENDIF

# ---------- name of ARF specified in grammar file
\IFDEF sARF_NAME

\GLOBAL_VARIABLES
sGlobalArfId
sGlobalArfId2

\INITIALIZE {
	#open the ARF to ensure that it stays open for the life time of the grammar
	sTemp = "OpenArf;Database=" + sARF_NAME
	sTemp = sTemp + ";"
	sGlobalArfId = CallPafFromStan(sTemp)
	# an error sets iPafError to non-zero or sGlobalArfId to "Error..."
	IF iPafError = 0
		sTemp = LEFT(sGlobalArfId, 5)
		IF sTemp = "Error"
			sGlobalArfId = ""
		END IF
	END IF

\IFDEF sARF_NAME2
	sTemp = "OpenArf;Database=" + sARF_NAME2
	sTemp = sTemp + ";"
	sGlobalArfId2 = CallPafFromStan(sTemp)
	# an error sets iPafError to non-zero or sGlobalArfId to "Error..."
	IF iPafError = 0
		sTemp = LEFT(sGlobalArfId2, 5)
		IF sTemp = "Error"
			sGlobalArfId2 = ""
		END IF
	END IF
\ENDIF #sARF_NAME2
}

\FINALIZE {
	IF sGlobalArfId <> ""
		sTemp = "CloseArf;Id=" + sGlobalArfId
		sTemp = sTemp + ";"
		CallPafFromStan(sTemp)
	END IF

\IFDEF sARF_NAME2
	IF sGlobalArfId2 <> ""
		sTemp = "CloseArf;Id=" + sGlobalArfId2
		sTemp = sTemp + ";"
		CallPafFromStan(sTemp)
	END IF
\ENDIF #sARF_NAME2
}

\ENDIF #sARF_NAME
# ----------

\ENDIF # NZ_SKIP_VALIDATION

\PRE_PARSE
{
\IFDEF NZ_REMOVE_PARENTHESIS
	# look for parentheses
	iPos = INSTR(INPUT, "(")
	IF iPos > 0
		iPos2 = INSTR(INPUT, ")", iPos)
		IF iPos2 > iPos
			# remove what's in parentheses
			iPos = iPos - 1
			iPos2 = iPos2 + 1
			sTemp = MID(INPUT, iPos2)
			INPUT = LEFT(INPUT, iPos)
			INPUT = INPUT & sTemp
		END IF
	END IF
\ENDIF
	
	INPUT = TRIM(INPUT, " \t,")	# [May10]

	# if the first word in the input is in the junkTable, remove it
\IFDEF NZ_REMOVE_JUNK
	iPos = INSTR(INPUT, " ")
	# is there a colon before first space?
	iPos2 = INSTR(INPUT, ":")
	IF iPos2 > 0
		IF iPos2 < iPos OR iPos = 0
			iPos = iPos2
		END IF
	END IF
	# get this first word
	iPos = iPos - 1
	sTemp = LEFT(INPUT, iPos)
	# is this word "junk"
	sTemp = LOOKUP(sTemp, junkTable)
	IF sTemp <> ""
		# remove this word
		iPos = iPos + 2
		INPUT = MID(INPUT, iPos)
		INPUT = TRIM(INPUT, " \t,")
	END IF
\ENDIF

}

\SUBROUTINE StreetName1or2
{
	# save, as second street will overwrite first
	IF bSecondStreet = 0
		StreetName_Save = StreetName_
		StreetType_Save	= StreetType_
		StreetSuffix_Save = StreetSuffix_
		sFullStreetName_Save = sFullStreetName
		sUserStName_Save = sUserStName
		sUserStType_Save = sUserStType
		sUserStSuf_Save = sUserStSuf
		bSecondStreet = 1
	# move this to second street, & get back saved first
	ELSE
		sStreet2Name = StreetName_
		sStreet2Type = StreetType_
		sFullStreetName2 = sFullStreetName
		#
		StreetName_ = StreetName_Save
		StreetType_ = StreetType_Save
		StreetSuffix_ = StreetSuffix_Save
		sFullStreetName = sFullStreetName_Save
		sUserStName = sUserStName_Save
		sUserStType = sUserStType_Save
		sUserStSuf = sUserStSuf_Save
		bSecondStreet = 2 # not used anymore
	END IF
}

\GRAMMAR
Word		: WORD2
			: "&" # some streets have "&" in them (eg. Reay & Watson Road)
Words2		: Word? Word Word Word DELIMITERS wordDelimiters
			: Word Word DELIMITERS wordDelimiters
Word2		: WORD2 SIZE 2 100
Words		: Words2
			: Word2 # don't allow single letter "words", eg street name [Jul13]
			: TABLE ordinals
# suburb, city, postcode
Nz			: TABLE NzTable TOLERANCE2 5
			{	Country_ = "NZ"	}
Region		: TABLE RegionTable ! DELIMITERS baseDelimiters TOLERANCE2 5 \
				INNER_DELIMITERS nonDividingDelimiters
City		: TABLE CityTable ! DELIMITERS baseDelimiters TOLERANCE2 5  \
				INNER_DELIMITERS nonDividingDelimiters
Suburb		: TABLE SuburbTable !  DELIMITERS baseDelimiters TOLERANCE2 5	\
				INNER_DELIMITERS nonDividingDelimiters
DistrictName: TABLE DistrictTable ! DELIMITERS nameDelimiters TOLERANCE2 5 \
				INNER_DELIMITERS nonDividingDelimiters # [Sep11]
DistrictWord: "DISTRICT" <>
			: "DIST" <>
District	: DistrictName(sDistrict) DistrictWord DELIMITERS " "
			{	sDistrict = sDistrict & "DISTRICT"	}
CityWord	: "CITY" <> # [Sep11]
City2		: City(sDummy sCity)
			{	IF State_ = ""
					State_ = sCity
				ELSE
					sLocality2 = sCity
				END IF
			}
			: City(sDummy sCity) CityWord(sTempCity)
			{	IF State_ = ""
					State_ = sCity & sTempCity
				ELSE
					sLocality2 = sCity & sTempCity
				END IF
			}
Pcode		: NUMBER_RANGE 101 9999 !
Pcodes		: Pcode(Pcode_)
			: Pcode(Pcode_) Pcode	# incase two postcodes in input
			{
				bFormatError = 1
			}
			: "0000" <> # [Mar11]
			{
				Pcode_ = ""
			}
# rural delivery			
RD			: TABLE RuralDeliveryTable ! DELIMITERS baseDelimitersNumbers
RDChar		: "C" <> DELIMITERS baseDelimitersNumbers
			: "D" <> DELIMITERS baseDelimitersNumbers
			: "H" <> DELIMITERS baseDelimitersNumbers
			: "K" <> DELIMITERS baseDelimitersNumbers
			: "O" <> DELIMITERS baseDelimitersNumbers
No			: "NO" <
Num			: NUMBER
Rural		: RD(sAbbr sUser) Num(sRdNumber) RDChar(sTempRD) \
				DELIMITERS streetAddressDelimiters2
			{	sRdNumber = sRdNumber + sTempRD
				IF sUser <> sAbbr
					bFormatError = 1
				END IF
			}
			: RD(sAbbr sUser) Num(sRdNumber) DELIMITERS streetAddressDelimiters2
			{	IF sUser <> sAbbr
					bFormatError = 1
				END IF
			}
			: RD(sAbbr sUser) RDChar(sRdNumber) DELIMITERS streetAddressDelimiters2
			{	AS_ABOVE	}
			: No? Num(sRdNumber) RDChar(sTempRD) RD(sAbbr sUser) \
				DELIMITERS streetAddressDelimiters2
			{	sRdNumber = sRdNumber + sTempRD
				IF sUser <> sAbbr
					bFormatError = 1
				END IF
			}
			: No? Num(sRdNumber) RD(sAbbr sUser) DELIMITERS streetAddressDelimiters2
			{	AS_ABOVE	}
			: No? RDChar(sTempRD) RD(sAbbr sUser) DELIMITERS streetAddressDelimiters2
			{	AS_ABOVE	}
LastLine
			\IFDEF NZ_LOOK_FOR_MULTIPLE_SUBURBS
			: Rural? District? City2? Suburb?(sDummy Locality_) Pcodes? \
				Suburb?(sDummy sSuburb2) City2? Nz? Region?(sRegion) \
				Suburb? Rural? ~ # look for double Rural
			\ELSE
			: Rural? District? City2? Suburb?(sDummy Locality_) Pcodes? \
				City2? Nz? Region?(sRegion) Rural? ~
			\ENDIF
			{
				# look for suburb after city
				i = ORDER_FOUND(3) #city
				j = ORDER_FOUND(4) #suburb
				IF i > 0
					IF j > i
						bFormatError = 1
					END IF
				END IF
				IF sSuburb2 <> ""
					Locality_ = sSuburb2
					bFormatError = 1
				END IF
				#
				IF Locality_ = ""
					Locality_ = sLocality2
					sLocality2 = ""
				END IF
				# convert SOUTH AUCKLAND region to auckland
				IF sRegion = "SOUTH AUCKLAND"
					IF State_ = ""
						IF Locality_ = ""
							State_ = "AUCKLAND"
							sRegion = ""
						END IF
					END IF
				END IF
			}
LastLine2	: Rural? Suburb?(sDummy Locality_) City(sDummy State_) Pcodes? Nz? \
				Region?(sRegion) Words(sSuburb2) Rural? ~01233300
			{	IF Locality_ = ""
					Locality_ = sSuburb2
				ELSE
					PostAddress_ = sSuburb2
				END IF
			}
			# to pick up unknown suburb or lobby; must also have city or pcode
LastLine3	: LastLine2
			: Rural? Suburb?(sDummy Locality_) Pcodes Nz? \
				Region?(sRegion) Words(sSuburb2) Rural? ~0133300
			{	IF Locality_ = ""
					Locality_ = sSuburb2
				ELSE
					PostAddress_ = sSuburb2
				END IF
			}
# postal
PostalType1	: TABLE PostalType1Table DELIMITERS pbtypeDelimiters
PostalType2	: TABLE PostalType2Table DELIMITERS baseDelimitersNumbers
PostalType3	: TABLE PostalType3Table DELIMITERS baseDelimitersNumbers
Char1		: WORD_SIZE_RANGE 1 1
PoNum		: Num(PostalNo_) Num?(sTempPoNum) DELIMITERS " -/" # PO Box 12 345
			{	IF sTempPoNum <> ""
					PostalNo_ = PostalNo_ + sTempPoNum
					bFormatError = 1
				END IF	}
			: Char1(PostalPrefix_) Num(PostalNo_) DELIMITERS ""
			: Num(PostalNo_) Char1?(PostalSuffix_) DELIMITERS "" # (Note: only 1 address in PAF with a suffix)
LobbyName	: TABLE BoxLobbyNamesTable
Postshop	: TABLE PostshopTable
PostalNum1	: PostalType1(PostalType_ sUser) PoNum DELIMITERS streetAddressDelimiters2
			{	IF sUser <> PostalType_
					bFormatError = 1
				END IF	}
			: PostalType3(PostalType_ sUser) PoNum DELIMITERS streetAddressDelimiters2 # [Apr10]
			{	IF sUser <> PostalType_
					bFormatError = 1
				END IF	}
PostalNum	: PostalNum1 Words(sLobbyName) Postshop(sPostshop) #[Apr10]
			{	sLobbyName = sLobbyName & sPostshop	}
			: PostalNum1 LobbyName?(sLobbyName)
			: PostalType3(PostalType_ sUser) PoNum DELIMITERS streetAddressDelimiters2
			{	AS_ABOVE	}
Postal		: PostalNum
			: PostalType2(PostalType_ sUser)
			{	AS_ABOVE	}
			: PostalType3(PostalType_ sUser)
			{	AS_ABOVE	}
# counter delivery
Counter		: TABLE CounterTable
CounterDeliv: Counter?(PostalType_) Words(BuildingName1_) Postshop(sPostshop)
			{	BuildingName1_ = BuildingName1_ & sPostshop	}
# street name
Corner		: TABLE CornerTable
StreetType	: TABLE StreetTypeTable  TOLERANCE2 6
StreetSuffix: TABLE StreetSuffixTable
StateHighway: TABLE StateHighwayTable  TOLERANCE2 5
SH			: "SH" <
Highway		: "HIGHWAY" <
NumStreet	: TABLE NumericStreetNamesTable DELIMITERS nameDelimiters
UnusualSt	: TABLE UnusualStreetNameTable DELIMITERS nameDelimiters
StreetNoType: TABLE StreetNameNoTypeTable DELIMITERS nameDelimiters
NumW		: Num
			: TABLE NumbersTable
StreetName	: SH NumW(sTempStName) Char1?(sTempStName2) \
				StateHighway(StreetName_ sUserStName) \
				DELIMITERS streetAddressDelimiters2
			{	sTempStName = "SH " + sTempStName	#[Nov08]
				sTempStName = sTempStName + sTempStName2
				StreetName_ = sTempStName & StreetName_
				sUserStName = sTempStName & sUserStName
				StreetType_ = "" # needed for StreetName1or2
				StreetName1or2() }
			: StateHighway(StreetName_ sUserStName) NumW(sTempStName) \
				Char1?(sTempStName2) StreetSuffix?(StreetSuffix_ sUserStSuf) \
				DELIMITERS streetAddressDelimiters2
			{	sTempStName = sTempStName + sTempStName2
				StreetName_ = StreetName_ & sTempStName
				sUserStName = sUserStName & sTempStName
				StreetType_ = "" # needed for StreetName1or2
				StreetName1or2() }
			: Words(StreetName_) StreetType(StreetType_ sUserStType) \
				StreetSuffix(StreetSuffix_ sUserStSuf) \
				DELIMITERS streetAddressDelimiters2
			{
				# Name="The" Type="Avenue" -> Name="The Avenue"
				IF StreetName_ = "THE"
					StreetName_ = StreetName_ & sUserStType
					StreetType_ = ""
					sUserStType = ""
				ELSE
					# create full street name lookup
					sFullStreetName = StreetName_ & sUserStType
					sFullStreetName = sFullStreetName & sUserStSuf
				END IF
				StreetName1or2()
			}
			# so "Main St Botany Bay" -> streetName="Main" not "Main St Botany"
			# but "Happy Hill Road" -> streetName="Happy Hill"
			: StreetType?(dummy sTempStName) \
				StreetType(StreetType_ sUserStType) Words(StreetName_) ~231 \
				DELIMITERS streetAddressDelimiters2
			{
				StreetName_ = StreetName_ & sTempStName
				# Name="The" Type="Avenue" -> Name="The Avenue"
				IF StreetName_ = "THE"
					StreetName_ = StreetName_ & sUserStType
					StreetType_ = ""
					sUserStType = ""
				ELSE
					# create full street name lookup
					sFullStreetName = StreetName_ & sUserStType
				END IF
				StreetName1or2()
			}
			# HIGHWAY 22 STATE HIGHWAY
			: Highway(sTempStName2) NumW(sTempStName) \
				StateHighway(StreetName_ sUserStName) \
				DELIMITERS streetAddressDelimiters2
			{	StreetName_ = sTempStName & StreetName_
				StreetName_ = sTempStName2 & StreetName_
				StreetName_ = sTempStName2 & sTempStName
				sUserStName = sTempStName & sUserStName
				sUserStName = sTempStName2 & sUserStName
				StreetType_ = "" # needed for StreetName1or2
				StreetName1or2() }
			: NumStreet(StreetName_ sUserStName) \
				StreetType?(StreetType_ sUserStType) \
				StreetSuffix?(StreetSuffix_ sUserStSuf) \
				DELIMITERS streetAddressDelimiters2
			{	sFullStreetName = StreetName_ & sUserStType
				sFullStreetName = sFullStreetName + sUserStSuf
				StreetName1or2() }
			: UnusualSt(StreetName_)
			{	StreetType_ = "" # needed for StreetName1or2
				StreetName1or2() }
			: StreetNoType(StreetName_) StreetSuffix?(StreetSuffix_ sUserStSuf)
			{	sFullStreetName = StreetName_ & sUserStSuf
				StreetType_ = "" # needed for StreetName1or2
				StreetName1or2() }
# unit
Char12		: WORD_SIZE_RANGE 1 2
Char123		: WORD_SIZE_RANGE 1 3
UnitNo		: Char1(FlatNo_) Num(sTempUnit1) Char1(sTempUnit2) DELIMITERS ""
			{
				FlatNo_ = FlatNo_ + sTempUnit1
				FlatNo_ = FlatNo_ + sTempUnit2
			}
			: Num(FlatNo_) Char1(sTempUnit1) Num(sTempUnit2) DELIMITERS ""
			{	AS_ABOVE	}
			: Char12(FlatNo_) Num(sTempUnit1) DELIMITERS ""
			{	FlatNo_ = FlatNo_ + sTempUnit1	}
			: Num(FlatNo_) Char1?(sTempUnit1) DELIMITERS unitNoDelimiters
			{	AS_ABOVE	}
			: Char123(FlatNo_)
Slash		: "/"
Hash		: "#"
UnitType	: TABLE UnitTypeTable CHAR_SET letters < # TOLERANCE1 6 <
Unit		: UnitType(FlatType_ sUserFlat) UnitNo
UnitSlash	: Unit Slash
			: UnitNo Slash
			: Hash UnitNo # [May13]
SureUnitType: TABLE SureUnitTypesTable CHAR_SET letters <
SureUnit	: SureUnitType(FlatType_ sUserFlat) UnitNo
# level
LevelNo		: NUMBER_RANGE 0 50 # zero is to pick up invalid level number
			: Char1
			: Char1 Num DELIMITERS ""
Ordinal2	: TABLE ordinals2
			: ORDINAL
LevelType1	: TABLE LevelType1Table CHAR_SET letters <
LevelType2	: TABLE LevelType2Table CHAR_SET letters <
LevelType3	: TABLE LevelType3Table CHAR_SET letters <
			# : $ "B" > # these two were removed from table, so picked up here
			# : $ "M" >
Level		: Ordinal2(LevelNo_) LevelType1(LevelType_ sUserLevel) \
				DELIMITERS streetAddressDelimiters2
			: LevelType1(LevelType_ sUserLevel) LevelNo(LevelNo_) \
				DELIMITERS streetAddressDelimiters2
			: LevelType2(LevelType_ sUserLevel) LevelNo(LevelNo_) \
				DELIMITERS streetAddressDelimiters2
			: LevelType3(LevelType_ sUserLevel) LevelNo?(LevelNo_) \
				DELIMITERS streetAddressDelimiters2
SureLvlType	: TABLE SureLevelTypesTable CHAR_SET letters <
SureLevel	: SureLvlType(LevelType_ sUserLevel) LevelNo(LevelNo_) \
				DELIMITERS streetAddressDelimiters2
# building name
Shed		: "SHED" <>
Wharf		: "WHARF" <>
BuildingType1: TABLE BuildingType1Table
BuildingType2: TABLE BuildingType2Table
Building	: Words BuildingType1
			{	iBuildingPos = TOKEN_POSITION(1)	}
			: Shed Num Words Wharf
			{	AS_ABOVE	}
			: Shed Num
			{	AS_ABOVE	}
			: BuildingType2
			{	AS_ABOVE	}
\IFDEF NZ_PARSE_BUILDING_NAME_IN_QUOTES
Quote		: "\"" #"
BuildingQ	: Quote Word2 Quote @ # allow anything between quotes. A bit dangerous
			{	BuildingName1_ = SUB_INPUT(1, -3)	}
\ENDIF
# street number
Dash		: "-"
LOT			: TABLE lot CHAR_SET letters <
Lot			: LOT Num(LotNo_) Char1?(sTempLot)
			{	LotNo_ = LotNo_ + sTempLot	}
			: LOT Char1(LotNo_)
NumChar1	: Num Char1? DELIMITERS ""
StreetNum	: Lot
			: NumChar1(HouseNo1_) Dash NumChar1(HouseNo2_) DELIMITERS " "
			{
				# remove house suffix from house number
				sTemp = RIGHT(HouseNo1_, 1)
				i = VAL(sTemp, -1)
				IF i < 0
					HouseSuffix1_ = sTemp
					i = LEN(HouseNo1_)
					i = i - 1
					HouseNo1_ = LEFT(HouseNo1_, i)
				END IF
				# remove house suffix from house number
				sTemp = RIGHT(HouseNo2_, 1)
				i = VAL(sTemp, -1)
				IF i < 0
					HouseSuffix2_ = sTemp
					i = LEN(HouseNo2_)
					i = i - 1
					HouseNo2_ = LEFT(HouseNo2_, i)
				END IF
			}
			: Num(HouseNo1_) Char1?(HouseSuffix1_) DELIMITERS ""
# address without suburb/city/postcode
FullStreetNum: Lot? Unit Level StreetNum ~ DELIMITERS streetNumDelimiters
			# "Lot?" added to pick up invalid address having both lot# & street#
			: Lot? Level UnitSlash? StreetNum DELIMITERS streetNumDelimiters
			: Lot? UnitSlash? StreetNum Level
			# to pick up invalid "Unit 1-5 main st" @@@
			: Lot? Unit Dash StreetNum
			{	bFormatError = 1	}
			# don't have "-" in delimiters, because "Unit 1-5 Main St"
			: Lot? Unit StreetNum ~ DELIMITERS streetNumDelimiters
			# don't have "-" in delimiters, because "C/- 5 Main St"
			: Lot? UnitSlash StreetNum DELIMITERS streetNumDelimiters
			#: Lot (moved to be part of StreetNum 29/6/00)
			# (also pick up invalid unit type without number [Oct07])
			: Lot? UnitType?(sTempFlat sTempUserFlat) No? StreetNum
			{
				IF sTempFlat <> ""
					FlatType_ = sTempFlat
					sUserFlat = sTempUserFlat
					bFormatError = 1
				END IF
			}
			# interpret "1 5 main st" as "1/5 main st"
\IFDEF NZ_UNIT_NUMBER_WITHOUT_SLASH
			: UnitNo StreetNum DELIMITERS " -"
			{	bFormatError = 1	}
\ENDIF
UnitOrLevel	: Level Unit? ~
			: Unit
			# delimiters to ensure streetNo and name on same address line
			# (no comma inbetween)
StNumAndName: FullStreetNum StreetName DELIMITERS streetAddressDelimiters2
			: Hash StreetNum StreetName DELIMITERS streetAddressDelimiters # [May13]
PluralStType: TABLE_SINGLE_WORDS PluralStTypeTable DELIMITERS nameDelimiters
AndAnd		: "&&"
And			: "AND" <>
			: AndAnd
			: "&"
StreetName2	: Corner(sCorner) StreetName And StreetName #[Jul11]
			{	bOtherError = 1	}
			: Corner(sCorner) Words(StreetName_) \
				StreetSuffix?(StreetSuffix_ sUserStSuf) And StreetName
			{	bOtherError = 1
				StreetType_ = "" # needed for StreetName1or2
				StreetName1or2() } # sStreet2Name = StreetName_
			: Corner(sCorner) Words(StreetName_) And Words(sStreet2Name) \
				PluralStType(StreetType_)
			{	bOtherError = 1
				sFullStreetName = StreetName_ & StreetType_
				sStreet2Type = StreetType_
				sFullStreetName2 = sStreet2Name & sStreet2Type }
			: StreetName AndAnd(sCorner) StreetName #[Mar14]
			{	bOtherError = 1	}
			: StreetName
# full address
StAddr		: UnitOrLevel Building?(BuildingName1_) FullStreetNum StreetName
			#: SureUnit SureLevel? Words2(BuildingName1_) FullStreetNum StreetName [Nov11] replaced by below
			: Unit SureLevel? Words(BuildingName1_) FullStreetNum StreetName
			: StNumAndName UnitOrLevel? Building?(BuildingName1_) ~
			: UnitOrLevel? Building?(BuildingName1_) StreetName2
			: UnitNo Building(BuildingName1_) StreetNum StreetName # [Mar10]
StAddrNoTyp : FullStreetNum Words(StreetName_) DELIMITERS " " #[Jun11]
StAddrNoType: Building?(BuildingName1_) Corner(sCorner) Words(StreetName_) # NH
			{	StreetName_ = sCorner & StreetName_	}
			: Building?(BuildingName1_) StAddrNoTyp UnitOrLevel? \
				DELIMITERS streetAddressDelimiters
StreetAddr	: StAddr
			: StAddrNoType
CareOf		: $ TABLE careof DELIMITERS careofDelimiters
			# ensure /- not delimiters
Tab			: "\t"
Name		: $ Words Tab
			{	PreAddress1_ = SUB_INPUT(0, 1)
				PreAddress1_ = TRIM(PreAddress1_, " \t\n,")	}
Full_addr	
\IFDEF NZ_PARSE_BUILDING_NAME_IN_QUOTES
			: $ BuildingQ LastLine(FoundFullLocality) $
\ENDIF
			: $ UnusualSt(StreetName_) FullStreetNum \
				LastLine?(FoundFullLocality) Name? $ ~3241
			: $ Name? CounterDeliv LastLine(FoundFullLocality) $
\IFDEF NZ_PARSE_BUILDING_NAME_IN_QUOTES
			: $ PostalNum? LastLine?(FoundFullLocality) \
				CareOf?(dummy PreAddress1_) StAddr? BuildingQ? Name? $ ~
\ELSE
			: $ PostalNum? LastLine?(FoundFullLocality) \
				CareOf?(dummy PreAddress1_) StAddr? Name? $ ~
\ENDIF
			{	# fix for name picked up as street in postal address [Nov11]
				# eg "TEDDY FORD, CMB 14164, WARRINGTON 9449"
				IF PostalNo_ <> ""
					IF StreetName_ <> ""
						IF HouseNo1_ = ""
							IF BuildingName1_ = ""
								IF FlatNo_ = ""
									IF LevelType_ = ""
										i = ORDER_FOUND(4) #4=StAddr
										IF i = 1
											sTemp = LOOKUP(StreetType_, \
												CommonStreetTypeTable)
											IF sTemp = ""
												PreAddress1_ = \
													SUB_INPUT_FOUND(-1, 1)
												StreetName_ = ""
												StreetType_ = ""
												StreetSuffix_ = ""
												sFullStreetName = ""
												sUserStName = ""
												sUserStType = ""
												sUserStSuf = ""
											END IF
										END IF
									END IF
								END IF
							END IF
						END IF
					END IF
				END IF
			}
			: $ PostalNum LastLine?(FoundFullLocality) \
				Building?(BuildingName1_) Name? $ ~2321
			# to pick up extra word(s) between suburb & city/pcode
			: $ CareOf?(dummy PreAddress1_) StAddr City?(sDummy State_) \
				Suburb(sDummy Locality_) Words(PostAddress_) Pcodes? \
				Name? $ ~0142340
			# don't want to pick up PostalNum and StAddrNoType,
			#	otherwise will fail on "PO BOX 123/456 Auckland City Auckland"
			: $ PostalNum? LastLine?(FoundFullLocality) \
				CareOf?(dummy PreAddress1_) $ ~
			# pick up unknown locality
			: $ StAddr LastLine3 $ # [Nov11]; moved up [Apr14]
			: $ LastLine?(FoundFullLocality) \
				CareOf?(dummy PreAddress1_) StAddrNoType? $ ~
			: StAddr? PostalNum LastLine(FoundFullLocality) $ # [Apr10]
			{
				sPreAddress = SUB_INPUT_FOUND(0, -1)
				sPreAddress = TRIM(sPreAddress, " \t\r\n,")
			}
			# LastLine2 will pick up unknown lobby name (ie. not a suburb name)
			: StAddr? PostalNum LastLine2(FoundFullLocality) $ # [Jun11]
			{
				sPreAddress = SUB_INPUT_FOUND(0, -1)
				sPreAddress = TRIM(sPreAddress, " \t\r\n,")
				sSaveLobby = Locality_
			}
			# TITOKI PDC TITOKI WHANGAREI 0101 [Oct14]
			: CounterDeliv LastLine(FoundFullLocality) Words(sLobbyName) $ ~132
			{
				sPreAddress = SUB_INPUT_FOUND(0, -1)
				sPreAddress = TRIM(sPreAddress, " \t\r\n,")
			}
			# PDC PAROA GREYMOUTH 7801 [Oct14]
			: LastLine(FoundFullLocality) Words(sLobbyName) \
				Postshop(BuildingName1_) $ ~321
			: Postal? LastLine?(FoundFullLocality) StreetAddr? \
				SureLevel? SureUnit? @ ~
		{	sTrim = " \t\n,"
			iPostalAddr = ORDER_FOUND(1)
			iLastLine = ORDER_FOUND(2)
			iStreetAddr = ORDER_FOUND(3)
			iSureUnit = ORDER_FOUND(5)
			# junk between unit and street address -> building name
			IF BuildingName1_ = ""
				i = iSureUnit + 1
				IF i = iStreetAddr
					BuildingName1_ = SUB_INPUT(5, -3) #5=SureUnit, 3=StreetAddr
					BuildingName1_ = TRIM(BuildingName1_, sTrim)
					IF BuildingName1_ <> ""
						bBuildingExtracted = 1
					END IF
				END IF
			END IF
			# junk between street address & last line -> suburb
			IF Locality_ = ""
				i = iStreetAddr + 1
				IF i = iLastLine
					sSuburbExtracted = SUB_INPUT(3, -2) #3=StreetAddr, 2=LastLine
					sSuburbExtracted = TRIM(sSuburbExtracted, " ")
					# only if on different line to street info
					sTemp = LEFT(sSuburbExtracted, 1)
					IF sTemp = "\t"
						sSuburbExtracted = TRIM(sSuburbExtracted, sTrim)
						# don't allow divider in suburb ("\t\n,")
						iPos = INSTRREV(sSuburbExtracted, "\t")
						iPos2 = INSTRREV(sSuburbExtracted, "\n")
						iPos3 = INSTRREV(sSuburbExtracted, ",")
						IF iPos3 > iPos
							iPos = iPos3
						END IF
						IF iPos2 > iPos
							iPos = iPos2
						END IF
						IF iPos > 0
							iPos = iPos + 1
							sSuburbExtracted = MID(sSuburbExtracted, iPos)
							sSuburbExtracted = TRIM(sSuburbExtracted , sTrim)
						END IF
						Locality_ = sSuburbExtracted
					ELSE
						sSuburbExtracted = ""
					END IF
				END IF
			END IF
			# junk between postal address & last line -> lobby (building)
			IF BuildingName1_ = ""
				i = iPostalAddr + 1
				IF i = iLastLine
					BuildingName1_ = SUB_INPUT(1, -2) #1=Postal, 2=LastLine
					BuildingName1_ = TRIM(BuildingName1_, sTrim)
					IF BuildingName1_ <> ""
						bBuildingExtracted = 1
					END IF
				END IF
			END IF
			# don't allow divider in building name ("\t\n,")
			IF bBuildingExtracted = 1
				iPos = INSTRREV(BuildingName1_, "\t")
				iPos2 = INSTRREV(BuildingName1_, "\n")
				iPos3 = INSTRREV(BuildingName1_, ",")
				IF iPos3 > iPos
					iPos = iPos3
				END IF
				IF iPos2 > iPos
					iPos = iPos2
				END IF
				IF iPos > 0
					iPos = iPos + 1
					BuildingName1_ = MID(BuildingName1_, iPos)
					BuildingName1_ = TRIM(BuildingName1_ , sTrim)
				END IF
			END IF
			#
			sPreAddress = SUB_INPUT_FOUND(0, -1)
			sPreAddress = RTRIM(sPreAddress, " \t\r\n,")
			#IF sCareof <> ""
			#	sTemp = SUB_INPUT_FOUND(1, -2)
			#	sTemp = LTRIM(sTemp, " :")
			#	sTemp = RTRIM (sTemp, sTrim)
			#	sCareof = sCareof & sTemp
			#ELSE
				PostAddress_ = SUB_INPUT_FOUND (1, -2)
				PostAddress_ = TRIM(PostAddress_, sTrim)
			#END IF
			# get extra info on line, not picked up
			sTemp = SUB_INPUT_FOUND(2, -3)
			sTemp = TRIM(sTemp, sTrim)
			PostAddress_ = PostAddress_ & sTemp
			sTemp = SUB_INPUT_FOUND(3, -4)
			sTemp = TRIM(sTemp, sTrim)
			PostAddress_ = PostAddress_ & sTemp
			sTemp = SUB_INPUT_FOUND(4, -5)
			sTemp = TRIM(sTemp, sTrim)
			PostAddress_ = PostAddress_ & sTemp
			sTemp = SUB_INPUT_FOUND(5)
			sTemp = TRIM(sTemp, sTrim)
			PostAddress_ = PostAddress_ & sTemp
			PostAddress_ = TRIM(PostAddress_, "\n\r\t ,")
			# remove from post address data already extracted
			#	(TODO: this may remove multiple occurrences)
			IF bBuildingExtracted = 1
				PostAddress_ = REMOVE(PostAddress_, BuildingName1_)
				PostAddress_ = TRIM(PostAddress_, sTrim)
			END IF
			IF sSuburbExtracted <> ""
				PostAddress_ = REMOVE(PostAddress_, sSuburbExtracted)
				PostAddress_ = TRIM(PostAddress_, sTrim)
			END IF
		}

\POST_PARSE {
	sDelim = "\t"
	PostAddress_ = PostAddress_ + sRegion

	# split pre address by carriage returns or tabs
	IF sPreAddress <> ""
		i = INSTR(sPreAddress, "\n")
		IF i <= 1
			i = INSTR(sPreAddress, "\t")
		END IF
		IF i <= 1
			PreAddress1_ = sPreAddress
		ELSE
			i = i - 1
			PreAddress1_ = LEFT(sPreAddress, i)
			i = i + 2
			PreAddress2_ = MID(sPreAddress, i)
		END IF
	END IF

	# lobby name may be city, suburb or building
	# (only really need this logic if BoxLobbyNamesTable is full)
	IF sLobbyName <> ""
		IF State_ = ""
			State_ = LOOKUP(sLobbyName, CityTable)
			IF State_ <> ""
				sLobbyName = ""
			END IF
		END IF
		IF sLobbyName <> ""
			IF Locality_ = ""
				Locality_ = LOOKUP(sLobbyName, SuburbTable)
				IF Locality_ <> ""
					sLobbyName = ""
				END IF
			END IF
			IF sLobbyName <> ""
				IF BuildingName1_ = ""
					BuildingName1_ = sLobbyName
				ELSE
					PostAddress_ = sLobbyName & PostAddress_
				END IF
			END IF
		END IF
	END IF
	# NZ POST error if both postal and street address
	IF PostalType_ <> ""
		IF StreetName_ <> ""
			bStreetAndPostalError = 1
			# fix for street name is really a person (eg. "MR FORD")
			IF HouseNo1_ = ""
				sTemp = LEFT(StreetName_, 3)
				IF StreetName_ = "MR"
					sTemp = "MRS "
				ELSEIF StreetName_ = "MS"
					sTemp = "MRS "
				ELSEIF StreetName_ = "MRS"
					sTemp = "MRS "
				ELSEIF sTemp = "MS "
					sTemp = "MRS "
				ELSEIF sTemp = "MR "
					sTemp = "MRS "
				ELSE
					sTemp = LEFT(StreetName_, 4)
				END IF
				IF sTemp = "MRS "
					PreAddress1_ = PreAddress1_ & StreetName_
					PreAddress1_ = PreAddress1_ & StreetType_
					PreAddress1_ = PreAddress1_ & StreetSuffix_
					StreetName_ = ""
					StreetType_ = ""
					StreetSuffix_ = ""
					bStreetAndPostalError = 0
					bRemovedStreet = 1
				END IF
			END IF
		END IF
	END IF

	# always use user's street name (TODO: improve effiiency above)
	IF sUserStName <> ""
		StreetName_ = sUserStName
	END IF

	# fix for range which is really unit (eg. 1-100 -> 1/100)
	IF HouseNo2_ <> ""
		IF FlatType_ = ""
			IF FlatNo_ = ""
				i = VAL(HouseNo1_)
				j = VAL(HouseNo2_)
				j = j - i
				\IFDEF NZ_RANGE_TO_UNIT_FIX_DIFF
					i = VAL(NZ_RANGE_TO_UNIT_FIX_DIFF)
				\ELSE
					i = 20 # default
				\ENDIF
				IF j > i
					FlatNo_ = HouseNo1_ + HouseSuffix1_
					HouseNo1_ = HouseNo2_
					HouseSuffix1_ = HouseSuffix2_
					HouseNo2_ = ""
					HouseSuffix2_ = ""
					bDashToSlash = 1
				END IF
			END IF
		END IF
	END IF

	# lookup address in NZ PAF
\IFNDEF NZ_SKIP_VALIDATION

	# save building name, as gets over-written
	sBuildingName = BuildingName1_
	sInputFlatType = FlatType_
	sInputFlatNo = FlatNo_
	sLocality = Locality_
	sInputCity = State_
	sInputPcode = Pcode_
 	sInputSuburb = Locality_
	sInputStreetName = StreetName_
	sInputStreetType = StreetType_
	sInputStreetSuffix = StreetSuffix_
	sInputRdNumber = sRdNumber
	IF HouseNo1_ = ""
		IF LotNo_ = ""
			sStreetName = StreetName_ & sUserStType
			sStreetName = sStreetName & sUserStSuf
		END IF
	END IF
	
	

	# see DpidGrammar.txt for discription of sFlag (512 = NZ specific)
	sFlag = ""
	# called by ValidateAddress (_NzAddress.grm)
	\IFDEF NZ_VALIDATE
		\IFDEF NZ_VALIDATE_LOOKUPFLAG
			sFlag = NZ_VALIDATE_LOOKUPFLAG
		\ELSEIF DEF LOOKUPFLAG
			sFlag = LOOKUPFLAG
		\ENDIF
	# not called by _NzAddress.grm
	\ELSEIF DEF NZ_LOOKUPFLAG
		sFlag = NZ_LOOKUPFLAG
	\ELSEIF DEF LOOKUPFLAG
		sFlag = LOOKUPFLAG
	\ENDIF
	# not set -> use default
	IF sFlag = ""
		i = 559 # 512 + 32 + 8 + 4 + 2 + 1
		\IFDEF KEEP_AUCKLAND_SUBURB
			sTemp = LOOKUP(State_, OldAucklandCitiesTable)
			IF sTemp = ""
				sTemp = LOOKUP(Locality_, OldAucklandCitiesTable)
			END IF
			IF sTemp <> ""
				i = i OR 128
			END IF
		\ENDIF
		sFlag = STR(i)
	END IF
	# parameter set to correct suburb
	\IFDEF PARAMETER_CorrectNzSuburb
		sTemp = UCASE(CorrectNzSuburb)
		IF sTemp = "TRUE"
			i = VAL(sFlag, 0)
			i = i AND NOT 12
			sFlag = STR(i)
		END IF
		# parameter with record format options
		i = VAL(paramRecordFormatOptions, -1)
		IF i >= 0
			sOtherOptions = sOtherOptions & "F"
			sOtherOptions = sOtherOptions + paramRecordFormatOptions
		END IF
		# address filter
		IF paramAddressFilter = "Postal"
			StreetName_ = ""
			StreetType_ = ""
			StreetSuffix_ = ""
			HouseNo1_ = ""
			HouseSuffix1_ = ""
			HouseNo2_ = ""
			HouseSuffix2_ = ""
			FlatType_ = ""
			FlatNo_ = ""
			LevelType_ = ""
			LevelNo_ = ""
			BuildingName1_ = ""
			BuildingName2_ = ""
			LotNo_ = ""
		ELSEIF paramAddressFilter = "Streets"
			PostalType_ = ""
			PostalNo_ = ""
			PostalPrefix_ = ""
			PostalSuffix_ = ""
		END IF
	\ENDIF
	
	# prepare input for iPaf32.GetDpid
	sFullPaf = JOIN(State_, 22, sDelim)
	sFullPafForFormat = sFullPaf
	sTemp = JOIN(ExtraInputs, 9, sDelim)
	sFullPaf = sFullPaf + sTemp
	
	# open the required ARF
	sTemp = "OpenArf;Database="
	sTemp = sTemp + sDatabase
	sTemp = sTemp + ";"
	iPafError = 0
	sId = CallPafFromStan(sTemp)
	sTemp = LEFT(sId, 5)
	# check for error
	IF iPafError <> 0
		sPafError = STR(iPafError)
		sPafError = "Opening ARF error: " + sPafError
	ELSEIF sTemp = "Error"
		sPafError = sId
	ELSE
		sId = "Id=" + sId
		sId = sId + ";"

		# tell iPaf32 which GCs we want
		IF sGIFields <> ""
			sTemp = "SetGeographicalCodes;" + sId
			sTemp = sTemp + sGIFields
			sTemp = CallPafFromStan(sTemp)
			IF iPafError <> 0
				sPafError = STR(iPafError)
				sPafError = "SetGeographicalCodes error: " + sPafError
			END IF
		END IF

		# set name of Old Postcode File
		IF sOldPostcodeGif <> ""
			sTemp = "SetOldPostcodeGif;" + sId
			sTemp = sTemp + sOldPostcodeGif
			sTemp = CallPafFromStan(sTemp)
			IF iPafError <> 0
				sPafError = STR(iPafError)
				sPafError = "SetOldPostcodeGif error: " + sPafError
				sPafError = sPafError & sTemp
			END IF
		END IF

		# tell iPaf32 which POIs we want
		\IFDEF NZ_POI
			IF sPOI <> ""
				sTemp = "SetPointsOfInterest;" + sId
				sTemp = sTemp + sPOI
				sTemp = CallPafFromStan(sTemp)
				IF iPafError <> 0
					sPafError = STR(iPafError)
					sPafError = "SetPointsOfInterest error: " + sPafError
				END IF
			END IF
		\ENDIF

		# lookup address with this ARF
		sTemp = "LookupAddress;" + sId
		sTemp = sTemp + "Lenient=True;"
		sFullPaf = sTemp + sFullPaf
		sFullPaf = CallPafFromStan(sFullPaf)
		IF iPafError <> 0
			sPafError = STR(iPafError)
			sPafError = "Address lookup error: " + sPafError
		ELSE
			# address found - some info in first 22 fields (till PP Flag)
			sTemp = LEFT(sFullPaf, 22)
			IF sTemp <> s22Tabs
				sFullPafForFormat = sFullPaf
			END IF
			# format address (options: 2=NoLocality, 4=ExpandFlatLevelAbbr
			#	16=ExpandStreetAbbr, 32=Uppercase, 256=NoBuilding)
			#	512=AlwaysHaveUnitType (if there is a unit number)
			#	1024=NoLotIfHaveStreetNumber, 4096=QuoteBuilding
			i = 2
			\IFNDEF NZ_ABBREVIATE_TYPES
				i = i + 20 # 16 + 4
			\ENDIF
			\IFDEF NZ_PARSE_BUILDING_NAME_IN_QUOTES
				i = i + 4096
			\ENDIF
			sTemp = STR(i)
			sTemp = "Options=" + sTemp
			sTemp = sTemp + ";"
			sTemp = sId + sTemp
			sTemp = "FormatAddress;" + sTemp
			sTemp = sTemp + sFullPafForFormat
			sTemp = CallPafFromStan(sTemp)
			sTemp = STRIP(sTemp, "\t")
			Address1_ = SPLIT(sTemp, 3, "\n")
		END IF
		# close ARF
		sTemp = "CloseArf;" + sId
		sTemp = CallPafFromStan(sTemp)
	END IF

	# error
	IF sPafError <> ""
		Flag_ = "E"
	ELSE
		sTemp = LEFT(sFullPaf, 1)
		# there is a returned address
		IF sTemp <> sDelim
			State_ = SPLIT(sFullPaf, 57, sDelim)
			bDllReturnedAddress = 1 # true
		ELSE
			# get reason for no match (fields 34 & 35)
			# and other fields (mainly GIF: fields 43-52)
			i = 1
			FOR j = 1 TO 33
				i = INSTR(sFullPaf, sDelim, i)
				i = i + 1
			NEXT
			sTemp = MID(sFullPaf, i)
			Flag_ = SPLIT(sTemp, 19, sDelim)
		END IF
	END IF

	# use input flat type, if no flat type in PAF (@@@ optional)
	IF FlatNo_ <> ""
		IF FlatType_ = ""
			IF FlatNo_ = sInputFlatNo
				FlatType_ = sInputFlatType
			END IF
		END IF
	END IF

	# what we thought was a lobby name is really post address info [Jul11]
	# (fix for LastLine2)
	IF sSaveLobby <> ""
		IF bDllReturnedAddress = 1
			iPos = INSTR(AmendedFlag_, "c") # 6=suburb
			IF iPos > 0
				PostAddress_ = PostAddress_ & sSaveLobby
				# remove "amended suburb" flag
				iPos = iPos + 1
				sTemp = MID(AmendedFlag_, iPos)
				iPos = iPos - 2
				AmendedFlag_ = LEFT(AmendedFlag_, iPos)
				AmendedFlag_ = AmendedFlag_ + sTemp
			END IF
		ELSEIF Locality_ = sSaveLobby
			PostAddress_ = PostAddress_ & sSaveLobby
			Locality_ = ""
		END IF
	END IF

	# Locality field may contain Lobby or RD number instead of Suburb [May09]
	#	move it to where appropriate
	IF bDllReturnedAddress = 1
		IF Locality_ <> ""
			# begins with "RD " -> Rural Delivery number
			sTemp = LEFT(Locality_, 3)
			IF sTemp = "RD "
				sRdNumberLookedUp = MID(Locality_, 4)
				Locality_ = ""
				# RD overwritten by value in building field (for Oamaru)
				sTemp = LEFT(BuildingName1_, 3)
				IF sTemp = "RD "
					sRdNumberLookedUp = MID(BuildingName1_, 4)
					BuildingName1_ = ""
				END IF
			# postal address -> lobby name
			ELSEIF PostalType_ <> ""
				\IFDEF NZ_LOBBY_IN_LOCALITY_FIELD # see note below
					bLobbyInLocalityField = 1
				\ELSE
					IF BuildingName1_ = ""
						BuildingName1_ = Locality_
					END IF
					sLobby = Locality_
					Locality_ = ""
				\ENDIF
			END IF
		END IF
	END IF

	# Note: When parsing, lobby is place into the Building field.
	#	If the DLL finds an address, it will move lobby into Locality field.
	#	We then have a grammar file option NZ_LOBBY_IN_LOCALITY_FIELD
	#	whether to leave it in Locality or put it back into Building field.
	
	# postal address -> lobby name checks
	IF PostalType_ <> ""
		IF bLobbyInLocalityField = 1
			sLobbyTemp = Locality_
		ELSE
			sLobbyTemp = BuildingName1_
		END IF
		IF sLobbyTemp <> ""
			# input box lobby name in PostAddress or input building name
			IF PostAddress_ = sLobbyTemp
				PostAddress_ = ""
			ELSEIF sBuildingName = sLobbyTemp
			# lobby name parsed as street name -> ok
			ELSEIF sStreetName = sLobbyTemp
				bStreetAndPostalError = 0
			# lobby name same as city -> ok
			ELSEIF State_ = sLobbyTemp
			# lobby name parsed as locality name -> ok
			ELSEIF sLocality = sLobbyTemp
			# incorrect or not provided lobby name -> not format error
			ELSE
				i = INSTR(AmendedFlag_, "6") # 6=lobby name error [Mar09]
				IF i = 0
					# lobby name only partially picked up and then corrected
					i = INSTR(sLobbyTemp, sBuildingName)
					IF i = 1
						sBuildingName = ""
					# format error
					ELSE
						bFormatError = 1 # TODO? different flag?
					END IF
				END IF
			END IF
		END IF
	ELSE
		# building name was in post address
		IF PostAddress_ = BuildingName1_
			PostAddress_ = ""
		END IF
	END IF
	# input building name, which is not output building name
	# (only do this if don't have 16 (hex 10) in sFlag)
	IF sBuildingName <> BuildingName1_ AND sBuildingName <> sLobbyTemp
		IF AmendedFlag_ <> "z" # matched to point of interest
			# if building name at beginning, put in in pre address instead
			IF iBuildingPos = 1
				PreAddress1_ = sBuildingName & PreAddress1_
			ELSE
				PostAddress_ = sBuildingName & PostAddress_
			END IF
		END IF
	# postal and building name (not lobby name) -> move building to pre [Apr10]
	ELSEIF PostalType_ <> ""
		IF BuildingName1_ <> ""
			IF bDllReturnedAddress = 0 #else building may be lobby name
				IF iBuildingPos = 1
					PreAddress1_ = BuildingName1_ & PreAddress1_
				ELSE
					PostAddress_ = BuildingName1_ & PostAddress_
				END IF
				BuildingName1_ = ""
			END IF
		END IF
	END IF

# if pre address is building name -> remove it
	IF BuildingName1_ <> ""
		IF PreAddress1_ <> ""
			sTemp = BuildingName1_ & BuildingName2_
			# pre2
			IF PreAddress2_ <> ""
				# pre2
				i = INSTR(sTemp, PreAddress2_)
				IF i > 0
					PreAddress2_ = ""
				END IF
			END IF
			# pre1
			i = INSTR(sTemp, PreAddress1_)
			IF i > 0
				PreAddress1_ = PreAddress2_
				PreAddress2_ = ""
			END IF
			# (modification 24/1/05) - building name in pre address
			IF PreAddress1_ <> ""
				IF PostalType_ = "" # not a lobby name [Feb10]
					i = INSTR(PreAddress1_, sTemp)
					IF i > 0
						BuildingName1_ = ""
						BuildingName2_ = ""
					END IF
				END IF
			END IF
		END IF
	END IF

# (6/9/04:) remove repeated Locality, State and Postcode from post address
	IF PostAddress_ <> ""
		IF PostAddress_ = Pcode_
			PostAddress_ = ""
			bFormatError = 1
		ELSEIF PostAddress_ = State_
			PostAddress_ = ""
			bFormatError = 1
		ELSEIF PostAddress_ = Locality_
			PostAddress_ = ""
			bFormatError = 1
		END IF
	END IF

	# DLL returned RD number
	IF sRdNumberLookedUp <> ""
		bDoRD = 1
	ELSE
		# RD number in GIF field
		\IFDEF NZ_RD_NUMBER_GIF_FIELD
			bDoRD = 1
			IF NZ_RD_NUMBER_GIF_FIELD = "5"
				sRdNumberLookedUp = GIField5
			ELSEIF NZ_RD_NUMBER_GIF_FIELD = "1"
				sRdNumberLookedUp = GIField1
			ELSEIF NZ_RD_NUMBER_GIF_FIELD = "2"
				sRdNumberLookedUp = GIField2
			ELSEIF NZ_RD_NUMBER_GIF_FIELD = "3"
				sRdNumberLookedUp = GIField3
			ELSEIF NZ_RD_NUMBER_GIF_FIELD = "4"
				sRdNumberLookedUp = GIField4
			# work out which field is the RD_NUMBER field
			ELSEIF NZ_RD_NUMBER_GIF_FIELD = "?"
				iPos = INSTR(sGIFields, "RD_NUMBER")
				IF iPos = 0
					bDoRD = 0
				ELSE
					# count commas and pluses to work out which field it is
					j = 1
					FOR i = 1 TO iPos
						sTemp = MID(sGIFields, i, 1)
						IF sTemp = ","
							j = j + 1
						ELSEIF sTemp = "+"
							j = j + 1
						END IF
					NEXT
					# now know which field number it is
					IF j = 1
						sRdNumberLookedUp = GIField1
					ELSEIF j = 2
						sRdNumberLookedUp = GIField2
					ELSEIF j = 3
						sRdNumberLookedUp = GIField3
					ELSEIF j = 4
						sRdNumberLookedUp = GIField4
					ELSEIF j = 5
						sRdNumberLookedUp = GIField5
					ELSEIF j = 6
						sRdNumberLookedUp = GIField6
					ELSEIF j = 7
						sRdNumberLookedUp = GIField7
					ELSEIF j = 8
						sRdNumberLookedUp = GIField8
					ELSEIF j = 9
						sRdNumberLookedUp = GIField9
					ELSEIF j = 10
						sRdNumberLookedUp = GIField10
					ELSEIF j = 11
						sRdNumberLookedUp = GIField11
					ELSEIF j = 12
						sRdNumberLookedUp = GIField12
					ELSEIF j = 13
						sRdNumberLookedUp = GIField13
					ELSEIF j = 14
						sRdNumberLookedUp = GIField14
					ELSEIF j = 15
						sRdNumberLookedUp = GIField15
					END IF
				END IF
			END IF
		\ENDIF
	END IF
# validate the RD number
	IF bDoRD = 1
		iPos = INSTR(AmendedFlag_, "5")
		IF sRdNumber <> sRdNumberLookedUp
			iFlag = VAL(Flag_, -1)
			IF iFlag >= 0
				IF iPos = 0
					AmendedFlag_ = AmendedFlag_ + "5" # RD number
				END IF
				sRdNumber = sRdNumberLookedUp
				iFlag = iFlag OR 4 # amended
				Flag_ = STR(iFlag)
			ELSEIF Flag_ = "Z"
				IF iPos = 0
					AmendedFlag_ = AmendedFlag_ + "5" # RD number
				END IF
			END IF
		END IF
	END IF

# place the RD number in the address lines
	IF sRdNumber <> ""
		\IFDEF NZ_RD_IN_LOCALITY_FIELD
		IF Locality_ = ""
			Locality_ = "RD " + sRdNumber
		ELSE
		\ENDIF
			IF Address1_ = ""
				Address1_ = "RD " + sRdNumber
			ELSEIF Address2_ = ""
				Address2_ = "RD " + sRdNumber
			ELSEIF Address3_ = ""
				Address3_ = "RD " + sRdNumber
			ELSE
				Address3_ = Address3_ + ", RD "
				Address3_ = Address3_ + sRdNumber
			END IF
		\IFDEF NZ_RD_IN_LOCALITY_FIELD
		END IF
		\ENDIF
	END IF
# place the Lobby name in address lines [May10]
# (The lobby name was in the Locality field when FormatAddress was called,
#	so it didn't get into the address lines. Then it was removed from the
#	Locality field and placed in the building field.
#	If NZ_LOBBY_IN_LOCALITY_FIELD, then it wasn't moved, so this is not needed)
	\IFNDEF NZ_LOBBY_IN_LOCALITY_FIELD
		IF sLobby <> ""
			IF Address1_ = ""
				Address1_ = sLobby
			ELSEIF Address2_ = ""	# most likely
				Address2_ = sLobby
			ELSEIF Address3_ = ""
				Address3_ = sLobby
			ELSE
				Address3_ = Address3_ + ", "
				Address3_ = Address3_ + sLobby
			END IF
		END IF
	\ENDIF

# extract ExtraLevel flag (%)
	i = INSTR(AmendedFlag_, "%")
	IF i > 0
		bExtraLevel = 1 # True
		i = i + 1
		sTemp = MID(AmendedFlag_, i)
		i = i - 2
		AmendedFlag_ = LEFT(AmendedFlag_, i)
		AmendedFlag_ = AmendedFlag_ + sTemp
	END IF

# amendments made to the address (not allowed by NZ Post) ?
	IF AmendedFlag_ <> ""
		IF PostalNo_ = ""
			sTemp = RTRIM(AmendedFlag_, "abcdx8 ") #allow suburb (a,b,c,d) errors
		ELSE
			sTemp = RTRIM(AmendedFlag_, "adx8 ") #suburb error is lobby error
		END IF
		IF sTemp <> ""
			bAmended = 1
		END IF
	END IF

# cannot have a level on a rural address
	IF sRdNumber <> ""
		IF LevelType_ <> ""
			bOtherError = 1
		END IF
	END IF

# cannot have a unit type without a number
	IF FlatType_ <> ""
		IF FlatNo_ = ""
			bOtherError = 1
		END IF
	END IF

# amended suburb is not a NZ error
	iFlag = VAL(Flag_, 0)
	i = iFlag AND 4 # amended
	IF i <> 0
		# no other errors besides suburb (abc8) and alternate street (x)
		# (from PafEngine 202, suburb spelling corrected, so include b [May11])
		sTemp = "abcx8 "
		# Rural address & incorrect suburb -> means address has RD & Suburb, which is invalid
		IF sRdNumber <> ""
			sTemp = "abx8 "
		END IF
		sTemp = RTRIM(AmendedFlag_, sTemp)
		IF sTemp = ""
			# temporarily remove amended flag
			sSaveFlag = Flag_
			iFlag = iFlag AND NOT 4
			Flag_ = STR(iFlag)
		END IF
	END IF

	# flag dash to slash
	IF bDashToSlash = 1
		AmendedFlag_ = AmendedFlag_ + "v" # v=Dash changed to Slash
		IF Flag_ = "Z"
			bFormatError = 1
		ELSE
			iFlag = VAL(Flag_, -1)
			IF iFlag >= 0
				iFlag = iFlag OR 4 # amended
				Flag_ = STR(iFlag)
			END IF
		END IF
	END IF

# unit type without number before address
	sTemp = LOOKUP(PreAddress2_, UnitTypeTable)
	IF sTemp <> ""
		bOtherError = 1
	ELSE
		sTemp = LOOKUP(PreAddress1_, UnitTypeTable)
		IF sTemp <> ""
			bOtherError = 1
		END IF
	END IF

# Invalid input street type [Nov11]
	IF StreetType_ <> ""
		sTemp = LOOKUP(sUserStType, InvalidStreetTypeTable)
		IF sTemp <> ""
			bFormatError = 1
		END IF
	END IF

# NZ Post validity flag

	# convert flag to number
	iFlag = VAL(Flag_, -1)
	IF iFlag >= 0
		# error flags 2 (didn't amend) and 64 (additional sub addresses exist)
		#  do not affect the validity flag, so remove them [Feb10]
		iFlag = iFlag AND NOT 66
	END IF

	# other error picked up above -> invalid
	IF bOtherError <> 0
		NzPostValidFlag_ = "INVALID"
	# address contains both street and postal address info
	ELSEIF bStreetAndPostalError <> 0
		NzPostValidFlag_ = "INVALID"
	# address needed to be modified -> invalid
	ELSEIF bAmended <> 0
		NzPostValidFlag_ = "INVALID"
	# format error
	ELSEIF bFormatError <> 0
		AmendedFlag_ = AmendedFlag_ + "4" # 4=amended format
		NzPostValidFlag_ = "INVALID"
	# other info in address -> invalid
	ELSEIF PostAddress_ <> ""
		NzPostValidFlag_ = "INVALID"
	# valid
	ELSEIF iFlag = 0
		NzPostValidFlag_ = "VALID_U"
	# match to primary point (base address in NZ terminology)
	ELSEIF iFlag = 1
		NzPostValidFlag_ = "VALID_B"
	ELSEIF Flag_ = "Z"
		NzPostValidFlag_ = "VALID_B"
	ELSEIF Flag_ = "16"	# matched to rural street
		IF HouseNo2_ = ""
			NzPostValidFlag_ = "VALID_B"
		ELSE
			NzPostValidFlag_ = "INVALID"	# range address -> invalid
		END IF
	ELSE
		NzPostValidFlag_ = "INVALID"
	END IF

	# put back flag
	IF sSaveFlag <> ""
		Flag_ = sSaveFlag
	END IF

# put back suburb in post address
	IF sSuburbExtracted <> ""
		IF sSuburbExtracted <> Locality_
			PostAddress_ = PostAddress_ + sSuburbExtracted
			PostAddress_ = TCASE(PostAddress_)
		END IF
	END IF
	PostAddress_ = PostAddress_ & sDistrict # TODO? here or with sRegion?

# mark extra level as a PP match (w/o flagging it INVALID)
	IF bExtraLevel = 1
		iFlag = VAL(Flag_, -1)
		IF iFlag >= 0
			iFlag = iFlag OR 1 # primary point match
			Flag_ = STR(iFlag)
		END IF
	END IF

# convert pre/post address to Title Case
	PreAddress1_ = TCASE(PreAddress1_)
	PreAddress2_ = TCASE(PreAddress2_)
	PostAddress_ = TCASE(PostAddress_)

# validate the new corrected address
\IFDEF NZ_VALIDATE_CORRECTED
	IF NzPostValidFlag_ = "INVALID"
		# this is not an error for NZ
		IF Flag_ = "Z"
			iFlag = 0
		ELSE
			iFlag = VAL(Flag_, -1)
		END IF
		# we were able to correct the address -> try second pass
		IF iFlag >= 0
			sTemp = "ARF=" + sDatabase
			IF sGIFields <> ""
				sTemp = sTemp + ";GIF="
				sTemp = sTemp + sGIFields
			END IF
			sTemp = sTemp + ";"
			sTemp = sTemp + Address1_
			sTemp = sTemp + "\t"
			sTemp = sTemp + Address2_
			sTemp = sTemp + "\t"
			sTemp = sTemp + Address3_
			sTemp = sTemp + "\t"
			sTemp = sTemp + Locality_
			sTemp = sTemp & State_
			sTemp = sTemp & Pcode_
			CorrectedValidFlag_ = NzValidate(sTemp, 1)
			IF CorrectedValidFlag_ = "INVALID"
				CorrectedValidFlag_ = ""
			END IF
		END IF
	END IF
\ENDIF # NZ_VALIDATE_CORRECTED

	# Split flag 6 into 4 & 2 [Jan11]
	sFlagTemp = Flag_
	sAmendFlag1 = AmendedFlag_
	iFlag = VAL(Flag_, -1)
	i = iFlag AND 6
	IF i = 6
		# from paf v187, there's a space between items amended and those not
		i = INSTR(AmendedFlag_, " ")
		IF i > 0
			i = i - 1
			sAmendFlag1 = LEFT(AmendedFlag_, i)
			i = i + 2
			sAmendFlag2 = MID(AmendedFlag_, i)
			iFlag = iFlag AND NOT 2 # remove flag 2
			sFlagTemp = STR(iFlag)
		END IF
	END IF
	
	# calculate flag string (before [Jan11] was done in NzAddress.grm)
	FlagString_ = LOOKUP(sFlagTemp, flagTable)
	# change message for flag Q (ambiguous street for this locality) [Jan11]
	IF Flag_ = "Q"
		IF PostalType_ <> ""
			FlagString_ = "ambiguous lobby"
		ELSE
			FlagString_ = "ambiguous street"
		END IF
	END IF

	IF Flag_ = "E"
		FlagString_ = FlagString_ & sPafError
	# amended code
	ELSE
		s2 = ""
		WHILE sAmendFlag1 <> ""
			# not first one -> add a comma
			IF s2 <> ""
				FlagString_ = FlagString_ + ","
			END IF
			#
			s2 = LEFT(sAmendFlag1, 1)
			sAmendFlag1 = MID(sAmendFlag1, 2)
			sTemp = LOOKUP(s2, amendedFlagTable)
			FlagString_ = FlagString_ & sTemp
		WEND
		# matched to Point Of Interest POI (dll returns a group match)
		IF Flag_ = "20" AND AmendedFlag_ = "z"
			FlagString_ = "matched to point of interest"
		END IF

		# items not amended
		IF sAmendFlag2 <> ""
			FlagString_ = FlagString_ + ", didn't amend"
			s2 = ""
			WHILE sAmendFlag2 <> ""
				# not first one -> add a comma
				IF s2 <> ""
					FlagString_ = FlagString_ + ","
				END IF
				#
				s2 = LEFT(sAmendFlag2, 1)
				sAmendFlag2 = MID(sAmendFlag2, 2)
				sTemp = LOOKUP(s2, amendedFlagTable)
				FlagString_ = FlagString_ & sTemp
			WEND
		END IF
	END IF

	# remove lobby name (from suburb field) if same as city name
	\IFDEF NZ_LOBBY_IN_LOCALITY_FIELD
		\IFDEF SKIP_THIS_NOW # [Nov14]. Was initially introduced in Sep12
		IF PostalType_ <> ""
			IF State_ = Locality_
				Locality_ = ""
			END IF
		END IF
		\ENDIF
	\ENDIF

\ENDIF # NZ_SKIP_VALIDATION

	\IFDEF NZ_ABBREVIATE_TYPES
		sTemp = LOOKUP(StreetType_, AbbreviateStreetTypeTable)
		IF sTemp <> ""
			StreetType_ = sTemp
		END IF
		sTemp = LOOKUP(StreetSuffix_, AbbreviateStreetSuffixTable)
		IF sTemp <> ""
			StreetSuffix_ = sTemp
		END IF
		sTemp = LOOKUP(FlatType_, AbbreviateFlatTable)
		IF sTemp <> ""
			FlatType_ = sTemp
		END IF
		sTemp = LOOKUP(LevelType_, AbbreviateLevelTable)
		IF sTemp <> ""
			LevelType_ = sTemp
		END IF
	\ENDIF
