home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / interpre / pl / scanner.pas < prev    next >
Pascal/Delphi Source File  |  1986-12-12  |  32KB  |  826 lines

  1. PROGRAM PL_SCANNER;
  2. {*****************************************************************************}
  3. {*****************************************************************************}
  4. {****    PROGRAM: PL_SCANNER - SCANS A TEXT FILE OF A PL PROGRAM AND      ****}
  5. {****             CONVERTS IT INTO CODE THE PL PARSER CAN UNDERSTAND...   ****}
  6. {-----------------------------------------------------------------------------}
  7. {****    AUTHOR: JAY MONFORT           FOR: MATH 434 - COMPILER DESIGN    ****}
  8. {****                      SEPTEMBER 25, 1985                             ****}
  9. {*****************************************************************************}
  10. {*****************************************************************************}
  11. {-----------------------------------------------------------------------------}
  12. {$C-,K-,V-,D-}
  13.    { NO CTRL-C CHECK, NO STACK CHECK, NO VAR LENGTH CHECK, NO DEVICE CHECK }
  14. {-----------------------------------------------------------------------------}
  15.  
  16. CONST
  17.  
  18.     MAXINT = 32767;
  19.  
  20.     MAXKEY = 107;     { LENGTH OF HASHTABLE }
  21.  
  22.     MAXCHARS = 1000;   { LENGTH OF SPELLING TABLE }
  23.  
  24.     MAXSTRING = 80;    { MAXIMUM STRING LENGTH }
  25.  
  26. {=============================================================================}
  27.  
  28. TYPE
  29.  
  30.     SYMBOL_TYPE =
  31.           (AND1,ARRAY1,ARROW1,BECOMES1,BEGIN1,{ 5 }BOOLEAN1,CALL1,COMMA1,CONST1,
  32.            DIV1,{ 10 }DO1,END1,ENDTEXT1,EQUAL1,FALSE1,{ 15 }FI1,GREATER1,IF1,
  33.            INTEGER1,LEFT_BRACKET1,{ 20 }LEFT_PAREN1,LESS1,MINUS1,MOD1,MULT1,
  34.            { 25 }NAME1,NEWLINE1,NOT1,NUMERAL1,OD1,{ 30 }OR1,PAIRED_BRACKETS1,
  35.            PERIOD1,PLUS1,PROC1,{ 35 }READ1,RIGHT_BRACKET1,RIGHT_PAREN1,
  36.            SEMICOLON1,SKIP1,{ 40 }TRUE1,UNKNOWN1,WRITE1);
  37.  
  38.     ERROR_TYPE = (NUMERAL3,UNKNOWN3,TOOBIG3);
  39.  
  40.     CHARSET = SET OF CHAR;
  41.  
  42.     WORD_POINTER = ^WORD_RECORD;
  43.  
  44.     WORD_RECORD = RECORD
  45.                      NEXT_WORD: WORD_POINTER; { POINTS TO NEXT WORD IN CHAIN }
  46.                      ISNAME: BOOLEAN;         { NAME ELSE SYMBOL }
  47.                      INDEX,                   { ORD(NAME) OR ORD(SYMBOL) }
  48.                      STRLENGTH,               { CHAR LENGTH IF NAME }
  49.                      LASTCHAR: INTEGER        { INDX LAST CHAR IN SPELL TABLE }
  50.                   END;
  51.  
  52.     WRKSTRING = STRING[MAXSTRING];
  53.  
  54.     HASHTABLETYPE = ARRAY[1..MAXKEY] OF WORD_POINTER;
  55.  
  56.     SPELLINGTABLETYPE = ARRAY[1..MAXCHARS] OF CHAR;
  57.  
  58. {=============================================================================}
  59.  
  60. VAR
  61.  
  62.     SEPARATORS,LETTERS, ALPHANUMERIC,
  63.     DIGITS, INVISIBLE, ASCII, SPECIAL: CHARSET;  { USEFUL CHARACTER SETS }
  64.  
  65.     TOTALCHARS,         { TOTAL NUMBER OF CHARACTERS IN SPELLING TABLE }
  66.     LINENUM,            { CURRENT SOURCE LINE NUMBER DURING SCAN }
  67.     NAMES:   INTEGER;   { NUMBER OF DEFINED NAMES }
  68.  
  69.     HASHTABLE: HASHTABLETYPE;      { FOR WORD SYMBOLS, USING DIRECT CHAINING }
  70.  
  71.     SPELLTABLE: SPELLINGTABLETYPE; { TABLE OF WORDS, ACCESSED THRU HASHTABLE }
  72.  
  73.     SOURCEFILE,                    { THE SOURCE CODE }
  74.                                    { BOTH WITH 10K BUFFERS }
  75.     CODEFILE: TEXT[$2800];         { THE OUTPUT CODE FILE }
  76.  
  77.     ERRFILE: TEXT[$800];           { THE ERROR MESSAGE FILE, WITH 2K BUFFER }
  78.  
  79.     CH: CHAR;                      { THE CURRENT CHARACTER }
  80.  
  81.     ERROPENED: BOOLEAN;            { TELLS IF ERROR FILE IS OPENED }
  82.  
  83. {=============================================================================}
  84.  
  85. {*****************************************************************************}
  86. {****          FUNCTION EXIST - RETURNS TRUE IF A FILE IS ON DISK         ****}
  87. {*****************************************************************************}
  88. FUNCTION EXIST(FILENAME: WRKSTRING): BOOLEAN;
  89. VAR
  90.    FIL: FILE;
  91. BEGIN
  92.      ASSIGN(FIL,FILENAME);
  93.      {$I-}
  94.      RESET(FIL);
  95.      {$I+}
  96.      EXIST:= (IORESULT = 0);
  97.      IF IORESULT = 0
  98.         THEN CLOSE(FIL)
  99. END;    { FUNCTION EXIST }
  100. {*****************************************************************************}
  101.  
  102. {=============================================================================}
  103. {=============================================================================}
  104. {====      THE FOLLOWING PROCEDURES OPEN THE INPUT AND OUTPUT FILES       ====}
  105. {====                                                                     ====}
  106. {*****************************************************************************}
  107. {****        PROCEDURE OPEN_SOURCE - OPENS THE SOURCE CODE FILE           ****}
  108. {*****************************************************************************}
  109. PROCEDURE OPEN_SOURCE;
  110. VAR
  111.    SOURCECODE: WRKSTRING;
  112. { GLOBAL VARIABLE - SOURCEFILE: TEXT }
  113. BEGIN
  114.      IF PARAMCOUNT = 0
  115.         THEN
  116.             BEGIN
  117.                  LOWVIDEO;
  118.                  WRITE('ENTER THE SOURCE CODE FILENAME: ');
  119.                  NORMVIDEO;
  120.                  READLN(SOURCECODE)
  121.             END
  122.         ELSE SOURCECODE:= PARAMSTR(1);
  123.      IF EXIST(SOURCECODE)
  124.         THEN
  125.             BEGIN
  126.                  ASSIGN(SOURCEFILE,SOURCECODE);
  127.                  RESET(SOURCEFILE);
  128.                  GOTOXY(20,8);
  129.                  LOWVIDEO;
  130.                  WRITE('SCANNING ');
  131.                  NORMVIDEO;
  132.                  WRITE(SOURCECODE)
  133.             END
  134.         ELSE
  135.             BEGIN
  136.                  WRITELN;
  137.                  WRITELN('UNKNOWN DISK ERROR OR ',SOURCECODE,' NOT FOUND.');
  138.                  HALT(100)      { USED FOR ERRORLEVEL IN BATCH FILE }
  139.             END
  140. END;    { PROCEDURE OPEN_SOURCE }
  141. {*****************************************************************************}
  142.  
  143. {*****************************************************************************}
  144. {****         PROCEDURE OPEN_CODE - OPENS THE CODE FILE FOR OUTPUT        ****}
  145. {*****************************************************************************}
  146. PROCEDURE OPEN_CODE;
  147. { GLOBAL VARIABLE - CODEFILE: TEXT }
  148. BEGIN
  149.      ASSIGN(CODEFILE,'TEMP1.');
  150.      {$I-}
  151.      REWRITE(CODEFILE);
  152.      {$I+}
  153.      IF IORESULT <> 0
  154.        THEN
  155.          BEGIN
  156.            WRITELN;
  157.            WRITELN('UNKNOWN DISK ERROR');
  158.            HALT(100)      { PICKED UP AS ERRORLEVEL BY DOS }
  159.          END
  160. END;
  161. {*****************************************************************************}
  162. {====                 END OF FILE OPENING PROCEDURES                      ====}
  163. {=============================================================================}
  164. {=============================================================================}
  165.  
  166.  
  167. {=============================================================================}
  168. {=============================================================================}
  169. {====         THE FOLLOWING ARE THE ERROR HANDLING PROCEDURES             ====}
  170. {====            FOR WRITING TO THE ERROR FILE...                         ====}
  171. {*****************************************************************************}
  172. {****              PROCEDURE OPENERROR - OPENS THE ERROR FILE             ****}
  173. {*****************************************************************************}
  174. PROCEDURE OPENERROR(FILENAME: WRKSTRING);
  175. { GLOBAL VARIABLE - ERRFILE: TEXT }
  176. BEGIN
  177.      ASSIGN(ERRFILE,FILENAME);
  178.      {$I-}
  179.      REWRITE(ERRFILE);
  180.      {$I+}
  181.      IF IORESULT <> 0
  182.         THEN
  183.           BEGIN
  184.              WRITELN('UNKNOWN DISK ERROR');
  185.              HALT(100)
  186.           END
  187. END;    { PROCEDURE OPENERROR }
  188. {*****************************************************************************}
  189.  
  190. {*****************************************************************************}
  191. {****    PROCEDURE TIMESTR - WRITES THE CURRENT TIME TO THE ERROR FILE    ****}
  192. {*****************************************************************************}
  193. PROCEDURE TIMESTR;
  194. { GLOBAL VARIABLE - ERRFILE: TEXT }
  195. TYPE
  196.     REGPACK = RECORD
  197.                     AX,BX,CX,DX,BP,SI,DI,DS,ES,FLAGS: INTEGER
  198.               END;
  199. VAR
  200.    REGS: REGPACK;
  201.    HOURS,MINS,SECS,FRACS: INTEGER;
  202.    HRSTR,MNSTR,SCSTR,FRACSTR: STRING[2];
  203. BEGIN
  204.      WITH REGS DO
  205.      BEGIN
  206.           AX:= $2C00;                 {DOS INT 21H, FUNCTION 2C(H)}
  207.           MSDOS(REGS);
  208.           HOURS:= HI(CX);              {HI ORDER BYTE OF CX}
  209.           MINS:= LO(CX);               {LOW ORDER BYTE OF CX}
  210.           SECS:= HI(DX);
  211.           FRACS:= LO(DX)
  212.      END;
  213.      STR(HOURS:2,HRSTR);
  214.      STR(MINS:2,MNSTR);
  215.      STR(SECS:2,SCSTR);
  216.      STR(FRACS:2,FRACSTR);
  217.      IF MINS = 0
  218.         THEN MNSTR:= '00'
  219.         ELSE IF MINS < 10
  220.                 THEN MNSTR[1]:= '0';
  221.      IF SECS = 0
  222.         THEN SCSTR:= '00'
  223.         ELSE IF SECS < 10
  224.                 THEN SCSTR[1]:= '0';
  225.      IF FRACS = 0
  226.         THEN FRACSTR:= '00'
  227.         ELSE IF FRACS < 10
  228.                 THEN FRACSTR[1]:= '0';
  229.      WRITE(ERRFILE,'-- ',HRSTR ,':',MNSTR,':',SCSTR,'.',FRACSTR,' --> ')
  230. END;      { PROCEDURE TIMESTR }
  231. {*****************************************************************************}
  232.  
  233. {*****************************************************************************}
  234. {****            PROCEDURE ERROR - HANDLES THE SCANNER ERRORS             ****}
  235. {*****************************************************************************}
  236. PROCEDURE ERROR(ERRTYPE: ERROR_TYPE);
  237. { GLOBAL VARIABLE - ERRFILE: TEXT }
  238. BEGIN
  239.    IF NOT ERROPENED
  240.      THEN
  241.        BEGIN
  242.          ERROPENED:= TRUE;
  243.          OPENERROR('ERROR1.');
  244.        END;
  245.    TIMESTR;
  246.    CASE ERRTYPE OF
  247.      NUMERAL3: WRITE(ERRFILE,'INTEGER OUT OF RANGE ');
  248.      UNKNOWN3: WRITE(ERRFILE,'UNKNOWN SYMBOL ');
  249.      TOOBIG3 : WRITE(ERRFILE,'SPELLING TABLE OVERFLOW ')
  250.    END;   { CASE }
  251.    WRITELN(ERRFILE,'AT LINE ',LINENUM:5)
  252. END;    { PROCEDURE ERROR }
  253. {*****************************************************************************}
  254. {====                                                                     ====}
  255. {====                END OF ERROR HANDLING PROCEDURES                     ====}
  256. {=============================================================================}
  257. {=============================================================================}
  258.  
  259.  
  260. {=============================================================================}
  261. {=============================================================================}
  262. {====     THE FOLLOWING ARE THE WORD SYMBOL PROCEDURES AND FUNCTIONS      ====}
  263. {====            FOR THE HASH AND SPELLING TABLES                         ====}
  264. {*****************************************************************************}
  265. {***            FUNCTION HASH - HASHES A NAME INTO A KEY NUMBER            ***}
  266. {*****************************************************************************}
  267. FUNCTION HASH(VAR TEXTSTRING: WRKSTRING; WORD_LENGTH: INTEGER): INTEGER;
  268. CONST
  269.      BIG = 32513;
  270.      HASHSIZE = MAXKEY;       { MAXKEY IS GLOBAL CONSTANT }
  271. VAR
  272.    SUM, I: INTEGER;
  273. BEGIN
  274.      SUM:= 0;
  275.      I:= 1;
  276.      WHILE I <= WORD_LENGTH DO
  277.        BEGIN
  278.             SUM:= (SUM + ORD(TEXTSTRING[I])) MOD BIG;
  279.             I:= I + 1
  280.        END;
  281.      HASH:= (SUM MOD HASHSIZE) + 1
  282. END;               { FUNCTION HASH }
  283. {*****************************************************************************}
  284.  
  285. {*****************************************************************************}
  286. {****  FUNCTION FITS - MAKES SURE A STRING WILL FIT IN THE SPELLING TABLE ****}
  287. {*****************************************************************************}
  288. FUNCTION FITS(WORD_LENGTH: INTEGER): BOOLEAN;
  289. { GLOBAL CONSTANT - MAXCHARS }
  290. { GLOBAL VARIABLE - TOTALCHARS: INTEGER }
  291. BEGIN
  292. IF (TOTALCHARS + WORD_LENGTH) <= MAXCHARS
  293.   THEN FITS:= TRUE
  294.     ELSE
  295.      BEGIN
  296.       ERROR(TOOBIG3);
  297.       FITS:= FALSE
  298.      END
  299. END;   { FUNCTION FITS }
  300. {*****************************************************************************}
  301.  
  302. {*****************************************************************************}
  303. {** PROCEDURE INSERTWORD - INSERTS A WORD INTO THE SPELLING AND HASH TABLES **}
  304. {*****************************************************************************}
  305. PROCEDURE INSERTWORD( ISNAME: BOOLEAN; VAR TEXTSTR: WRKSTRING;
  306.                       INDEX, WORD_LENGTH, KEYNUM: INTEGER);
  307. { GLOBAL VARIABLES - TOTALCHARS: INTEGER;  HASHTABLE: HASHTABLETYPE }
  308. VAR
  309.    POINTER: WORD_POINTER;
  310.    M, N, I: INTEGER;
  311. BEGIN
  312.      IF FITS(WORD_LENGTH)
  313.         THEN
  314.           BEGIN
  315.             TOTALCHARS:= TOTALCHARS + WORD_LENGTH;
  316.             M:= WORD_LENGTH;
  317.             N:= TOTALCHARS - M;
  318.             FOR I:= M DOWNTO 1 DO
  319.                 SPELLTABLE[I + N]:= TEXTSTR[I];
  320.             NEW(POINTER);
  321.             POINTER^.NEXT_WORD:= HASHTABLE[KEYNUM];
  322.             POINTER^.ISNAME:= ISNAME;
  323.             POINTER^.INDEX:= INDEX;
  324.             POINTER^.STRLENGTH:= WORD_LENGTH;
  325.             POINTER^.LASTCHAR:= TOTALCHARS;
  326.             HASHTABLE[KEYNUM]:= POINTER
  327.           END   { IF FITS }
  328. END;    { PROCEDURE INSERT }
  329. {*****************************************************************************}
  330.  
  331. {*****************************************************************************}
  332. {* PROCEDURE DEFINE - USED TO INITIALIZE WORD SYMBOLS TO THE SPELLING TABLE  *}
  333. {*****************************************************************************}
  334. PROCEDURE DEFINE(ISNAME: BOOLEAN; TEXTSTR: WRKSTRING;
  335.                   INDEX, WORD_LENGTH: INTEGER);
  336. BEGIN
  337.      INSERTWORD(ISNAME,TEXTSTR,INDEX,WORD_LENGTH,HASH(TEXTSTR,WORD_LENGTH))
  338. END;      { PROCEDURE DEFINE }
  339. {*****************************************************************************}
  340.  
  341. {*****************************************************************************}
  342. {*PROCEDURE SEARCH-LOOK TO SEE IF A NAME OR WORDSYMBOL WAS DEFINED PREVIOUSLY*}
  343. {*****************************************************************************}
  344. PROCEDURE SEARCH(VAR TEXTSTR: WRKSTRING; VAR ISNAME: BOOLEAN;
  345.                  VAR INDEX: INTEGER; WORD_LENGTH: INTEGER);
  346. { GLOBAL VARIABLE - HASHTABLE: HASHTABLETYPE }
  347. VAR
  348.    KEYNUM: INTEGER;
  349.    POINTER: WORD_POINTER;
  350.    DONE: BOOLEAN;
  351.  
  352. {-----------------------------------------------------------------------------}
  353. {--- FUNCTION FOUND - LOOKS TO SEE IF THE CURRENT CHARS ARE THE RIGHT ONES ---}
  354. {-----------------------------------------------------------------------------}
  355.    FUNCTION FOUND: BOOLEAN;
  356.    { GLOBAL VARIABLE - SPELLTABLE: SPELLTABLETYPE }
  357.    VAR
  358.       SAME: BOOLEAN;
  359.       M, N: INTEGER;
  360.    BEGIN
  361.         IF POINTER^.STRLENGTH <> WORD_LENGTH
  362.            THEN SAME:= FALSE
  363.            ELSE
  364.              BEGIN
  365.                SAME:= TRUE;
  366.                M:= WORD_LENGTH;
  367.                N:= POINTER^.LASTCHAR - M;
  368.                WHILE SAME AND (M > 0) DO
  369.                  BEGIN
  370.                    SAME:= (TEXTSTR[M] = SPELLTABLE[M+N]);
  371.                    M:= M - 1
  372.                  END
  373.              END;
  374.         FOUND:= SAME
  375.    END;       { FUNCTION FOUND }
  376. {-----------------------------------------------------------------------------}
  377.  
  378. BEGIN   { PROCEDURE SEARCH }
  379.      KEYNUM:= HASH(TEXTSTR,WORD_LENGTH);
  380.      POINTER:= HASHTABLE[KEYNUM];
  381.      DONE:= FALSE;
  382.      WHILE NOT DONE DO
  383.          IF POINTER = NIL
  384.             THEN
  385.               BEGIN
  386.                 ISNAME:= TRUE;
  387.                 NAMES:= NAMES + 1;
  388.                 INDEX:= NAMES;
  389.                 INSERTWORD(TRUE,TEXTSTR,INDEX,WORD_LENGTH,KEYNUM);
  390.                 DONE:= TRUE
  391.               END
  392.             ELSE
  393.               IF FOUND
  394.                  THEN
  395.                    BEGIN
  396.                      ISNAME:= POINTER^.ISNAME;
  397.                      INDEX:= POINTER^.INDEX;
  398.                      DONE:= TRUE
  399.                    END
  400.             ELSE POINTER:= POINTER^.NEXT_WORD
  401. END;    { PROCEDURE SEARCH }
  402. {*****************************************************************************}
  403. {====                                                                     ====}
  404. {====     END OF HASH AND SPELLING TABLE PROCEDURES AND FUNCTIONS         ====}
  405. {=============================================================================}
  406. {=============================================================================}
  407.  
  408. {*****************************************************************************}
  409. {* PROCEDURE INITIALIZE - SETS UP SYSTEM AND ERASES OLD ERROR AND TEMP FILES *}
  410. {*****************************************************************************}
  411. PROCEDURE INITIALIZE;
  412. { GLOBAL CONSTANTS - MAXKEY, MAXCHARS                                      }
  413. { GLOBAL VARIABLES - HASHTABLE: HASHTABLETYPE; SPELLTABLE: SPELLTABLETYPE; }
  414. {                    TOTALCHARS, LINENUM, NAMES: INTEGER;                  }
  415. {                    ASCII, SPECIAL, INVISIBLE, LETTERS,                   }
  416. {                    DIGITS, ALPHANUMERIC, SEPARATORS: CHARSET             }
  417. CONST
  418.      F = FALSE;
  419. VAR
  420.    I: INTEGER;
  421.    FIL: FILE;
  422. BEGIN
  423. {-------------      INITIALIZE THE SPELLING AND HASH TABLES      -------------}
  424.      FOR I:= 1 TO MAXKEY DO
  425.          HASHTABLE[I]:= NIL;
  426.      FOR I:= 1 TO MAXCHARS DO
  427.          SPELLTABLE[I]:= #0;
  428. {----------         ERASE OLD ERROR AND CODE OUTPUT FILES         ------------}
  429.      ERROPENED:= FALSE;       { INITIALIZE ERRORFILE VARIABLE }
  430.      IF EXIST('ERROR1.')
  431.         THEN
  432.             BEGIN
  433.                  ASSIGN(FIL,'ERROR1.');
  434.                  ERASE(FIL)
  435.             END;
  436.      IF EXIST('TEMP1.')
  437.         THEN
  438.             BEGIN
  439.                  ASSIGN(FIL,'TEMP1.');
  440.                  ERASE(FIL)
  441.             END;
  442. {---------------       INITIALIZE THE COUNTING VARIABLES       ---------------}
  443.      TOTALCHARS:= 0;
  444.      NAMES:= 100;       { 101 WILL BE THE FIRST NAME ORDINAL VALUE }
  445.      LINENUM:= 0;
  446. {--------------        ENTER STANDARD WORDS TO THE TABLES       --------------}
  447.      DEFINE(F,'ARRAY',ORD(ARRAY1),5);       DEFINE(F,'BEGIN',ORD(BEGIN1),5);
  448.      DEFINE(F,'BOOLEAN',ORD(BOOLEAN1),7);   DEFINE(F,'CALL',ORD(CALL1),4);
  449.      DEFINE(F,'CONST',ORD(CONST1),5);       DEFINE(F,'DO',ORD(DO1),2);
  450.      DEFINE(F,'END',ORD(END1),3);           DEFINE(F,'FALSE',ORD(FALSE1),5);
  451.      DEFINE(F,'FI',ORD(FI1),2);             DEFINE(F,'IF',ORD(IF1),2);
  452.      DEFINE(F,'INTEGER',ORD(INTEGER1),7);   DEFINE(F,'OD',ORD(OD1),2);
  453.      DEFINE(F,'PROC',ORD(PROC1),4);         DEFINE(F,'READ',ORD(READ1),4);
  454.      DEFINE(F,'SKIP',ORD(SKIP1),4);         DEFINE(F,'TRUE',ORD(TRUE1),4);
  455.      DEFINE(F,'WRITE',ORD(WRITE1),5);
  456. {--------------       INITIALIZE THE CHARACTER SETS       --------------------}
  457.      ASCII:= [#0..#255];
  458.      INVISIBLE:= [#0..#31] + [#127] - [#10,#26];
  459.      LETTERS:= ['A'..'Z'] +['_'];
  460.      DIGITS:= ['0'..'9'];
  461.      ALPHANUMERIC:= LETTERS + DIGITS;
  462.      SEPARATORS:= [' ',#10,'$'];
  463.      SPECIAL:= ['.',',','~','[',']','(',')','\','/','*','|','&',';','+','-',
  464.                 '=',':','<','>'];
  465. {----------   SET UP SCREEN AND OPEN THE DISKS FILES FOR I/O  ----------------}
  466.      CLRSCR;
  467.      WRITELN(
  468. 'PL SCANNER - SCANS PL SOURCE CODE AND CONVERTS IT TO CODE FOR THE PL PARSER'
  469.      );
  470.      LOWVIDEO;
  471.      WRITE('AUTHOR:');
  472.      NORMVIDEO;
  473.      WRITE(' JAY MONFORT               ');
  474.      LOWVIDEO;
  475.      WRITE('FOR:');
  476.      NORMVIDEO;
  477.      WRITELN(' MATH 434, COMPILER DESIGN');
  478.      LOWVIDEO;
  479.      WRITE('DATE:');
  480.      NORMVIDEO;
  481.      WRITELN(' SEPTEMBER 25, 1986');
  482.      WRITELN; WRITELN;
  483.      OPEN_SOURCE;                      { OPEN SOURCE AND      }
  484.      GOTOXY(20,9);
  485.      LOWVIDEO;
  486.      WRITE('LINE NUMBER: ');
  487.      NORMVIDEO;
  488.      OPEN_CODE                         {   CODE FILES....     }
  489. END;    { PROCEDURE INITIALIZE }
  490. {*****************************************************************************}
  491.  
  492. {*****************************************************************************}
  493. {*****     PROCEDURE FINALIZE - CLOSES UP ALL THE DISK FILES             *****}
  494. {*****************************************************************************}
  495. PROCEDURE FINALIZE;
  496. VAR
  497.    CHA: CHAR;
  498. BEGIN
  499.      CLOSE(SOURCEFILE);                { CLOSE UP THE FILES.  }
  500.      FLUSH(CODEFILE);
  501.      CLOSE(CODEFILE);
  502.      IF ERROPENED
  503.         THEN
  504.           BEGIN
  505.             FLUSH(ERRFILE);
  506.             CLOSE(ERRFILE);
  507.             GOTOXY(10,11);
  508.             WRITE('ERRORS FOUND IN SOURCE CODE - FILE ERROR1 EXISTS'^G^G);
  509.             GOTOXY(20,13);
  510.             WRITE('CONTINUE??=(Y/N)=>');
  511.             REPEAT
  512.                   READ(KBD,CHA)
  513.             UNTIL UPCASE(CHA) IN ['Y','N'];
  514.             IF UPCASE(CHA) = 'N'
  515.                THEN HALT(100)
  516.           END
  517. END;   { PROCEDURE FINALIZE }
  518. {*****************************************************************************}
  519.  
  520.  
  521. {=============================================================================}
  522. {=============================================================================}
  523. {====            MAIN SCANNING FUNCTIONS AND PROCEDURES                   ====}
  524. {====                                                                     ====}
  525. {*****************************************************************************}
  526. {****  FUNCTION NEXTCHAR - RETURNS THE NEXT CHARACTER IN THE SOURCE CODE  ****}
  527. {*****************************************************************************}
  528. FUNCTION NEXTCHAR: CHAR;
  529. { GLOBAL VARIABLES - SOURCEFILE: TEXT;   ASCII, INVISIBLE: CHARSET }
  530. VAR
  531.    CHA: CHAR;
  532. BEGIN
  533.      REPEAT
  534.          READ(SOURCEFILE,CHA)
  535.      UNTIL CHA IN (ASCII - INVISIBLE);
  536.      NEXTCHAR:= UPCASE(CHA)
  537. END;    { FUNCTION NEXTCHAR }
  538. {*****************************************************************************}
  539.  
  540. {*****************************************************************************}
  541. {**** PROCEDURE EMIT, EMIT1 AND EMIT2 OUTPUT CODE NUMBERS TO THE CODE FILE****}
  542. {*****************************************************************************}
  543. { GLOBAL VARIABLE - CODEFILE: TEXT }
  544. PROCEDURE EMIT(VALUE: INTEGER);
  545. BEGIN
  546.      WRITELN(CODEFILE,VALUE:8)
  547. END;
  548.  
  549. {-----------------------------------------------------------------------------}
  550.  
  551. PROCEDURE EMIT1(VALUE: INTEGER);
  552. BEGIN
  553.      WRITE(CODEFILE,VALUE:8)
  554. END;
  555.  
  556. {-----------------------------------------------------------------------------}
  557.  
  558. PROCEDURE EMIT2(VALUE1, VALUE2: INTEGER);
  559. BEGIN
  560.      EMIT1(VALUE1);
  561.      EMIT(VALUE2)
  562. END;
  563. {*****************************************************************************}
  564.  
  565. {*****************************************************************************}
  566. {****        PROCEDURE NEWLINE - INCREMENTS LINENUM, EMITS NEWLINE        ****}
  567. {*****************************************************************************}
  568. PROCEDURE NEWLINE;
  569. { GLOBAL VARIABLE - CH: CHAR }
  570. BEGIN
  571.      CH:= NEXTCHAR;
  572.      LINENUM:= SUCC(LINENUM);
  573.      GOTOXY(33,9);
  574.      WRITE(LINENUM:5);
  575.      EMIT2(ORD(NEWLINE1),LINENUM)
  576. END;    { PROCEDURE NEWLINE }
  577. {*****************************************************************************}
  578.  
  579. {*****************************************************************************}
  580. {****            PROCEDURE COMMENT - SKIPS THROUGH COMMENTS               ****}
  581. {*****************************************************************************}
  582. PROCEDURE COMMENT;
  583. { GLOBAL VARIABLE - CH: CHAR }
  584. BEGIN
  585.      REPEAT
  586.            CH:= NEXTCHAR
  587.      UNTIL CH IN [#10,#26];
  588.      IF CH = #10
  589.         THEN NEWLINE
  590. END;    { PROCEDURE COMMENT }
  591. {*****************************************************************************}
  592.  
  593. {*****************************************************************************}
  594. {*** PROCEDURE SKIP_SEPARATORS - SKIPS THROUGH SPACES, COMMENTS AND EOLNS  ***}
  595. {*****************************************************************************}
  596. PROCEDURE SKIP_SEPARATORS;
  597. { GLOBAL VARIABLES - CH: CHAR; SEPARATORS: CHARSET }
  598. BEGIN
  599.      WHILE CH IN SEPARATORS DO
  600.            IF CH = ' '
  601.               THEN CH:= NEXTCHAR
  602.               ELSE
  603.                 IF CH = #10
  604.                    THEN NEWLINE
  605.               ELSE COMMENT
  606. END;   { PROCEDURE SKIP_SEPARATORS }
  607. {*****************************************************************************}
  608.  
  609. {*****************************************************************************}
  610. {PROCEDURE SCAN_WORDS GETS A STRING OF ALPHANUMERICS AND FEEDS IT TO SEARCHER }
  611. {*****************************************************************************}
  612. PROCEDURE SCAN_WORDS;
  613. { GLOBAL VARIABLES - CH: CHAR; ALPHANUMERIC: CHARSET }
  614. VAR
  615.    WORD_LENGTH, INDEX: INTEGER;
  616.    THE_WORD: WRKSTRING;
  617.    ISNAME: BOOLEAN;
  618. BEGIN
  619.      WORD_LENGTH:= 0;
  620.      WHILE CH IN ALPHANUMERIC DO
  621.        BEGIN
  622.          IF WORD_LENGTH < 80          { MAKE SURE IT FITS IN THE STRING }
  623.             THEN
  624.               BEGIN
  625.                 WORD_LENGTH:= SUCC(WORD_LENGTH);
  626.                 THE_WORD[WORD_LENGTH]:= CH
  627.               END;
  628.          CH:= NEXTCHAR
  629.        END;
  630.      SEARCH(THE_WORD,ISNAME,INDEX,WORD_LENGTH);
  631.      IF ISNAME
  632.         THEN EMIT2(ORD(NAME1),INDEX)
  633.         ELSE EMIT(INDEX)
  634. END;   { PROCEDURE SCAN_WORDS }
  635. {*****************************************************************************}
  636.  
  637. {*****************************************************************************}
  638. { PROCEDURE SCAN_NUMERALS - CHECKS A SEQUENCE OF DIGITS AND MAKES AN INTEGER  }
  639. {*****************************************************************************}
  640. PROCEDURE SCAN_NUMERALS;
  641. { GLOBAL VARIABLES - CH: CHAR; DIGITS: CHARSET }
  642. VAR
  643.    VALUE: INTEGER;
  644.    DIGIT: 0..9;
  645. BEGIN
  646.      VALUE:= 0;
  647.      WHILE CH IN DIGITS DO
  648.        BEGIN
  649.          DIGIT:= ORD(CH) - ORD('0');
  650.          IF VALUE <= (MAXINT - DIGIT) DIV 10
  651.             THEN
  652.               BEGIN
  653.                 VALUE:= VALUE*10 + DIGIT;
  654.                 CH:= NEXTCHAR
  655.               END
  656.             ELSE
  657.               BEGIN
  658.                 ERROR(NUMERAL3);
  659.                 WHILE CH IN DIGITS DO
  660.                   CH:= NEXTCHAR
  661.               END
  662.        END;
  663.      EMIT2(ORD(NUMERAL1),VALUE)
  664. END;   { SCAN_NUMERALS }
  665. {*****************************************************************************}
  666.  
  667. {*****************************************************************************}
  668. {*** PROCEDURE SPECIAL_SYMBOLS - LOOKS FOR AND IDENTIFIES SPECIAL SYMBOLS  ***}
  669. {*****************************************************************************}
  670. PROCEDURE SPECIAL_SYMBOLS;
  671. { GLOBAL VARIABLE - CH: CHAR }
  672. BEGIN
  673.      CASE CH OF
  674.           '&': BEGIN
  675.                  CH:= NEXTCHAR;
  676.                  EMIT(ORD(AND1))
  677.                END;
  678.           '-': BEGIN
  679.                  CH:= NEXTCHAR;
  680.                  IF CH = '>'
  681.                     THEN
  682.                       BEGIN
  683.                         CH:= NEXTCHAR;
  684.                         EMIT(ORD(ARROW1))
  685.                       END
  686.                     ELSE EMIT(ORD(MINUS1))
  687.                END;
  688.           ':': BEGIN
  689.                  CH:= NEXTCHAR;
  690.                  IF CH = '='
  691.                     THEN
  692.                       BEGIN
  693.                         CH:= NEXTCHAR;
  694.                         EMIT(ORD(BECOMES1))
  695.                       END
  696.                     ELSE
  697.                       BEGIN
  698.                         ERROR(UNKNOWN3);
  699.                         EMIT(ORD(UNKNOWN1))
  700.                       END
  701.                END;
  702.           ',': BEGIN
  703.                  CH:= NEXTCHAR;
  704.                  EMIT(ORD(COMMA1))
  705.                END;
  706.           '/': BEGIN
  707.                  CH:= NEXTCHAR;
  708.                  EMIT(ORD(DIV1))
  709.                END;
  710.           '=': BEGIN
  711.                  CH:= NEXTCHAR;
  712.                  EMIT(ORD(EQUAL1))
  713.                END;
  714.           '>': BEGIN
  715.                  CH:= NEXTCHAR;
  716.                  EMIT(ORD(GREATER1))
  717.                END;
  718.           '[': BEGIN
  719.                  CH:= NEXTCHAR;
  720.                  IF CH = ']'
  721.                     THEN
  722.                       BEGIN
  723.                         CH:= NEXTCHAR;
  724.                         EMIT(ORD(PAIRED_BRACKETS1))
  725.                       END
  726.                     ELSE EMIT(ORD(LEFT_BRACKET1))
  727.                END;
  728.           '(': BEGIN
  729.                  CH:= NEXTCHAR;
  730.                  EMIT(ORD(LEFT_PAREN1))
  731.                END;
  732.           '<': BEGIN
  733.                  CH:= NEXTCHAR;
  734.                  EMIT(ORD(LESS1))
  735.                END;
  736.           '\': BEGIN
  737.                  CH:= NEXTCHAR;
  738.                  EMIT(ORD(MOD1))
  739.                END;
  740.           '*': BEGIN
  741.                  CH:= NEXTCHAR;
  742.                  EMIT(ORD(MULT1))
  743.                END;
  744.           '~': BEGIN
  745.                  CH:= NEXTCHAR;
  746.                  EMIT(ORD(NOT1))
  747.                END;
  748.           '|': BEGIN
  749.                  CH:= NEXTCHAR;
  750.                  EMIT(ORD(OR1))
  751.                END;
  752.           '.': BEGIN
  753.                  CH:= NEXTCHAR;
  754.                  EMIT(ORD(PERIOD1))
  755.                END;
  756.           '+': BEGIN
  757.                  CH:= NEXTCHAR;
  758.                  EMIT(ORD(PLUS1))
  759.                END;
  760.           ']': BEGIN
  761.                  CH:= NEXTCHAR;
  762.                  EMIT(ORD(RIGHT_BRACKET1))
  763.                END;
  764.           ')': BEGIN
  765.                  CH:= NEXTCHAR;
  766.                  EMIT(ORD(RIGHT_PAREN1))
  767.                END;
  768.           ';': BEGIN
  769.                  CH:= NEXTCHAR;
  770.                  EMIT(ORD(SEMICOLON1))
  771.                END
  772.      END     { CASE }
  773. END;    { PROCEDURE SPECIAL_SYMBOLS }
  774. {*****************************************************************************}
  775.  
  776. {*****************************************************************************}
  777. {****     PROCEDURE NEXTSYMBOL - LOOKS AT THE NEXT CHARACTER INPUT        ****}
  778. {*****************************************************************************}
  779. PROCEDURE NEXTSYMBOL;
  780. { GLOBAL VARIABLES - CH: CHAR; LETTERS, DIGITS, SPECIAL: CHARSET }
  781. BEGIN
  782.      SKIP_SEPARATORS;
  783.      IF CH IN LETTERS
  784.              THEN SCAN_WORDS
  785.      ELSE IF CH IN DIGITS
  786.              THEN SCAN_NUMERALS
  787.      ELSE IF CH IN SPECIAL
  788.              THEN SPECIAL_SYMBOLS
  789.      ELSE IF CH <> #26
  790.              THEN
  791.                BEGIN
  792.                  CH:= NEXTCHAR;
  793.                  EMIT(ORD(UNKNOWN1));
  794.                  ERROR(UNKNOWN3)
  795.                END
  796. END;   { PROCEDURE NEXTSYMBOL }
  797. {*****************************************************************************}
  798.  
  799. {*****************************************************************************}
  800. {*****       PROCEDURE SCAN - STARTS AND FINISHES THE SCAN               *****}
  801. {*****************************************************************************}
  802. PROCEDURE SCAN;
  803. BEGIN
  804.      NEWLINE;                         { GET FIRST CHARACTER, AND INC LINENUM  }
  805.      WHILE CH <> #26 DO               { AND FEED  IT TO      }
  806.        NEXTSYMBOL;                    {   NEXTSYMBOL.        }
  807.      EMIT(ORD(ENDTEXT1))
  808. END;     { PROCEDURE SCAN }
  809. {*****************************************************************************}
  810. {====                                                                     ====}
  811. {====            END OF MAIN SCANNING PROCEDURES                          ====}
  812. {=============================================================================}
  813. {=============================================================================}
  814.  
  815. {=============================================================================}
  816. {=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=}
  817. {*****************************************************************************}
  818. BEGIN   { PROGRAM PL_SCAN }
  819.      INITIALIZE;
  820.      SCAN;
  821.      FINALIZE
  822. END.   { PROGRAM PL_SCAN }
  823. {*****************************************************************************}
  824. {*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*}
  825. {=============================================================================}
  826.