.NLIST TOC .TITLE PAREXP .SBTTL PARSE FORTRAN EXPRESSIONS .IDENT /V02/ ;+ ; AUTHOR: GARY MAXWELL ; DATE: 27-AUG-79 ; ; SUBROUTINE FOR PARSING A FORTRAN EXPRESSION POINTED ; TO BY THE GLOBAL POINTER LINPTR. ; ; BY ASSUMING THAT VARTYP HAS BEEN APPROPRIATELY INITIALIZED, ; PAREXP CALLS GETVAR WHEN NECESSARY TO STORE A VARIABLE ; FOUND IN THE EXPRESSION. ; ; INPUTS: VARTYP AND LINPTR ARE APPROPRIATELY INITIALIZED ; ; OUTPUTS: LINPTR IS UPDATED TO THE FIRST CHARACTER FOUND ; THAT DOESN'T MATCH EXPRESSION SYNTAX. ; ; CARRY IS CLEAR IF THE EXPRESSION APPEARED NORMAL. ; CARRY SET IF SOMETHING IS WRONG WITH EXPRESSION ; (I.E., PARENTHETICAL LEVEL DOESN'T MATCH) ;- .PSECT PAREXP .NLIST BEX ;+ ; OPERATOR LISTS ;- UNLS: .ASCIZ /+/ .ASCIZ /-/ .ASCIZ /"/ .ASCIZ /.NOT./ .BYTE 0 BOOLS: .ASCIZ /.TRUE./ .ASCIZ /.FALSE./ .BYTE 0 BOPLS: .ASCIZ /+/ .ASCIZ /-/ .ASCIZ ^/^ .ASCIZ /**/ .ASCIZ /*/ .ASCIZ /.AND./ .ASCIZ /.OR./ .ASCIZ /.GT./ .ASCIZ /.GE./ .ASCIZ /.LT./ .ASCIZ /.LE./ .ASCIZ /.EQ./ .ASCIZ /.NE./ .ASCIZ /.XOR./ .ASCIZ /.EQV./ .BYTE 0 .EVEN .LIST BEX PLEV: .WORD 0 ; LOCAL PAREN LEVEL WORD ;+ ; PAREXP ENTRY ;- PAREXP:: CLR PLEV ; SET LEVEL TO ZERO PST: MOV #UNLS,R0 ; POINT TO UNARY OPS CALL SEEK ; HAVE WE FOUND ONE? BCS 20$ ; NO, KEEP LOOKING MOV R1,LINPTR ; YES! POINT AFTER IT 20$: MOVB @LINPTR,R0 ; GET CHARACTER BEQ POUT0 ; NOTHING TO LOOK AT CMP #'(,R0 ; START A NEST? BNE 30$ ; NO INC PLEV ; YES, BUMP LEVEL INC LINPTR ; BUMP POINTER BR PST ; AND TRY AGAIN 30$: CALL TYPE ; FIND WHAT IT IS TST TYPECH ; LOOK AT FLAG BLE 40$ ; NUM OR TERMINAL - SKIP AHEAD CALL GETVAR ; ALPHA - PARSE TERM CMPB #'(,@LINPTR ; IS THIS A FUNCTION INVOCATION? BNE CLOTRM ; NO, SKIP AHEAD INC LINPTR ; YES, POINT TO FIRST ARG CMPB #'),@LINPTR ; NULL ARG LIST? BNE 310$ ; NO, GO PARSE ARG LIST INC LINPTR ; YES, BUMP OVER ')' BR CLOTRM ; GO CLOSE THE TERM 300$: CMP #'),R0 ; COME TO CLOSING ')'? BEQ CLOTRM ; YES, GO CLOSE TERM 310$: MOV PLEV,-(SP) ; PUSH OUR NEST LEVEL CALL PAREXP ; PARSE NEXT ARGUMENT MOV (SP)+,PLEV ; GET BACK THE NEST BCS PEXIT ; BUT EXIT IF PARSE WAS BAD MOVB @LINPTR,R0 ; GET CHAR AFTER ARGUMENT BEQ POUT0 ; EXIT IF NOTHING THERE INC LINPTR ; POINT AFTER IT BR 300$ ; AND GET REST OF LIST .PAGE 40$: BEQ 50$ ; GO SKIP OVER NUMBERS CMP #<'.>,R0 ; IS TERMINAL A PERIOD? BNE 410$ ; NO, TRY AGAIN MOV LINPTR,R0 ; YES, GRAB POINTER MOVB 1(R0),R0 ; AND SNATCH NEXT CHAR BEQ POUT0 ; EXIT IF NOTHING THERE CALL TYPE ; FIND WHAT IT IS TST TYPECH ; CHECK FLAG BEQ 50$ ; NUMBER - GO PARSE DECIMALS BLT POUT ; TERMINAL - EXIT MOV #BOOLS,R0 ; ALPHA - MAYBE A BOOLEAN CALL SEEK ; IS IT? BCS POUT ; NO, WE'RE BAFFLED MOV R1,LINPTR ; YES, POINT AFTER IT BR CLOTRM ; AND FIND WHAT FOLLOWS 410$: CMP #<''>,R0 ; STARTING A QUOTE? BNE POUT ; NO - GIVE UP CALL GETVAR ; YES - GETVAR PARSES THEM NICELY BR CLOTRM ; AND FIND WHAT FOLLOWS 50$: CALL SKPNUM ; SKIP OVER NUMBERS ;+ ; WORK ON BINARY OPS ;- CLOTRM: CMPB #'),@LINPTR ; CLOSING PARENTHESIS? BNE 10$ ; NO, SKIP AHEAD TST PLEV ; CHECK OUR LEVEL BLE PEXIT ; ZERO MEANS WE'RE DONE DEC PLEV ; ELSE BUMP BACK LEVEL INC LINPTR ; BUMP CHAR POINTER BR CLOTRM ; GO TRY AGAIN 10$: MOV #BOPLS,R0 ; GET BINARY OP LIST CALL SEEK ; IS THAT WHAT WE HAVE? BCS POUT ; NO, THAT MEANS WE'RE DONE MOV R1,LINPTR ; ELSE UPDATE POINTER BR PST ; AND START AGAIN POUT0: INC ARGFLG ; SET END OF LINE FLAG POUT: TST PLEV ; FINAL LEVEL CHECK BEQ PEXIT ; IF ZERO, FINE SEC ; ELSE WARN CALLER PEXIT: RETURN ;+ ; SUBROUTINE SEEK - PERFORMS MATCH OF BUFFER AGAINST LIST ; ; INPUTS: R0 POINTS TO A LIST OF QUALIFIED TOKENS TO BE ; MATCHED AGAINST THE CURRENT INPUT TOKEN. EACH ; TOKEN IN THE LIST IS TERMINATED BY A NULL BYTE, ; FOLLOWED BY THE NEXT TOKEN IN THE LIST. ANOTHER ; NULL BYTE IS PLACED AFTER THE LAST ENTRY TO SIGNIFY ; THE END OF THE LIST ; ; OUTPUTS: CARRY SET - TOKEN NOT FOUND ; R0 AND R1 DESTORYED ; CARRY CLEAR - TOKEN FOUND ; R1 POINTS TO CHARACTER FOLLOWING MATCHED ; TOKEN IN INPUT STREAM. ; R0 DESTORYED ; ;- SEEK: TSTB (R0) ; END OF LIST? BEQ NS ; YES, AFRAID SO MOV LINPTR,R1 ; ELSE SET INPUT POINTER 10$: CMPB (R0)+,(R1)+ ; CHARACTERS MATCH? BNE 20$ ; NO, GO TO NEXT IN LIST TSTB (R0) ; CHECK FOR MATCH BNE 10$ ; NOT AT END OF TOKEN BR SEXIT ; YES! EXIT (CARRY ALREADY CLEAR) 20$: TSTB (R0)+ ; GET TO END OF TOKEN IN LIST BEQ SEEK ; FOUND - START NEXT PASS BR 20$ ; ELSE BUMP AGAIN NS: SEC SEXIT: RETURN .END