
	SUBROUTINE PARSE( LINE , BLANK , QUOTE , SEPARATORS ,
     1   DIMPNTR , PNTR , WORDLENGTH , NUMWORDS , ERROR )


	CHARACTER*(*) LINE, SEPARATORS, BLANK, QUOTE

	INTEGER*2 DIMPNTR ,
     1   PNTR( 2 , DIMPNTR ) , WORDLENGTH( DIMPNTR ) , NUMWORDS ,
     1   STATE , INDEX , LNTH , ERROR, IB, IQ

	LOGICAL*1 NONSEP

	INTEGER*2 LENGTH


C
CC--
CC Variable initialization
CC--

	ERROR = 0
	INDEX = 1
	NUMWORDS = 0

	LNTH = LENGTH( LINE )

	IF( LNTH .EQ. 0 .OR. DIMPNTR .EQ. 0 ) THEN
	  STATE = -1
	ELSE
	  STATE = 0
	END IF

C
CC--
CC Main routine
CC--

C	DO WHILE( STATE .GE. 0 )
100	IF( STATE .GE. 0 ) GOTO 200
	GOTO 1000

200	CONTINUE

	  IF( STATE .EQ. 0 ) THEN

	    DO 210 IB = 1 , LEN(BLANK)
	      IF( LINE(INDEX:INDEX) .EQ. BLANK(IB:IB) ) THEN
	        STATE = 2
	        GOTO 250
	      END IF
210	    CONTINUE

	    DO 220 IQ = 1 , LEN(QUOTE)
	      IF( LINE(INDEX:INDEX) .EQ. QUOTE(IQ:IQ) ) THEN
	        STATE = 11
	        GOTO 250
	      END IF
220	    CONTINUE

	    IF(NONSEP(LINE(INDEX:INDEX),SEPARATORS)) THEN
	      STATE = 3
	    ELSE
	      STATE = 1
	    END IF

250	    CONTINUE

	  ELSE IF( STATE .EQ. 1 ) THEN
	    CALL SETNEXT1STPNTR( INDEX , NUMWORDS , DIMPNTR , PNTR )
	    CALL SET2NDPNTR( INDEX , NUMWORDS , DIMPNTR , PNTR ,
     1     WORDLENGTH )
	    STATE = 9

	  ELSE IF( STATE .EQ. 2 ) THEN
	    INDEX = INDEX + 1
	    IF( INDEX .GT. LNTH ) THEN
	      STATE = -1
	    ELSE
	      STATE = 0
	    END IF

	  ELSE IF( STATE .EQ. 3 ) THEN
	    CALL SETNEXT1STPNTR( INDEX , NUMWORDS , DIMPNTR , PNTR )
	    STATE = 4

	  ELSE IF( STATE .EQ. 4 ) THEN
	    INDEX = INDEX + 1
	    IF( INDEX .GT. LNTH ) THEN
	      STATE = 5
	    ELSE
	      STATE = 6
	    END IF

	  ELSE IF( STATE .EQ. 5 ) THEN
	    CALL SET2NDPNTR( INDEX-1 , NUMWORDS , DIMPNTR , PNTR ,
     1     WORDLENGTH )
	    STATE = -1

	  ELSE IF( STATE .EQ. 6 ) THEN

	    DO 260 IB = 1 , LEN(BLANK)
	      IF( LINE(INDEX:INDEX) .EQ. BLANK(IB:IB) ) THEN
	        STATE = 7
	        GOTO 290
	      END IF
260	    CONTINUE

	    DO 270 IQ = 1 , LEN(QUOTE)
	      IF( LINE(INDEX:INDEX) .EQ. QUOTE(IQ:IQ) ) THEN
	        STATE = 18
	        GOTO 290
	      END IF
270	    CONTINUE

	    IF(NONSEP(LINE(INDEX:INDEX),SEPARATORS)) THEN
	      STATE = 4
	    ELSE
	      STATE = 8
	    END IF

290	    CONTINUE
C
	  ELSE IF( STATE .EQ. 7 ) THEN
	    CALL SET2NDPNTR( INDEX-1 , NUMWORDS , DIMPNTR , PNTR ,
     1     WORDLENGTH )
	    STATE = 9

	  ELSE IF( STATE .EQ. 8 ) THEN
	    CALL SET2NDPNTR( INDEX-1 , NUMWORDS , DIMPNTR , PNTR ,
     1     WORDLENGTH )
	    IF( NUMWORDS .GE. DIMPNTR ) THEN
	      STATE = -1
	    ELSE
	      STATE = 10
	    END IF

	  ELSE IF( STATE .EQ. 9 ) THEN
	    IF( NUMWORDS .GE. DIMPNTR ) THEN
	      STATE = -1
	    ELSE
	      STATE = 2
	    END IF

	  ELSE IF( STATE .EQ. 10 ) THEN
	    CALL SETNEXT1STPNTR( INDEX , NUMWORDS , DIMPNTR , PNTR )
	    CALL SET2NDPNTR( INDEX , NUMWORDS , DIMPNTR , PNTR ,
     1     WORDLENGTH )
	    STATE = 9

	  ELSE IF( STATE .EQ. 11 ) THEN
	    ERROR = ERROR + 1
	    INDEX = INDEX + 1
	    IF( INDEX .LE. LNTH ) THEN
	      STATE = 12
	    ELSE
	      STATE = -1
	    END IF

	  ELSE IF( STATE .EQ. 12 ) THEN

	    DO 300 IQ = 1 , LEN(QUOTE)
	      IF( LINE(INDEX:INDEX) .EQ. QUOTE(IQ:IQ) ) THEN
	        STATE = 13
	        GOTO 400
	      END IF
300	    CONTINUE

	    STATE = 14

400	    CONTINUE

	  ELSE IF( STATE .EQ. 13 ) THEN
	    ERROR = ERROR - 1
	    STATE = 1

	  ELSE IF( STATE .EQ. 14 ) THEN
	    CALL SETNEXT1STPNTR( INDEX , NUMWORDS , DIMPNTR , PNTR )
	    STATE = 15

	  ELSE IF( STATE .EQ. 15 ) THEN
	    INDEX = INDEX + 1
	    IF( INDEX .LE. LNTH ) THEN
	      STATE = 16
	    ELSE
	      STATE = -1
	    END IF

	  ELSE IF( STATE .EQ. 16 ) THEN

	    DO 500 IQ = 1 , LEN(QUOTE)
	      IF( LINE(INDEX:INDEX) .EQ. QUOTE(IQ:IQ) ) THEN
	        STATE = 17
	        GOTO 600
	      END IF
500	    CONTINUE

	    STATE = 15

600	    CONTINUE


	  ELSE IF( STATE .EQ. 17 ) THEN
	    ERROR = ERROR - 1
	    CALL SET2NDPNTR( INDEX-1 , NUMWORDS , DIMPNTR , PNTR ,
     1     WORDLENGTH )
	    STATE = 9

	  ELSE IF( STATE .EQ. 18 ) THEN
	    CALL SET2NDPNTR( INDEX-1 , NUMWORDS , DIMPNTR , PNTR ,
     1     WORDLENGTH )
	    IF( NUMWORDS .GE. DIMPNTR ) THEN
	      STATE = 19
	    ELSE
	      STATE = 11
	    END IF

	  ELSE IF( STATE .EQ. 19 ) THEN
	    ERROR = 1
	    STATE = -1

	  END IF


C	END DO
	GOTO 100
1000	CONTINUE


	RETURN
	END
C
	SUBROUTINE SETNEXT1STPNTR( INDEX , NUMWORDS , DIMPNTR , PNTR )

CC--
CC Set next pointer to beginning of next token
CC--

	INTEGER*2 INDEX , NUMWORDS , DIMPNTR , PNTR( 2 , DIMPNTR )

	NUMWORDS = NUMWORDS + 1
	PNTR( 1 , NUMWORDS ) = INDEX

	RETURN
	END
C
	SUBROUTINE SET2NDPNTR( INDEX , NUMWORDS , DIMPNTR , PNTR ,
     1   WORDLENGTH )

CC--
CC Set current pointer to end of token and calculate length
CC--

	INTEGER*2 INDEX , NUMWORDS , DIMPNTR , PNTR( 2 , DIMPNTR ) ,
     1   WORDLENGTH( DIMPNTR )

	PNTR( 2 , NUMWORDS ) = INDEX
	WORDLENGTH( NUMWORDS ) =
     1   PNTR( 2 , NUMWORDS ) - PNTR( 1 , NUMWORDS ) + 1

	RETURN
	END
C
	LOGICAL*1 FUNCTION NONSEP( CHR , SEPARATORS )

CC--
CC Check if CHR is a non-separator. If it is, NONSEP is TRUE.
CC--

	CHARACTER * 1 CHR
	CHARACTER*(*) SEPARATORS

	INTEGER*2 I

C -- FUNCTIONS

	INTEGER*2 LENGTH


	DO 10 I = 1 , LENGTH( SEPARATORS )

	  IF( CHR .EQ. SEPARATORS(I:I) ) THEN
	    NONSEP = .FALSE.
	    RETURN
	  END IF

10	CONTINUE

	NONSEP = .TRUE.

	RETURN
	END

