LL1P20: PROC; /**************************************************************** * LL(1) GRAMMAR ANALYZER - PHASE 2 * *PURPOSE: * * THIS PROGRAM SORTS THE VOCABULARY AND PRINTS THE INTERNAL * * FORM OF THE LANGUAGE IN A BNF FORMAT. * *INPUT: * *OUTPUT: * *OUTLINE: * *REMARKS: * ****************************************************************/ /**************************************************************** * * * * * * * * * * * COMMON DATA DEFINITIONS * * * * * * * * * * ****************************************************************/ /* * * * COMMON REPLACEMENTS * * * */ %REPLACE TRUE BY '1'B; %REPLACE FALSE BY '0'B; %INCLUDE 'LL1CMN.DCL'; /* GET COMMON AREAS. */ /**************************************************************** * * * * * * * * * * * COMMON PROCUDURES * * * * * * * * * * * * * ****************************************************************/ %INCLUDE 'LL1PRC.DCL'; /**************************************************************** * * * * * * * * * * * GRAMMAR PRINT PROCUDURES * * * * * * * * ** ****************************************************************/ PRINT_PRODUCTIONS: PROC; /*THIS ROUTINE IS RESPONSIBLE FOR PRINTING THE VOCABULARY. */ DCL I BIN(15); /* INDEXES */ DCL J BIN(15); DCL NUM_LINES BIN(15); /* MAXIMUM NUMBER OF LINES */ DCL LHS_ENT CHAR(10) VARYING; DCL RHS_ENT(5) CHAR(10) VARYING; /* OUTPUT THE HEADING. */ ON ENDPAGE(LSTFIL) BEGIN; PUT FILE(LSTFIL) PAGE; PUT FILE(LSTFIL) SKIP(3) EDIT('*** PRODUCTION LISTING ***','PAGE', PAGENO(LSTFIL)-1) (X(20),A(26),X(10),A(4),F(4)); PUT FILE(LSTFIL) SKIP(1); END; SIGNAL ENDPAGE(LSTFIL); /* PRINT THE REPORT LINES. */ PUT FILE(LSTFIL) SKIP(1) EDIT('STARTING SYMBOL: ',VOC(CHRNUM(STRSYM))) (X(14),A(17),A(10)); DO I=1 TO NUMPRD; LHS_ENT=VOC(CHRNUM(LHS(I))); DO J=1 TO 5; IF J>LENGTH(RHS(I)) THEN RHS_ENT(J)=''; ELSE RHS_ENT(J)=VOC(CHRNUM(SUBSTR(RHS(I),J,1))); END; PUT FILE(LSTFIL) SKIP(1) EDIT(I,LHS_ENT,' -> ',(RHS_ENT(J) DO J=1 TO 5),';') (F(4),X(01),A,A(04),5(A,X(01)),A(1)); END; END PRINT_PRODUCTIONS; PRINT_VOCABULARY: PROC; /*THIS ROUTINE IS RESPONSIBLE FOR PRINTING THE VOCABULARY. */ DCL I BIN(15); /* INDEXES */ DCL J BIN(15); DCL NUM_LINES BIN(15); /* MAXIMUM NUMBER OF LINES */ DCL TRM_ENT CHAR(10) VARYING; DCL NTRM_ENT CHAR(10) VARYING; /* DETERMINE MAX LENGTH FOR LOOP. */ IF LENGTH(TRM)>LENGTH(NTRM) THEN NUM_LINES=LENGTH(TRM); ELSE NUM_LINES=LENGTH(NTRM); /* OUTPUT THE HEADING. */ ON ENDPAGE(LSTFIL) BEGIN; PUT FILE(LSTFIL) PAGE; PUT FILE(LSTFIL) SKIP(3) EDIT('*** VOCABULARY LISTING ***','PAGE', PAGENO(LSTFIL)-1) (X(20),A(26),X(10),A(4),F(4)); PUT FILE(LSTFIL) SKIP(1) EDIT('TERMINALS','NON-TERMINALS') (X(19),A(10),X(05),A(13)); PUT FILE(LSTFIL) SKIP(1); END; SIGNAL ENDPAGE(LSTFIL); /* PRINT THE REPORT LINES. */ DO I=1 TO NUM_LINES; IF I>LENGTH(TRM) THEN /* GET TERMINAL ENTRY.*/ TRM_ENT=''; ELSE TRM_ENT=VOC(CHRNUM(SUBSTR(TRM,I,1))); IF I>LENGTH(NTRM) THEN /* GET NON-TERMINAL ENTRY.*/ NTRM_ENT=''; ELSE NTRM_ENT=VOC(CHRNUM(SUBSTR(NTRM,I,1))); PUT FILE(LSTFIL) SKIP(1) EDIT(I,TRM_ENT,NTRM_ENT) (X(14),F(4),X(01),A(10),X(05),A(10)); END; END PRINT_VOCABULARY; SORT_VOCABULARY: PROC; /*THIS ROUTINE IS RESPONSIBLE FOR SORTING THE VOCABULARY. */ /*IT SORTS: 1) NON-TERMINAL VS TERMINAL 2) SYMBOL /*THEN IT UPDATES ALL THE TABLES TO REFLECT THE NEW ORDER. */ DCL I BIN(15); /* INDEXES */ DCL J BIN(15); DCL SORT_FLAG BIT(1); DCL 1 VOC_INDEX(254), /* SORT INDEX FOR VOCABULARY */ 2 TRM_IND BIT(1), /* 0=NON-TERMINAL 1=TERMINAL */ 2 SYM_LEN BIN(7), /* SYMBOL LENGTH */ 2 ORIG CHAR; /* ORIGINAL ORDER */ DCL 1 TMP_INDEX, /* TEMP AREA FOR BUBBLE SORT */ 2 TRM_IND BIT(1), /* 0=NON-TERMINAL 1=TERMINAL */ 2 SYM_LEN BIN(7), /* SYMBOL LENGTH */ 2 ORIG CHAR; /* ORIGINAL ORDER */ DCL TMP_VOC(254) CHAR(10) VARYING; DCL TMP_REORG(254) BIN(15); /* BUILD SORT INDEX. */ STRSYM=SUBSTR(NTRM,1,1); /*STARTING SYMBOL*/ DO I=1 TO NUMVOC; VOC_INDEX.TRM_IND(I)=ISTRM(NUMCHR(I)); VOC_INDEX.SYM_LEN(I)=LENGTH(VOC(I)); VOC_INDEX.ORIG(I)=NUMCHR(I); END; /* BUBBLE SORT THE INDEX. */ SORT_FLAG=TRUE; DO WHILE(SORT_FLAG=TRUE); SORT_FLAG=FALSE; DO I=1 TO NUMVOC-1; IF VOC_INDEX.TRM_IND(I)=TRUE & VOC_INDEX.TRM_IND(I+1)=FALSE THEN DO; TMP_INDEX=VOC_INDEX(I); VOC_INDEX(I)=VOC_INDEX(I+1); VOC_INDEX(I+1)=TMP_INDEX; SORT_FLAG=TRUE; END; ELSE IF VOC_INDEX.TRM_IND(I)=VOC_INDEX.TRM_IND(I+1) THEN IF VOC(CHRNUM(VOC_INDEX.ORIG(I))) > VOC(CHRNUM(VOC_INDEX.ORIG(I+1))) THEN DO; TMP_INDEX=VOC_INDEX(I); VOC_INDEX(I)=VOC_INDEX(I+1); VOC_INDEX(I+1)=TMP_INDEX; SORT_FLAG=TRUE; END; END; END; /* PUT THE VOCABULARY TABLE IN ORDER SPECIFIED BY THE SORT. */ DO I=1 TO NUMVOC; TMP_VOC(I)=VOC(CHRNUM(VOC_INDEX.ORIG(I))); END; DO I=1 TO NUMVOC; VOC(I)=TMP_VOC(I); END; /* PUT THE NON-TERMINAL TABLE IN ORDER SPECIFIED BY THE SORT. */ NTRM=''; DO I=1 TO NUMVOC; IF VOC_INDEX.TRM_IND(I)=FALSE THEN NTRM=NTRM || NUMCHR(I); END; /* PUT THE TERMINAL TABLE IN ORDER SPECIFIED BY THE SORT. */ TRM=''; DO I=1 TO NUMVOC; IF VOC_INDEX.TRM_IND(I)=TRUE THEN TRM=TRM || NUMCHR(I); END; /* TRANSLATE THE PRODUCTIONS ARRAY TO THE NEW INDEX. */ DO I=1 TO NUMVOC; TMP_REORG(CHRNUM(VOC_INDEX.ORIG(I)))=I; END; DO I=1 TO NUMPRD; LHS(I)=NUMCHR(TMP_REORG(CHRNUM(LHS(I)))); IF LENGTH(RHS(I))>0 THEN DO J=1 TO LENGTH(RHS(I)); SUBSTR(RHS(I),J,1)=NUMCHR(TMP_REORG(CHRNUM( SUBSTR(RHS(I),J,1)))); END; END; STRSYM=NUMCHR(TMP_REORG(CHRNUM(STRSYM))); /*STARTING SYMBOL*/ /* RETURN TO CALLER. */ END SORT_VOCABULARY; /**************************************************************** * * * * * * * * * * * MAIN LINE PROCEDURE * * * * * * * * * * * * ****************************************************************/ /* DO INITIALIZATION. */ PUT SKIP LIST('BEGINNING PHASE 2 PROCESSING.'); /* PRINT THE GRAMMAR. */ CALL SORT_VOCABULARY; CALL PRINT_VOCABULARY; /* PRINT THE VOCABULARY. */ CALL PRINT_PRODUCTIONS; /* PRINT THE PRODUCTIONS. */ /* RETURN TO CALLER. */ PUT SKIP LIST('PHASE 2 PROCESSING COMPLETE - NO ERRORS.'); END LL1P20;