home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / interpre / pl / parser.pas < prev    next >
Pascal/Delphi Source File  |  1986-12-14  |  50KB  |  1,629 lines

  1. PROGRAM PARSER;
  2. {=============================================================================}
  3. {  PROGRAM: PARSER V - PL PARSER WITH SYNTAX CHECKING, ERROR RECOVERY,        }
  4. {                     SCOPE ANALYSIS, TYPE ANALYSIS, CODE GENERATION          }
  5. {  AUTHOR: JAY MONFORT                     FOR: MATH 434 - COMPILER DESIGN    }
  6. {  DATE: DECEMBER 4, 1986                                                     }
  7. {=============================================================================}
  8. {$K-,D-,V-,C-}
  9.  { NO CTRL-C CHECK, NO STACK CHECK, NO VAR LENGTH CHECK, NO DEVICE CHECK }
  10.  
  11. CONST
  12.      NO_NAME = 100;
  13.  
  14.      MAXLABEL = 1000;
  15.  
  16. TYPE
  17.     SYMBOL_TYPE =
  18.           (AND1,ARRAY1,ARROW1,BECOMES1,BEGIN1,{ 5 }BOOLEAN1,CALL1,COMMA1,CONST1,
  19.            DIV1,{ 10 }DO1,END1,ENDTEXT1,EQUAL1,FALSE1,{ 15 }FI1,GREATER1,IF1,
  20.            INTEGER1,LEFT_BRACKET1,{ 20 }LEFT_PAREN1,LESS1,MINUS1,MOD1,MULT1,
  21.            { 25 }NAME1,NEWLINE1,NOT1,NUMERAL1,OD1,{ 30 }OR1,PAIRED_BRACKETS1,
  22.            PERIOD1,PLUS1,PROC1,{ 35 }READ1,RIGHT_BRACKET1,RIGHT_PAREN1,
  23.            SEMICOLON1,SKIP1,{ 40 }TRUE1,UNKNOWN1,WRITE1);
  24.  
  25.  
  26.     RULE_TYPE =
  27.         (PROGRAM2,BLOCK2,DEFINITION_PART2,DEFINITION2,CONSTANT_DEFINITION2,
  28.          { 5 }VARIABLE_DEFINITION2,ARRAY_GROUP2,ARRAY_TAIL2,
  29.          TYPE_SYMBOL2,VARIABLE_LIST2,PROCEDURE_DEFINITION2,
  30.          STATEMENT_PART2,{ 12 }STATEMENT2,
  31.          EMPTY_STATEMENT2,READ_STATEMENT2,VARIABLE_ACCESS_LIST2,
  32.          WRITE_STATEMENT2,{ 17 }EXPRESSION_LIST2,ASSIGNMENT_STATEMENT2,
  33.          PROCEDURE_STATEMENT2,IF_STATEMENT2,DO_STATEMENT2,
  34.          { 22 }GUARDED_COMMAND_LIST2,GUARDED_COMMAND2,EXPRESSION2,
  35.          PRIMARY_OPERATOR2,PRIMARY_EXPRESSION2,{ 27 }RELATIONAL_OPERATOR2,
  36.          SIMPLE_EXPRESSION2,ADDING_OPERATOR2,TERM2,MULTIPLYING_OPERATOR2,
  37.          { 32 }FACTOR2,VARIABLE_ACCESS2,INDEXED_SELECTOR2,CONSTANT2,NUMERAL2,
  38.          { 37 }BOOLEAN_SYMBOL2,NAME2);
  39.  
  40.  
  41.     CLASS = (ARRAY3,CONST3,PROC3,STANDARD_PROC3,STANDARD_TYPE3,UNDEFINED3,
  42.              VAR3);
  43.  
  44.  
  45.     ERRTYPE = (SYNTAX4,UNDEFINED4,AMBIGUOUS4,TYPE4,KIND4,UNEQUAL4,RANGE4);
  46.  
  47.  
  48.     OPERATION_PART =
  49.              (ADD5,AND5,ARROW5,ASSIGN5,BAR5,CALL5,CONSTANT5,DIVIDE5,END_PROC5,
  50.               END_PROG5,EQUAL5,FI5,GREATER5,INDEX5,LESS5,MINUS5,MODULO5,
  51.               MULTIPLY5,NOT5,OR5,PROC5,PROG5,READ5,SUBTRACT5,VALUE5,VARIABLE5,
  52.               WRITE5);
  53.  
  54.  
  55.     IF_DO_TYPE = (IF_,DO_);
  56.  
  57.     RANGE = 1..MAXLABEL;
  58.  
  59.     OBJECT_POINTER = ^OBJECT_RECORD;
  60.  
  61.     OBJECT_RECORD = RECORD
  62.                       NAME: INTEGER;
  63.                       PREVIOUS: OBJECT_POINTER;
  64.                       CASE KIND: CLASS OF
  65.                                 ARRAY3: ( UPPER_BOUND,
  66.                                           ARRAY_LEVEL,
  67.                                           ARRAY_DISPLACEMENT: INTEGER;
  68.                                           ELEMENT_TYPE,
  69.                                           INDEX_TYPE:  OBJECT_POINTER );
  70.                                 CONST3: ( CONST_VALUE: INTEGER;
  71.                                           CONST_TYPE: OBJECT_POINTER );
  72.                                  PROC3: ( PROC_LEVEL: INTEGER;
  73.                                           PROC_LABEL: RANGE );
  74.                         STANDARD_PROC3: ();
  75.                         STANDARD_TYPE3: ();
  76.                             UNDEFINED3: ();
  77.                                   VAR3: ( VAR_TYPE: OBJECT_POINTER;
  78.                                           VAR_LEVEL,
  79.                                           VAR_DISPLACEMENT: INTEGER );
  80.                     END;
  81.  
  82.     BLOCK_POINTER = ^BLOCK_RECORD;
  83.  
  84.     BLOCK_RECORD = RECORD
  85.                      PREVIOUS_BLOCK: BLOCK_POINTER;
  86.                      LAST_OBJECT: OBJECT_POINTER
  87.                    END;
  88.  
  89.     SYMBOLS = SET OF SYMBOL_TYPE;
  90.  
  91.     SYMBOL_SET_ARRAY = ARRAY[RULE_TYPE] OF SYMBOLS;
  92.  
  93.     OPERATIONS = SET OF OPERATION_PART;
  94.  
  95.     ASSEMBLY_TABLE = ARRAY[RANGE] OF INTEGER;
  96.  
  97.     TEMP_ARRAY = ARRAY[1..1667,1..3] OF INTEGER;
  98.  
  99.     WRKSTRING = STRING[80];
  100.  
  101. {-----------------------------------------------------------------------------}
  102.  
  103. CONST
  104.     LONGSYMBOLS: SYMBOLS = [NUMERAL1,NAME1];
  105.  
  106.     ONE_OPERANDS: OPERATIONS = [ARROW5,ASSIGN5,BAR5,CONSTANT5,DIVIDE5,FI5,
  107.                                 MODULO5,READ5,WRITE5];
  108.  
  109.     TWO_OPERANDS: OPERATIONS = [CALL5,INDEX5,PROC5,PROG5,VARIABLE5];
  110.  
  111. {-----------------------------------------------------------------------------}
  112.  
  113. VAR
  114.     FIRST: SYMBOL_SET_ARRAY;         { FIRST AND FOLLOW SYMBOLS FOR RULE_TYPES}
  115.  
  116.     SYMBOL: SYMBOL_TYPE;             { THE CURRENT SYMBOL }
  117.  
  118.     LABEL_NUMBER,                    { THE NEXT LABEL NUMBER IN ASSEMBLY TABLE}
  119.     EXIT_LABEL: RANGE;               { USED TO EXIT IF AND DO LOOPS           }
  120.  
  121.     ADDRESS,                         { THE CURRENT ADDRESS FOR CODE GENERATION}
  122.     ROW,                             { USED IN FILLING THE TEMP TABLE }
  123.     BLOCK_NUM,                       { THE CURRENT BLOCK LEVEL NUMBER }
  124.     ARGUMENT,                        { INTEGER WITH LONG SYMBOLS }
  125.     LINENUM: INTEGER;                { INTEGER WITH NEWLINE1     }
  126.  
  127.     TABLE: ASSEMBLY_TABLE;           { USED FOR STORING LABEL ADDRESSES }
  128.  
  129.     TEMP: TEMP_ARRAY;                { CONTAINS THE FIRST PASS CODE }
  130.  
  131.     BLOCK_LEVEL: BLOCK_POINTER;      { POINTER TO CURRENT BLOCK }
  132.  
  133.     INTEGER_TYPE,                    { POINTERS TO STANDARD TYPES }
  134.     BOOLEAN_TYPE,
  135.     UNIVERSAL_TYPE: OBJECT_POINTER;
  136.  
  137.     TEMP1FILE,                       { TEMP1 FROM SCANNER, TEMP2 FROM PARSER }
  138.     TEMP2FILE: TEXT[$2800];          { 10K BUFFERS FOR TEMP FILES }
  139.  
  140.     ERRFILE: TEXT[$800];             {  2K BUFFER FOR ERROR FILES }
  141.  
  142.     ERROPENED: BOOLEAN;              { TELLS IF THE ERROR FILE HAS BEEN USED }
  143.  
  144.  
  145. {-----------------------------------------------------------------------------}
  146. {----          FUNCTION EXIST - RETURNS TRUE IF A FILE IS ON DISK         ----}
  147. {-----------------------------------------------------------------------------}
  148. FUNCTION EXIST(FILENAME: WRKSTRING): BOOLEAN;
  149. VAR
  150.    FIL: FILE;
  151. BEGIN
  152.      ASSIGN(FIL,FILENAME);
  153.      {$I-}
  154.      RESET(FIL);
  155.      {$I+}
  156.      EXIST:= (IORESULT = 0);
  157.      IF IORESULT = 0
  158.         THEN CLOSE(FIL)
  159. END;    { FUNCTION EXIST }
  160. {-----------------------------------------------------------------------------}
  161.  
  162. {=============================================================================}
  163. {====      THE FOLLOWING PROCEDURES OPEN THE INPUT AND OUTPUT FILES       ====}
  164. {====                                                                     ====}
  165. {-----------------------------------------------------------------------------}
  166. {----        PROCEDURE OPEN_TEMP1 - OPENS THE TEMP1 CODE FILE             ----}
  167. {-----------------------------------------------------------------------------}
  168. PROCEDURE OPEN_TEMP1;
  169. { GLOBAL VARIABLE - TEMP1FILE: TEXT }
  170. BEGIN
  171.      IF EXIST('TEMP1.')
  172.         THEN
  173.             BEGIN
  174.                  ASSIGN(TEMP1FILE,'TEMP1.');
  175.                  RESET(TEMP1FILE);
  176.                  LOWVIDEO;
  177.                  GOTOXY(20,8);
  178.                  WRITE('PARSING ');
  179.                  NORMVIDEO;
  180.                  WRITELN('TEMP1')
  181.             END
  182.         ELSE
  183.             BEGIN
  184.                  WRITELN;
  185.                  WRITELN('UNKNOWN DISK ERROR OR TEMP1. NOT FOUND.');
  186.                  HALT(100)      { USED FOR ERRORLEVEL IN BATCH FILE }
  187.             END
  188. END;    { PROCEDURE OPEN_TEMP1 }
  189. {-----------------------------------------------------------------------------}
  190.  
  191. {-----------------------------------------------------------------------------}
  192. {----         PROCEDURE OPEN_TEMP2 - OPENS THE CODE FILE FOR OUTPUT       ----}
  193. {-----------------------------------------------------------------------------}
  194. PROCEDURE OPEN_TEMP2;
  195. { GLOBAL VARIABLE - TEMP2FILE: TEXT }
  196. BEGIN
  197.      ASSIGN(TEMP2FILE,'TEMP2.');
  198.      {$I-}
  199.      REWRITE(TEMP2FILE);
  200.      {$I+}
  201.      IF IORESULT <> 0
  202.        THEN
  203.          BEGIN
  204.            WRITELN;
  205.            WRITELN('UNKNOWN DISK ERROR');
  206.            HALT(100)      { PICKED UP AS ERRORLEVEL BY DOS }
  207.          END
  208. END;
  209. {-----------------------------------------------------------------------------}
  210. {====                 END OF FILE OPENING PROCEDURES                      ====}
  211. {=============================================================================}
  212.  
  213.  
  214. {=============================================================================}
  215. {====         THE FOLLOWING ARE THE ERROR FILE PROCEDURES                 ====}
  216. {                                                                             }
  217. {----              PROCEDURE OPENERROR - OPENS THE ERROR FILE             ----}
  218. {-----------------------------------------------------------------------------}
  219. PROCEDURE OPENERROR(FILENAME: WRKSTRING);
  220. { GLOBAL VARIABLE - ERRFILE: TEXT }
  221. BEGIN
  222.      ASSIGN(ERRFILE,FILENAME);
  223.      {$I-}
  224.      REWRITE(ERRFILE);
  225.      {$I+}
  226.      IF IORESULT <> 0
  227.         THEN
  228.           BEGIN
  229.              WRITELN('UNKNOWN DISK ERROR');
  230.              HALT(100)
  231.           END
  232. END;    { PROCEDURE OPENERROR }
  233. {-----------------------------------------------------------------------------}
  234.  
  235. {-----------------------------------------------------------------------------}
  236. {----            PROCEDURE ERROR - HANDLES THE PARSER ERRORS              ----}
  237. {-----------------------------------------------------------------------------}
  238. PROCEDURE ERROR(KIND_OF_ERROR: ERRTYPE);
  239. { GLOBAL VARIABLE - ERRFILE: TEXT; LINENUM: INTEGER; ERROPENED: BOOLEAN }
  240. BEGIN
  241.    IF NOT ERROPENED
  242.      THEN
  243.        BEGIN
  244.          ERROPENED:= TRUE;
  245.          OPENERROR('ERROR2.');
  246.        END;
  247.    WRITE(ERRFILE,' LINE:',LINENUM:5);
  248.    CASE KIND_OF_ERROR OF
  249.         SYNTAX4: WRITELN(ERRFILE,' SYNTAX ERROR');
  250.      UNDEFINED4: WRITELN(ERRFILE,' SEMANTIC ERROR - UNDEFINED NAME');
  251.      AMBIGUOUS4: WRITELN(ERRFILE,' SEMANTIC ERROR - NAME ALREADY DEFINED');
  252.           TYPE4: WRITELN(ERRFILE,' TYPE ERROR - INCOMPATIBLE TYPE(S)');
  253.           KIND4: WRITELN(ERRFILE,' KIND ERROR - THIS TYPE NOT ACCEPTABLE HERE');
  254.        UNEQUAL4: WRITELN(ERRFILE,' SYNTAX ERROR - UNEQUAL VARIABLES AND ASSIGNMENTS');
  255.          RANGE4: WRITELN(ERRFILE,' SYNTAX ERROR - NEGATIVE VALUES NOT ALLOWED IN ARRAY INDICES')
  256.    END   { CASE }
  257. END;    { PROCEDURE ERROR }
  258. {-----------------------------------------------------------------------------}
  259. {====                END OF ERROR FILE PROCEDURES                         ====}
  260. {=============================================================================}
  261.  
  262.  
  263. {-----------------------------------------------------------------------------}
  264. {        PROCEDURE MAKE_FIRSTS - MAKES THE FIRST SETS FOR RULE_TYPES          }
  265. {-----------------------------------------------------------------------------}
  266. PROCEDURE MAKE_FIRSTS;
  267. { GLOBAL VARIABLE - FIRST: SYMBOL_SET_ARRAY }
  268. BEGIN
  269.      FIRST[NAME2]:= [NAME1];
  270.      FIRST[BOOLEAN_SYMBOL2]:= [FALSE1,TRUE1];
  271.      FIRST[NUMERAL2]:= [NUMERAL1];
  272.      FIRST[CONSTANT2]:= FIRST[NAME2] + FIRST[BOOLEAN_SYMBOL2] +
  273.                         FIRST[NUMERAL2] + [MINUS1];
  274.      FIRST[INDEXED_SELECTOR2]:= [LEFT_BRACKET1];
  275.      FIRST[VARIABLE_ACCESS2]:= [NAME1];
  276.      FIRST[FACTOR2]:= FIRST[CONSTANT2] + FIRST[VARIABLE_ACCESS2] +
  277.                       [LEFT_PAREN1,NOT1];
  278.      FIRST[MULTIPLYING_OPERATOR2]:= [MULT1,MOD1,DIV1];
  279.      FIRST[TERM2]:= FIRST[FACTOR2];
  280.      FIRST[ADDING_OPERATOR2]:= [PLUS1,MINUS1];
  281.      FIRST[SIMPLE_EXPRESSION2]:= FIRST[TERM2] + [MINUS1];
  282.      FIRST[RELATIONAL_OPERATOR2]:= [LESS1,EQUAL1,GREATER1];
  283.      FIRST[PRIMARY_EXPRESSION2]:= FIRST[SIMPLE_EXPRESSION2];
  284.      FIRST[PRIMARY_OPERATOR2]:= [AND1,OR1];
  285.      FIRST[EXPRESSION2]:= FIRST[PRIMARY_EXPRESSION2];
  286.      FIRST[GUARDED_COMMAND2]:= FIRST[EXPRESSION2];
  287.      FIRST[GUARDED_COMMAND_LIST2]:= FIRST[GUARDED_COMMAND2];
  288.      FIRST[DO_STATEMENT2]:= [DO1];
  289.      FIRST[IF_STATEMENT2]:= [IF1];
  290.      FIRST[PROCEDURE_STATEMENT2]:= [CALL1];
  291.      FIRST[VARIABLE_ACCESS_LIST2]:= FIRST[VARIABLE_ACCESS2];
  292.      FIRST[ASSIGNMENT_STATEMENT2]:= FIRST[VARIABLE_ACCESS_LIST2];
  293.      FIRST[EXPRESSION_LIST2]:= FIRST[EXPRESSION2];
  294.      FIRST[WRITE_STATEMENT2]:= [WRITE1];
  295.      FIRST[READ_STATEMENT2]:= [READ1];
  296.      FIRST[EMPTY_STATEMENT2]:= [SKIP1];
  297.      FIRST[STATEMENT2]:= FIRST[EMPTY_STATEMENT2] + FIRST[READ_STATEMENT2] +
  298.                          FIRST[WRITE_STATEMENT2] + FIRST[DO_STATEMENT2] +
  299.                          FIRST[PROCEDURE_STATEMENT2] + FIRST[IF_STATEMENT2] +
  300.                          FIRST[ASSIGNMENT_STATEMENT2];
  301.      FIRST[STATEMENT_PART2]:= FIRST[STATEMENT2];
  302.      FIRST[PROCEDURE_DEFINITION2]:= [PROC1];
  303.      FIRST[VARIABLE_LIST2]:= [NAME1];
  304.      FIRST[TYPE_SYMBOL2]:= [INTEGER1,BOOLEAN1];
  305.      FIRST[ARRAY_TAIL2]:= [COMMA1,LEFT_BRACKET1];
  306.      FIRST[ARRAY_GROUP2]:= [NAME1];
  307.      FIRST[VARIABLE_DEFINITION2]:= FIRST[TYPE_SYMBOL2];
  308.      FIRST[CONSTANT_DEFINITION2]:= [CONST1];
  309.      FIRST[DEFINITION2]:= FIRST[CONSTANT_DEFINITION2] +
  310.                           FIRST[VARIABLE_DEFINITION2] +
  311.                           FIRST[PROCEDURE_DEFINITION2];
  312.      FIRST[DEFINITION_PART2]:= FIRST[DEFINITION2];
  313.      FIRST[BLOCK2]:= [BEGIN1];
  314.      FIRST[PROGRAM2]:= FIRST[BLOCK2]
  315. END;   { PROCEDURE MAKE_FIRSTS }
  316.  
  317. {-----------------------------------------------------------------------------}
  318.  
  319. { PROCEDURES EMIT, EMIT1, EMIT2, EMIT3 - WRITE CODE TO THE TEMP ARRAY         }
  320.  
  321. PROCEDURE EMIT(ARGUMENT, COL: INTEGER);
  322. { GLOBAL VARIABLES - TEMP: TEMP_ARRAY; ROW, ADDRESS: INTEGER; }
  323. BEGIN
  324.      TEMP[ROW,COL]:= ARGUMENT;
  325.      ADDRESS:= ADDRESS + 1
  326. END;
  327.  
  328. PROCEDURE EMIT1(OPERATION: OPERATION_PART);
  329. { GLOBAL VARIABLE - ROW: INTEGER }
  330. BEGIN
  331.      ROW:= ROW + 1;
  332.      EMIT(ORD(OPERATION),1)
  333. END;
  334.  
  335. PROCEDURE EMIT2(OPERATION: OPERATION_PART; OPERAND: INTEGER);
  336. { GLOBAL VARIABLE - ROW: INTEGER }
  337. BEGIN
  338.      ROW:= ROW + 1;
  339.      EMIT(ORD(OPERATION),1);
  340.      EMIT(OPERAND,2)
  341. END;
  342.  
  343. PROCEDURE EMIT3(OPERATION: OPERATION_PART; OPERAND1, OPERAND2: INTEGER);
  344. { GLOBAL VARIABLE - ROW: INTEGER }
  345. BEGIN
  346.      ROW:= ROW + 1;
  347.      EMIT(ORD(OPERATION),1);
  348.      EMIT(OPERAND1,2);
  349.      EMIT(OPERAND2,3)
  350. END;
  351.  
  352.  
  353. { FUNCTION TYPE_LENGTH - RETURNS THE SIZE OF THE OBJECT TYPE IN INTEGERS      }
  354.  
  355. FUNCTION TYPE_LENGTH(TYPEX: OBJECT_POINTER): INTEGER;
  356. BEGIN
  357.      IF TYPEX^.KIND = STANDARD_TYPE3
  358.         THEN TYPE_LENGTH:= 1
  359.         ELSE
  360.           BEGIN
  361.             ERROR(KIND4);
  362.             TYPE_LENGTH:= 0
  363.           END
  364. END;
  365.  
  366.  
  367. { PROCEDURE NEW_LABEL - UPDATES THE LABEL NUMBER FOR THE ASSEMBLY TABLE       }
  368.  
  369. PROCEDURE NEW_LABEL(VAR NUMBER: RANGE);
  370. { GLOBAL VARIABLE - LABEL_NUMBER: RANGE }
  371. BEGIN
  372.      LABEL_NUMBER:= LABEL_NUMBER + 1;
  373.      NUMBER:= LABEL_NUMBER
  374. END;
  375.  
  376. { PROCEDURE DEFINE_ADDRESS - ASSIGNS THE CORRECT ADDRESS TO A LABEL           }
  377.  
  378. PROCEDURE DEFINE_ADDRESS(LAB_NUMBER: RANGE);
  379. { GLOBAL VARIABLES - TABLE: ASSEMBLY_TABLE; ADDRESS: INTEGER }
  380. BEGIN
  381.      TABLE[LAB_NUMBER]:= ADDRESS
  382. END;
  383.  
  384. {-----------------------------------------------------------------------------}
  385. {----    PROCEDURE NEWLINE - UPDATES THE LINE NUMBER TO THE SCREEN        ----}
  386. {-----------------------------------------------------------------------------}
  387. PROCEDURE NEWLINE;
  388. BEGIN
  389.      GOTOXY(33,9);
  390.      WRITE(LINENUM:5)
  391. END;
  392.  
  393. PROCEDURE NEW_BLOCK;
  394. { GLOBAL VARIABLES: BLOCK: BLOCK_POINTER; BLOCK_NUM: INTEGER }
  395. VAR
  396.    BLOCK: BLOCK_POINTER;
  397. BEGIN
  398.      NEW(BLOCK);
  399.      BLOCK^.PREVIOUS_BLOCK:= BLOCK_LEVEL;
  400.      BLOCK_LEVEL:= BLOCK;
  401.      BLOCK^.LAST_OBJECT:= NIL;
  402.      BLOCK_NUM:= BLOCK_NUM + 1
  403. END;    { PROCEDURE NEW_BLOCK }
  404.  
  405.  
  406. PROCEDURE END_BLOCK;
  407. VAR
  408.    OLD_BLOCK: BLOCK_POINTER;
  409.    P, Q: OBJECT_POINTER;
  410. BEGIN
  411.      OLD_BLOCK:= BLOCK_LEVEL;
  412.      BLOCK_LEVEL:= BLOCK_LEVEL^.PREVIOUS_BLOCK;
  413.      P:= OLD_BLOCK^.LAST_OBJECT;
  414.      WHILE P <> NIL DO
  415.        BEGIN
  416.          Q:= P;
  417.          P:= P^.PREVIOUS;
  418.          DISPOSE(Q)
  419.        END;
  420.      DISPOSE(OLD_BLOCK);
  421.      BLOCK_NUM:= BLOCK_NUM - 1
  422. END;
  423.  
  424.  
  425. PROCEDURE CHECK_TYPE(VAR TYPE1: OBJECT_POINTER; TYPE2: OBJECT_POINTER);
  426. BEGIN
  427.      IF TYPE1 <> TYPE2
  428.         THEN
  429.           BEGIN
  430.             IF (TYPE1 <> UNIVERSAL_TYPE) AND (TYPE2 <> UNIVERSAL_TYPE)
  431.                THEN ERROR(TYPE4);
  432.             TYPE1:= UNIVERSAL_TYPE;
  433.           END
  434. END;   { PROCEDURE CHECK_TYPE }
  435.  
  436.  
  437. PROCEDURE TYPE_ERROR(VAR TYPEX: OBJECT_POINTER);
  438. BEGIN
  439.      IF TYPEX <> UNIVERSAL_TYPE
  440.         THEN
  441.           BEGIN
  442.             ERROR(TYPE4);
  443.             TYPEX:= UNIVERSAL_TYPE
  444.           END
  445. END;   { PROCEDURE TYPE_ERROR }
  446.  
  447.  
  448.  
  449. PROCEDURE KIND_ERROR(OBJECT: OBJECT_POINTER);
  450. BEGIN
  451.      IF OBJECT^.KIND <> UNDEFINED3
  452.         THEN ERROR(KIND4)
  453. END;   { PROCEDURE KIND_ERROR }
  454.  
  455.  
  456. PROCEDURE SEARCH(NAME: INTEGER; THIS_LEVEL: BLOCK_POINTER; VAR FOUND: BOOLEAN;
  457.                  VAR OBJECT: OBJECT_POINTER);
  458. VAR
  459.    MORE: BOOLEAN;
  460. BEGIN
  461.      MORE:= TRUE;
  462.      OBJECT:= THIS_LEVEL^.LAST_OBJECT;
  463.      WHILE MORE DO
  464.         IF OBJECT = NIL
  465.            THEN
  466.              BEGIN
  467.                MORE:= FALSE;
  468.                FOUND:= FALSE
  469.              END
  470.         ELSE IF OBJECT^.NAME = NAME
  471.            THEN
  472.              BEGIN
  473.                MORE:= FALSE;
  474.                FOUND:= TRUE
  475.              END
  476.         ELSE OBJECT:= OBJECT^.PREVIOUS
  477. END;
  478.  
  479.  
  480. PROCEDURE DEFINE(NAME: INTEGER; KIND: CLASS; VAR OBJECT: OBJECT_POINTER);
  481. VAR
  482.    FOUND: BOOLEAN;
  483.    PNTR: OBJECT_POINTER;
  484. BEGIN
  485.      SEARCH(NAME,BLOCK_LEVEL,FOUND,PNTR);
  486.      IF FOUND
  487.         THEN ERROR(AMBIGUOUS4)
  488.         ELSE
  489.           BEGIN
  490.             NEW(OBJECT);
  491.             OBJECT^.NAME:= NAME;
  492.             OBJECT^.PREVIOUS:= BLOCK_LEVEL^.LAST_OBJECT;
  493.             OBJECT^.KIND:= KIND;
  494.             BLOCK_LEVEL^.LAST_OBJECT:= OBJECT
  495.           END
  496. END;   { PROCEDURE DEFINE }
  497.  
  498.  
  499. PROCEDURE FIND(NAME: INTEGER; VAR OBJECT: OBJECT_POINTER);
  500. VAR
  501.    MORE, FOUND: BOOLEAN;
  502.    THIS_LEVEL: BLOCK_POINTER;
  503. BEGIN
  504.      MORE:= TRUE;
  505.      THIS_LEVEL:= BLOCK_LEVEL;
  506.      WHILE MORE DO
  507.        BEGIN
  508.          SEARCH(NAME,THIS_LEVEL,FOUND,OBJECT);
  509.          IF FOUND OR (THIS_LEVEL^.PREVIOUS_BLOCK = NIL)
  510.             THEN MORE:= FALSE
  511.             ELSE THIS_LEVEL:= THIS_LEVEL^.PREVIOUS_BLOCK
  512.        END;
  513.      IF NOT FOUND
  514.         THEN
  515.           BEGIN
  516.             ERROR(UNDEFINED4);
  517.             DEFINE(NAME,UNDEFINED3,OBJECT)
  518.           END
  519. END;   { PROCEDURE FIND }
  520.  
  521. {-----------------------------------------------------------------------------}
  522. {----        PROCEDURE NEXTSYMBOL - READS A SYMBOL FROM TEMP1             ----}
  523. {-----------------------------------------------------------------------------}
  524. PROCEDURE NEXTSYMBOL;
  525. VAR
  526.    ORDINAL: INTEGER;
  527. BEGIN
  528.      READ(TEMP1FILE,ORDINAL);
  529.      SYMBOL:= SYMBOL_TYPE(ORDINAL);
  530.      WHILE SYMBOL = NEWLINE1 DO
  531.            BEGIN
  532.                 READ(TEMP1FILE,LINENUM);
  533.                 NEWLINE;
  534.                 READ(TEMP1FILE,ORDINAL);
  535.                 SYMBOL:= SYMBOL_TYPE(ORDINAL)
  536.            END;
  537.      IF SYMBOL IN LONGSYMBOLS
  538.         THEN READ(TEMP1FILE,ARGUMENT)
  539. END;  { PRODEDURE NEXTSYMBOL }
  540.  
  541. {-----------------------------------------------------------------------------}
  542. {-- PROCEDURE SYNTAX_ERROR - WRITES MESSAGE TO ERROR FILE AND FINDS A STOP  --}
  543. {-----------------------------------------------------------------------------}
  544. PROCEDURE SYNTAX_ERROR(STOPS: SYMBOLS);
  545. BEGIN
  546.      ERROR(SYNTAX4);
  547.      WHILE NOT (SYMBOL IN STOPS) DO
  548.         NEXTSYMBOL
  549. END;   { PROCEDURE SYNTAX_ERROR }
  550.  
  551. {-----------------------------------------------------------------------------}
  552. {---- PROCEDURE SYNTAX_CHECK - CHECKS NEXT SYMBOL TO SEE IF ITS A STOP    ----}
  553. {-----------------------------------------------------------------------------}
  554. PROCEDURE SYNTAX_CHECK(STOPS: SYMBOLS);
  555. BEGIN
  556.      IF NOT (SYMBOL IN STOPS)
  557.         THEN SYNTAX_ERROR(STOPS)
  558. END;   { PROCEDURE SYNTAX_CHECK }
  559.  
  560. {-----------------------------------------------------------------------------}
  561. {----  PROCEDURE EXPECT - CHECKS TO SEE THAT THE NEXT SYMBOL IS EXPECTED  ----}
  562. {-----------------------------------------------------------------------------}
  563. PROCEDURE EXPECT(THIS_SYMBOL: SYMBOL_TYPE; STOPS: SYMBOLS);
  564. BEGIN
  565.      IF SYMBOL = THIS_SYMBOL
  566.         THEN NEXTSYMBOL
  567.         ELSE SYNTAX_ERROR(STOPS);
  568.      SYNTAX_CHECK(STOPS)
  569. END;   { PROCEDURE EXPECT }
  570.  
  571.  
  572. PROCEDURE EXPECT_NAME(VAR NAME: INTEGER; STOPS: SYMBOLS);
  573. BEGIN
  574.      IF SYMBOL = NAME1
  575.         THEN
  576.           BEGIN
  577.             NAME:= ARGUMENT;
  578.             NEXTSYMBOL
  579.           END
  580.         ELSE
  581.           BEGIN
  582.             NAME:= NO_NAME;
  583.             SYNTAX_ERROR(STOPS)
  584.           END;
  585.      SYNTAX_CHECK(STOPS)
  586. END;   { PROCEDURE EXPECT_NAME }
  587.  
  588.  
  589. PROCEDURE STANDARD_BLOCK;
  590. BEGIN
  591.      BLOCK_NUM:= -1;
  592.      BLOCK_LEVEL:= NIL;
  593.      NEW_BLOCK;
  594.      DEFINE(NO_NAME,STANDARD_TYPE3,UNIVERSAL_TYPE);
  595.      DEFINE(ORD(INTEGER1),STANDARD_TYPE3,INTEGER_TYPE);
  596.      DEFINE(ORD(BOOLEAN1),STANDARD_TYPE3,BOOLEAN_TYPE)
  597. END;   { PROCEDURE STANDARD_BLOCK }
  598.  
  599. {-----------------------------------------------------------------------------}
  600. {     THE FOLLOWING FORWARD DECLARATIONS ARE NEEDED TO KEEP THE BNF RULE      }
  601. {  PROCEDURES IN THE SAME ORDER AS SHOWN IN THE TEXT.                         }
  602. {                                                                             }
  603. PROCEDURE EXPRESSION(VAR EXPR_TYPE: OBJECT_POINTER;
  604.                      STOPS: SYMBOLS);            FORWARD;
  605.  
  606. PROCEDURE VARIABLE_ACCESS_LIST(VAR ACCESS_TYPE: OBJECT_POINTER;
  607.                                VAR ACCESSES: INTEGER;
  608.                                STOPS: SYMBOLS);  FORWARD;
  609.  
  610. PROCEDURE EXPRESSION_LIST(VAR EXPR_TYPE: OBJECT_POINTER; VAR EXPRS: INTEGER;
  611.                           STOPS: SYMBOLS);       FORWARD;
  612.  
  613. PROCEDURE STATEMENT_PART(STOPS: SYMBOLS);        FORWARD;
  614.  
  615. PROCEDURE ARRAY_TAIL(VAR LENGTH, UPPER_BOUND: INTEGER;
  616.                      ELEMENT_TYPE: OBJECT_POINTER;
  617.                      VAR INDEX_TYPE: OBJECT_POINTER; STOPS: SYMBOLS);
  618.                                                  FORWARD;
  619.  
  620. PROCEDURE BLOCK(VAR_LABEL, BEG_LABEL: RANGE; STOPS: SYMBOLS);
  621.                                                  FORWARD;
  622. {-----------------------------------------------------------------------------}
  623.  
  624. {-----------------------------------------------------------------------------}
  625. {---- THE FOLLOWING ARE THE PROCEDURES FOR THE PL BNF RULES IN BOTTOMS UP ----}
  626. {---- ORDERING.      ( NAME2..PROGRAM2 )                                  ----}
  627. {                                                                             }
  628. PROCEDURE NAMEX(VAR NAME: INTEGER; STOPS: SYMBOLS);
  629. BEGIN
  630.      EXPECT_NAME(NAME,STOPS)
  631. END;
  632.  
  633. PROCEDURE NUMERAL(STOPS: SYMBOLS);
  634. BEGIN
  635.      EXPECT(NUMERAL1,STOPS)
  636. END;
  637.  
  638. PROCEDURE BOOLEAN_SYMBOL(VAR VALUE: INTEGER; STOPS: SYMBOLS);
  639.  
  640. (* BOOLEAN SYMBOL = "FALSE" | "TRUE" *)
  641.  
  642. BEGIN
  643.      IF SYMBOL = FALSE1
  644.         THEN
  645.           BEGIN
  646.             EXPECT(FALSE1,STOPS);
  647.             VALUE:= ORD(FALSE)
  648.           END
  649.      ELSE IF SYMBOL = TRUE1
  650.         THEN
  651.           BEGIN
  652.             EXPECT(TRUE1,STOPS);
  653.             VALUE:= ORD(TRUE)
  654.           END
  655.      ELSE
  656.        BEGIN
  657.          SYNTAX_ERROR(STOPS);
  658.          VALUE:= ORD(FALSE)             {  PROGRAMMER'S CHOICE }
  659.        END
  660. END;
  661.  
  662.  
  663.  
  664. PROCEDURE CONSTANT(VAR VALUE: INTEGER; VAR TYPEX: OBJECT_POINTER;
  665.                    STOPS: SYMBOLS);
  666.  
  667. (* CONSTANT = NUMERAL | BOOLEAN SYMBOL | NAME : "-" CONSTANT *)
  668. VAR
  669.    NAME,
  670.    VALUE1: INTEGER;
  671.    OBJECT: OBJECT_POINTER;
  672.  
  673. BEGIN
  674.      CASE SYMBOL OF
  675.          MINUS1:   BEGIN
  676.                         EXPECT(MINUS1,STOPS+FIRST[CONSTANT2]);
  677.                         IF SYMBOL IN FIRST[CONSTANT2]
  678.                            THEN
  679.                              BEGIN
  680.                                CONSTANT(VALUE1,TYPEX,STOPS);
  681.                                IF TYPEX <> INTEGER_TYPE
  682.                                   THEN SYNTAX_ERROR(STOPS)
  683.                                   ELSE VALUE:= -VALUE1
  684.                              END
  685.                            ELSE SYNTAX_ERROR(STOPS)
  686.                    END;
  687.          NUMERAL1: BEGIN
  688.                         VALUE:= ARGUMENT;
  689.                         TYPEX:= INTEGER_TYPE;
  690.                         NUMERAL(STOPS)
  691.                    END;
  692.          TRUE1,
  693.          FALSE1: BEGIN
  694.                       BOOLEAN_SYMBOL(VALUE,STOPS);
  695.                       TYPEX:= BOOLEAN_TYPE
  696.                  END;
  697.          NAME1:  BEGIN
  698.                    NAMEX(NAME,STOPS);
  699.                    FIND(NAME,OBJECT);
  700.                    IF OBJECT^.KIND = CONST3
  701.                       THEN
  702.                         BEGIN
  703.                           VALUE:= OBJECT^.CONST_VALUE;
  704.                           TYPEX:= OBJECT^.CONST_TYPE
  705.                         END
  706.                       ELSE
  707.                         BEGIN
  708.                           KIND_ERROR(OBJECT);
  709.                           VALUE:= 0;
  710.                           TYPEX:= UNIVERSAL_TYPE
  711.                         END
  712.                  END
  713.        ELSE
  714.          BEGIN
  715.            SYNTAX_ERROR(STOPS);
  716.            VALUE:= 0;
  717.            TYPEX:= UNIVERSAL_TYPE
  718.          END
  719.      END  { CASE }
  720. END;     { PROCEDURE CONSTANT }
  721.  
  722.  
  723.  
  724. PROCEDURE INDEXED_SELECTOR(TYPEX: OBJECT_POINTER; STOPS: SYMBOLS);
  725.  
  726. (* INDEXED SELECTOR = "[" EXPRESSION "]" *)
  727. VAR
  728.    EXPR_TYPE: OBJECT_POINTER;
  729.  
  730. BEGIN
  731.      EXPECT(LEFT_BRACKET1,STOPS + FIRST[EXPRESSION2] + [RIGHT_BRACKET1]);
  732.      EXPRESSION(EXPR_TYPE,STOPS + [RIGHT_BRACKET1]);
  733.      EXPECT(RIGHT_BRACKET1,STOPS);
  734.      CHECK_TYPE(TYPEX,EXPR_TYPE)
  735. END;
  736.  
  737.  
  738.  
  739. PROCEDURE VARIABLE_ACCESS(VAR TYPEX: OBJECT_POINTER; STOPS: SYMBOLS);
  740.  
  741. (* VARIABLE ACCESS = NAME[INDEXED SELECTOR] *)
  742. VAR
  743.    NAME: INTEGER;
  744.    OBJECT: OBJECT_POINTER;
  745.  
  746. BEGIN
  747.      NAMEX(NAME,STOPS + FIRST[INDEXED_SELECTOR2]);
  748.      FIND(NAME,OBJECT);
  749.      SYNTAX_CHECK(STOPS + FIRST[INDEXED_SELECTOR2]);
  750.      IF OBJECT^.KIND = ARRAY3
  751.         THEN
  752.           BEGIN
  753.             IF SYMBOL IN FIRST[INDEXED_SELECTOR2]
  754.               THEN
  755.                 BEGIN
  756.                   EMIT3(VARIABLE5,BLOCK_NUM - OBJECT^.ARRAY_LEVEL,
  757.                         OBJECT^.ARRAY_DISPLACEMENT);
  758.                   INDEXED_SELECTOR(OBJECT^.INDEX_TYPE,STOPS);
  759.                   EMIT3(INDEX5,OBJECT^.UPPER_BOUND,LINENUM);
  760.                   TYPEX:= OBJECT^.ELEMENT_TYPE
  761.                 END
  762.               ELSE SYNTAX_ERROR(STOPS)
  763.           END
  764.      ELSE IF OBJECT^.KIND = VAR3
  765.          THEN
  766.            BEGIN
  767.              TYPEX:= OBJECT^.VAR_TYPE;
  768.              EMIT3(VARIABLE5,BLOCK_NUM - OBJECT^.VAR_LEVEL,
  769.                    OBJECT^.VAR_DISPLACEMENT)
  770.            END
  771.      ELSE
  772.        BEGIN
  773.          SYNTAX_ERROR(STOPS);
  774.          TYPEX:= UNIVERSAL_TYPE
  775.        END
  776. END;
  777.  
  778.  
  779.  
  780. PROCEDURE FACTOR(VAR TYPEX: OBJECT_POINTER; STOPS: SYMBOLS);
  781.  
  782. (* FACTOR = CONSTANT | VARIABLE ACCESS | "(" EXPRESSION ")" | "~" FACTOR *)
  783. {     rewritten as: }
  784. (* FACTOR = NUMERAL | BOOLEAN SYMBOL | VARIABLE ACCESS | "("EXPRESSION")" |
  785.             "~"FACTOR *)
  786. VAR
  787.    NAME, VALUE: INTEGER;
  788.    OBJECT: OBJECT_POINTER;
  789.  
  790. BEGIN
  791.      IF SYMBOL IN [NUMERAL1,TRUE1,FALSE1]
  792.         THEN
  793.           BEGIN
  794.             CONSTANT(VALUE,TYPEX,STOPS);
  795.             EMIT2(CONSTANT5,VALUE)
  796.           END
  797.      ELSE IF SYMBOL = NAME1
  798.         THEN
  799.           BEGIN
  800.             FIND(ARGUMENT,OBJECT);
  801.             IF OBJECT^.KIND = CONST3
  802.                THEN
  803.                  BEGIN
  804.                    CONSTANT(VALUE,TYPEX,STOPS);
  805.                    EMIT2(CONSTANT5,VALUE)
  806.                  END
  807.             ELSE IF (OBJECT^.KIND = VAR3) OR (OBJECT^.KIND = ARRAY3)
  808.                THEN
  809.                  BEGIN
  810.                    VARIABLE_ACCESS(TYPEX,STOPS);
  811.                    EMIT1(VALUE5)
  812.                  END
  813.             ELSE
  814.               BEGIN
  815.                 KIND_ERROR(OBJECT);
  816.                 TYPEX:= UNIVERSAL_TYPE;
  817.                 EXPECT(NAME1,STOPS)
  818.               END
  819.           END
  820.      ELSE IF SYMBOL = LEFT_PAREN1
  821.         THEN
  822.           BEGIN
  823.             EXPECT(LEFT_PAREN1,STOPS + FIRST[EXPRESSION2] + [RIGHT_PAREN1]);
  824.             EXPRESSION(TYPEX,STOPS + [RIGHT_PAREN1]);
  825.             EXPECT(RIGHT_PAREN1,STOPS)
  826.           END
  827.      ELSE IF SYMBOL = NOT1
  828.         THEN
  829.           BEGIN
  830.             EXPECT(NOT1,STOPS + FIRST[FACTOR2]);
  831.             FACTOR(TYPEX,STOPS);
  832.             CHECK_TYPE(TYPEX,BOOLEAN_TYPE);
  833.             EMIT1(NOT5)
  834.           END
  835.      ELSE
  836.        BEGIN
  837.          SYNTAX_ERROR(STOPS);
  838.          TYPEX:= UNIVERSAL_TYPE
  839.        END
  840. END;     { PROCEDURE FACTOR }
  841.  
  842.  
  843.  
  844. PROCEDURE MULTIPLYING_OPERATOR(STOPS: SYMBOLS);
  845.  
  846. (* MULTIPLYING OPERATOR = "*" | "/" | "\" *)
  847.  
  848. BEGIN
  849.      CASE SYMBOL OF
  850.           MULT1: EXPECT(MULT1,STOPS);
  851.           DIV1:  EXPECT(DIV1,STOPS);
  852.           MOD1:  EXPECT(MOD1,STOPS)
  853.         ELSE SYNTAX_ERROR(STOPS)
  854.      END
  855. END;
  856.  
  857.  
  858.  
  859. PROCEDURE TERM(VAR TERM_TYPE: OBJECT_POINTER; STOPS: SYMBOLS);
  860.  
  861. (* TERM = FACTOR { MULTIPLYING OPERATOR  FACTOR } *)
  862. VAR
  863.    OP: SYMBOL_TYPE;
  864. BEGIN
  865.     FACTOR(TERM_TYPE,STOPS + FIRST[MULTIPLYING_OPERATOR2]);
  866.     IF SYMBOL IN FIRST[MULTIPLYING_OPERATOR2]
  867.        THEN CHECK_TYPE(TERM_TYPE,INTEGER_TYPE);
  868.     WHILE SYMBOL IN FIRST[MULTIPLYING_OPERATOR2] DO
  869.        BEGIN
  870.          OP:= SYMBOL;
  871.          MULTIPLYING_OPERATOR(STOPS + FIRST[MULTIPLYING_OPERATOR2] +
  872.                               FIRST[FACTOR2]);
  873.          FACTOR(TERM_TYPE,STOPS + FIRST[MULTIPLYING_OPERATOR2]);
  874.          CHECK_TYPE(TERM_TYPE,INTEGER_TYPE);
  875.          TERM_TYPE:= INTEGER_TYPE;
  876.          CASE OP OF
  877.               MULT1: EMIT1(MULTIPLY5);
  878.                DIV1: EMIT2(DIVIDE5,LINENUM);
  879.                MOD1: EMIT2(MODULO5,LINENUM)
  880.          END
  881.        END
  882. END;
  883.  
  884.  
  885.  
  886. PROCEDURE ADDING_OPERATOR(STOPS: SYMBOLS);
  887.  
  888. (* ADDING OPERATOR = "+" | "-" *)
  889.  
  890. BEGIN
  891.      IF SYMBOL = PLUS1
  892.         THEN EXPECT(PLUS1,STOPS)
  893.      ELSE IF SYMBOL = MINUS1
  894.         THEN EXPECT(MINUS1,STOPS)
  895.      ELSE SYNTAX_ERROR(STOPS)
  896. END;
  897.  
  898.  
  899.  
  900. PROCEDURE SIMPLE_EXPRESSION(VAR EXPR_TYPE: OBJECT_POINTER; STOPS: SYMBOLS);
  901.  
  902. (* SIMPLE EXPRESSION = ["-"] TERM { ADDING OPERATOR  TERM } *)
  903. VAR
  904.    OP: SYMBOL_TYPE;
  905. BEGIN
  906.      SYNTAX_CHECK(STOPS + [MINUS1] + FIRST[TERM2] + FIRST[ADDING_OPERATOR2]);
  907.      IF SYMBOL = MINUS1
  908.         THEN
  909.           BEGIN
  910.             EXPECT(MINUS1,STOPS + FIRST[TERM2] + FIRST[ADDING_OPERATOR2]);
  911.             TERM(EXPR_TYPE,STOPS + FIRST[ADDING_OPERATOR2]);
  912.             CHECK_TYPE(EXPR_TYPE,INTEGER_TYPE);
  913.             EMIT1(MINUS5)
  914.           END
  915.         ELSE TERM(EXPR_TYPE,STOPS + FIRST[ADDING_OPERATOR2]);
  916.      IF SYMBOL IN FIRST[ADDING_OPERATOR2]
  917.         THEN CHECK_TYPE(EXPR_TYPE,INTEGER_TYPE);
  918.      WHILE SYMBOL IN FIRST[ADDING_OPERATOR2] DO
  919.         BEGIN
  920.           OP:= SYMBOL;
  921.           ADDING_OPERATOR(STOPS + FIRST[TERM2] + FIRST[ADDING_OPERATOR2]);
  922.           TERM(EXPR_TYPE,STOPS + FIRST[ADDING_OPERATOR2]);
  923.           CHECK_TYPE(EXPR_TYPE,INTEGER_TYPE);
  924.           EXPR_TYPE:= INTEGER_TYPE;
  925.           IF OP = PLUS1
  926.              THEN EMIT1(ADD5)
  927.              ELSE EMIT1(SUBTRACT5)
  928.         END
  929. END;
  930.  
  931.  
  932.  
  933. PROCEDURE RELATIONAL_OPERATOR(STOPS: SYMBOLS);
  934.  
  935. (* RELATIONAL OPERATOR = "<" | "=" | ">" *)
  936.  
  937. BEGIN
  938.      CASE SYMBOL OF
  939.           LESS1: EXPECT(LESS1,STOPS);
  940.          EQUAL1: EXPECT(EQUAL1,STOPS);
  941.        GREATER1: EXPECT(GREATER1,STOPS)
  942.       ELSE SYNTAX_ERROR(STOPS)
  943.      END   { CASE }
  944. END;
  945.  
  946.  
  947.  
  948. PROCEDURE PRIMARY_EXPRESSION(VAR EXPR_TYPE: OBJECT_POINTER; STOPS: SYMBOLS);
  949.  
  950. (* PRIMARY EXPRESSION = SIMPLE EXPRESSION
  951.                         [RELATIONAL OPERATOR  SIMPLE EXPRESSION] *)
  952. VAR
  953.    OP: SYMBOL_TYPE;
  954. BEGIN
  955.      SIMPLE_EXPRESSION(EXPR_TYPE,STOPS + FIRST[RELATIONAL_OPERATOR2]);
  956.      IF SYMBOL IN FIRST[RELATIONAL_OPERATOR2]
  957.         THEN
  958.           BEGIN
  959.             OP:= SYMBOL;
  960.             CHECK_TYPE(EXPR_TYPE,INTEGER_TYPE);
  961.             RELATIONAL_OPERATOR(STOPS + FIRST[SIMPLE_EXPRESSION2]);
  962.             SIMPLE_EXPRESSION(EXPR_TYPE,STOPS);
  963.             CHECK_TYPE(EXPR_TYPE,INTEGER_TYPE);
  964.             EXPR_TYPE:= BOOLEAN_TYPE;
  965.             CASE OP OF
  966.                  LESS1: EMIT1(LESS5);
  967.                 EQUAL1: EMIT1(EQUAL5);
  968.               GREATER1: EMIT1(GREATER5)
  969.             END
  970.           END
  971. END;
  972.  
  973.  
  974.  
  975. PROCEDURE PRIMARY_OPERATOR(STOPS: SYMBOLS);
  976.  
  977. (* PRIMARY OPERATOR = "&" | "|" *)
  978.  
  979. BEGIN
  980.      IF SYMBOL = AND1
  981.         THEN EXPECT(AND1,STOPS)
  982.      ELSE IF SYMBOL = OR1
  983.         THEN EXPECT(OR1,STOPS)
  984.      ELSE SYNTAX_ERROR(STOPS)
  985. END;
  986.  
  987.  
  988.  
  989. PROCEDURE EXPRESSION{(VAR EXPR_TYPE: OBJECT_POINTER; STOPS: SYMBOLS)};
  990. { FORWARD REFERENCED }
  991.  
  992. (* EXPRESSION = PRIMARY EXPRESSION { PRIMARY OPERATOR  PRIMARY EXPRESSION }  *)
  993. VAR
  994.    OP: SYMBOL_TYPE;
  995. BEGIN
  996.      PRIMARY_EXPRESSION(EXPR_TYPE,STOPS + FIRST[PRIMARY_OPERATOR2]);
  997.      IF SYMBOL IN FIRST[PRIMARY_OPERATOR2]
  998.         THEN CHECK_TYPE(EXPR_TYPE,BOOLEAN_TYPE);
  999.      WHILE SYMBOL IN FIRST[PRIMARY_OPERATOR2] DO
  1000.          BEGIN
  1001.            OP:= SYMBOL;
  1002.            PRIMARY_OPERATOR(STOPS + FIRST[PRIMARY_OPERATOR2] +
  1003.                             FIRST[PRIMARY_EXPRESSION2]);
  1004.            PRIMARY_EXPRESSION(EXPR_TYPE,STOPS + FIRST[PRIMARY_OPERATOR2]);
  1005.            IF OP = OR1
  1006.               THEN EMIT1(OR5)
  1007.               ELSE EMIT1(AND5);
  1008.            CHECK_TYPE(EXPR_TYPE,BOOLEAN_TYPE);
  1009.            EXPR_TYPE:= BOOLEAN_TYPE
  1010.          END
  1011. END;
  1012.  
  1013.  
  1014.  
  1015. PROCEDURE GUARDED_COMMAND(LABEL_: RANGE; STOPS: SYMBOLS);
  1016.  
  1017. (* GUARDED COMMAND = EXPRESSION "->" STATEMENT PART *)
  1018. VAR
  1019.    EXPR_TYPE: OBJECT_POINTER;
  1020.  
  1021. BEGIN
  1022.      EXPRESSION(EXPR_TYPE,STOPS + [ARROW1] + FIRST[STATEMENT_PART2]);
  1023.      CHECK_TYPE(EXPR_TYPE,BOOLEAN_TYPE);
  1024.      EXPR_TYPE:= BOOLEAN_TYPE;
  1025.      EXPECT(ARROW1,STOPS + FIRST[STATEMENT_PART2]);
  1026.      EMIT2(ARROW5,LABEL_);
  1027.      STATEMENT_PART(STOPS)
  1028. END;
  1029.  
  1030.  
  1031.  
  1032. PROCEDURE GUARDED_COMMAND_LIST(IF_DO: IF_DO_TYPE; STOPS: SYMBOLS);
  1033.  
  1034. (* GUARDED COMMAND LIST = GUARDED COMMAND { "[]" GUARDED COMMAND } *)
  1035. VAR
  1036.    THIS_LABEL,
  1037.    NEXT_LABEL: RANGE;
  1038. BEGIN
  1039.      NEW_LABEL(THIS_LABEL);
  1040.      NEW_LABEL(NEXT_LABEL);
  1041.      DEFINE_ADDRESS(THIS_LABEL);
  1042.      GUARDED_COMMAND(NEXT_LABEL,STOPS + [PAIRED_BRACKETS1]);
  1043.      IF IF_DO = DO_
  1044.         THEN EMIT2(BAR5,THIS_LABEL)
  1045.         ELSE EMIT2(BAR5,EXIT_LABEL);
  1046.      WHILE SYMBOL = PAIRED_BRACKETS1 DO
  1047.        BEGIN
  1048.          EXPECT(PAIRED_BRACKETS1,STOPS + [PAIRED_BRACKETS1] +
  1049.                                  FIRST[GUARDED_COMMAND2]);
  1050.          THIS_LABEL:= NEXT_LABEL;
  1051.          NEW_LABEL(NEXT_LABEL);
  1052.          DEFINE_ADDRESS(THIS_LABEL);
  1053.          GUARDED_COMMAND(NEXT_LABEL,STOPS + [PAIRED_BRACKETS1]);
  1054.          IF IF_DO = DO_
  1055.             THEN EMIT2(BAR5,THIS_LABEL)
  1056.             ELSE EMIT2(BAR5,EXIT_LABEL)
  1057.        END;
  1058.      DEFINE_ADDRESS(NEXT_LABEL)
  1059. END;
  1060.  
  1061.  
  1062.  
  1063. PROCEDURE DO_STATEMENT(STOPS: SYMBOLS);
  1064.  
  1065. (* DO STATEMENT = "DO" GUARDED COMMAND LIST "OD" *)
  1066.  
  1067. BEGIN
  1068.      EXPECT(DO1,STOPS + FIRST[GUARDED_COMMAND_LIST2] + [OD1]);
  1069.      GUARDED_COMMAND_LIST(DO_,STOPS + [OD1]);
  1070.      EXPECT(OD1,STOPS)
  1071. END;
  1072.  
  1073.  
  1074.  
  1075. PROCEDURE IF_STATEMENT(STOPS: SYMBOLS);
  1076.  
  1077. (* IF STATEMENT = "IF" GUARDED COMMAND LIST "FI" *)
  1078. BEGIN
  1079.      NEW_LABEL(EXIT_LABEL);
  1080.      EXPECT(IF1,STOPS + FIRST[GUARDED_COMMAND_LIST2] + [FI1]);
  1081.      GUARDED_COMMAND_LIST(IF_,STOPS + [FI1]);
  1082.      EXPECT(FI1,STOPS);
  1083.      EMIT2(FI5,LINENUM);
  1084.      DEFINE_ADDRESS(EXIT_LABEL)
  1085. END;
  1086.  
  1087.  
  1088.  
  1089. PROCEDURE PROCEDURE_STATEMENT(STOPS: SYMBOLS);
  1090.  
  1091. (* PROCEDURE STATEMENT = "CALL" NAME *)
  1092. VAR
  1093.    NAME: INTEGER;
  1094.    OBJECT: OBJECT_POINTER;
  1095.  
  1096. BEGIN
  1097.      EXPECT(CALL1,STOPS + [NAME1]);
  1098.      NAMEX(NAME,STOPS);
  1099.      FIND(NAME,OBJECT);
  1100.      IF OBJECT^.KIND <> PROC3
  1101.         THEN KIND_ERROR(OBJECT)
  1102.         ELSE EMIT3(CALL5,BLOCK_NUM - OBJECT^.PROC_LEVEL,OBJECT^.PROC_LABEL)
  1103. END;
  1104.  
  1105.  
  1106.  
  1107. PROCEDURE ASSIGNMENT_STATEMENT(STOPS: SYMBOLS);
  1108.  
  1109. (* ASSIGNMENT STATEMENT = VARIABLE ACCESS LIST ":=" EXPRESSION LIST *)
  1110. VAR
  1111.    NUM_ACCESSES,
  1112.    NUM_EXPRESSN: INTEGER;
  1113.    ACCESS_TYPE,
  1114.    EXPRES_TYPE: OBJECT_POINTER;
  1115.  
  1116. BEGIN
  1117.      VARIABLE_ACCESS_LIST(ACCESS_TYPE,NUM_ACCESSES,
  1118.                           STOPS + [BECOMES1] + FIRST[EXPRESSION_LIST2]);
  1119.      EXPECT(BECOMES1,STOPS + FIRST[EXPRESSION_LIST2]);
  1120.      EXPRESSION_LIST(EXPRES_TYPE,NUM_EXPRESSN,STOPS);
  1121.      IF NUM_EXPRESSN <> NUM_ACCESSES
  1122.         THEN ERROR(UNEQUAL4)
  1123.         ELSE EMIT2(ASSIGN5,NUM_ACCESSES);
  1124.      CHECK_TYPE(ACCESS_TYPE,EXPRES_TYPE);
  1125. END;
  1126.  
  1127.  
  1128.  
  1129. PROCEDURE EXPRESSION_LIST{(VAR EXPR_TYPE: OBJECT_POINTER; VAR EXPRS: INTEGER;
  1130.                            STOPS: SYMBOLS)};
  1131. { FORWARD REFERENCED }
  1132.  
  1133. (* EXPRESSION LIST = EXPRESSION {"," EXPRESSION } *)
  1134. VAR
  1135.    TYPEX: OBJECT_POINTER;
  1136.  
  1137. BEGIN
  1138.      EXPRS:= 1;
  1139.      EXPRESSION(EXPR_TYPE,STOPS + [COMMA1]);
  1140.      WHILE SYMBOL = COMMA1 DO
  1141.        BEGIN
  1142.          EXPECT(COMMA1,STOPS + FIRST[EXPRESSION2] + [COMMA1]);
  1143.          EXPRESSION(TYPEX,STOPS + [COMMA1]);
  1144.          EXPRS:= EXPRS + 1;
  1145.          CHECK_TYPE(TYPEX,EXPR_TYPE)
  1146.        END
  1147. END;
  1148.  
  1149.  
  1150.  
  1151. PROCEDURE WRITE_STATEMENT(STOPS: SYMBOLS);
  1152.  
  1153. (* WRITE STATEMENT = "WRITE" EXPRESSION LIST *)
  1154. VAR
  1155.    EXPRS: INTEGER;
  1156.    EXPR_TYPE: OBJECT_POINTER;
  1157.  
  1158. BEGIN
  1159.      EXPECT(WRITE1,STOPS + FIRST[EXPRESSION_LIST2]);
  1160.      EXPRESSION_LIST(EXPR_TYPE,EXPRS,STOPS);
  1161.      CHECK_TYPE(EXPR_TYPE,INTEGER_TYPE);
  1162.      EMIT2(WRITE5,EXPRS)
  1163. END;
  1164.  
  1165.  
  1166.  
  1167. PROCEDURE VARIABLE_ACCESS_LIST{(VAR ACCESS_TYPE: OBJECT_POINTER;
  1168.                                 VAR ACCESSES: INTEGER; STOPS: SYMBOLS)};
  1169. { FORWARD REFERENCED }
  1170.  
  1171. (* VARIABLE ACCESS LIST = VARIABLE ACCESS {"," VARIABLE ACCESS } *)
  1172. VAR
  1173.    TYPEX: OBJECT_POINTER;
  1174.  
  1175. BEGIN
  1176.      ACCESSES:= 1;
  1177.      VARIABLE_ACCESS(ACCESS_TYPE,STOPS + [COMMA1]);
  1178.      WHILE SYMBOL = COMMA1 DO
  1179.         BEGIN
  1180.           EXPECT(COMMA1,STOPS + FIRST[VARIABLE_ACCESS2] + [COMMA1]);
  1181.           ACCESSES:= ACCESSES + 1;
  1182.           VARIABLE_ACCESS(TYPEX,STOPS + [COMMA1]);
  1183.           CHECK_TYPE(TYPEX,ACCESS_TYPE)
  1184.         END
  1185. END;
  1186.  
  1187.  
  1188.  
  1189. PROCEDURE READ_STATEMENT(STOPS: SYMBOLS);
  1190.  
  1191. (* READ STATEMENT = "READ" VARIABLE ACCESS LIST *)
  1192. VAR
  1193.    ACCESSES: INTEGER;
  1194.    ACCESS_TYPE: OBJECT_POINTER;
  1195. BEGIN
  1196.      EXPECT(READ1,STOPS + FIRST[VARIABLE_ACCESS_LIST2]);
  1197.      VARIABLE_ACCESS_LIST(ACCESS_TYPE,ACCESSES,STOPS);
  1198.      CHECK_TYPE(ACCESS_TYPE,INTEGER_TYPE);
  1199.      EMIT2(READ5,ACCESSES)
  1200. END;
  1201.  
  1202.  
  1203.  
  1204. PROCEDURE EMPTY_STATEMENT(STOPS: SYMBOLS);
  1205.  
  1206. (* EMPTY STATEMENT = "SKIP" *)
  1207.  
  1208. BEGIN
  1209.      EXPECT(SKIP1,STOPS)
  1210. END;
  1211.  
  1212.  
  1213.  
  1214. PROCEDURE STATEMENT(STOPS: SYMBOLS);
  1215.  
  1216. (* STATEMENT = EMPTY STATEMENT | READ STATEMENT | WRITE STATEMENT |
  1217.                ASSIGNMENT STATEMENT | PROCEDURE STATEMENT |
  1218.                DO STATEMENT | IF STATEMENT *)
  1219.  
  1220. BEGIN
  1221.      CASE SYMBOL OF
  1222.        SKIP1: EMPTY_STATEMENT(STOPS);
  1223.        READ1: READ_STATEMENT(STOPS);
  1224.       WRITE1: WRITE_STATEMENT(STOPS);
  1225.        NAME1: ASSIGNMENT_STATEMENT(STOPS);
  1226.        CALL1: PROCEDURE_STATEMENT(STOPS);
  1227.          IF1: IF_STATEMENT(STOPS);
  1228.          DO1: DO_STATEMENT(STOPS)
  1229.       ELSE SYNTAX_ERROR(STOPS)
  1230.      END
  1231. END;
  1232.  
  1233.  
  1234.  
  1235. PROCEDURE STATEMENT_PART{(STOPS: SYMBOLS)};      { FORWARD REFERENCED }
  1236.  
  1237. (* STATEMENT PART = { STATEMENT ";" } *)
  1238.  
  1239. BEGIN
  1240.      SYNTAX_CHECK(STOPS + FIRST[STATEMENT2]);
  1241.      WHILE SYMBOL IN FIRST[STATEMENT2] DO
  1242.        BEGIN
  1243.          STATEMENT(STOPS + FIRST[STATEMENT2] + [SEMICOLON1]);
  1244.          EXPECT(SEMICOLON1,STOPS + FIRST[STATEMENT2])
  1245.        END
  1246. END;
  1247.  
  1248.  
  1249.  
  1250. PROCEDURE PROCEDURE_DEFINITION(STOPS: SYMBOLS);
  1251.  
  1252. (* PROCEDURE DEFINITION = "PROC" NAME BLOCK *)
  1253. VAR
  1254.    NAME: INTEGER;
  1255.    OBJECT: OBJECT_POINTER;
  1256.    VAR_LABEL,
  1257.    BEG_LABEL: RANGE;
  1258. BEGIN
  1259.      EXPECT(PROC1,STOPS + [NAME1] + FIRST[BLOCK2]);
  1260.      NAMEX(NAME,STOPS + FIRST[BLOCK2]);
  1261.      DEFINE(NAME,PROC3,OBJECT);
  1262.      OBJECT^.PROC_LEVEL:= BLOCK_NUM;
  1263.      OBJECT^.PROC_LABEL:= ADDRESS;
  1264.      NEW_LABEL(VAR_LABEL);
  1265.      NEW_LABEL(BEG_LABEL);
  1266.      EMIT3(PROC5,VAR_LABEL,BEG_LABEL);
  1267.      BLOCK(VAR_LABEL,BEG_LABEL,STOPS);
  1268.      EMIT1(END_PROC5)
  1269. END;
  1270.  
  1271.  
  1272.  
  1273. PROCEDURE VARIABLE_LIST(VAR LENGTH: INTEGER;
  1274.                         TYPEX: OBJECT_POINTER; STOPS: SYMBOLS);
  1275.  
  1276. (* VARIABLE LIST = VARIABLE NAME { "," VARIABLE NAME } *)
  1277. VAR
  1278.    NAME: INTEGER;
  1279.    OBJECT: OBJECT_POINTER;
  1280. BEGIN
  1281.      NAMEX(NAME,STOPS + [COMMA1]);
  1282.      DEFINE(NAME,VAR3,OBJECT);
  1283.      OBJECT^.VAR_TYPE:= TYPEX;
  1284.      OBJECT^.VAR_LEVEL:= BLOCK_NUM;
  1285.      OBJECT^.VAR_DISPLACEMENT:= LENGTH;
  1286.      LENGTH:= LENGTH + TYPE_LENGTH(OBJECT^.VAR_TYPE);
  1287.      WHILE SYMBOL = COMMA1 DO
  1288.         BEGIN
  1289.           EXPECT(COMMA1,STOPS + [COMMA1] + FIRST[NAME2]);
  1290.           NAMEX(NAME,STOPS + [COMMA1]);
  1291.           DEFINE(NAME,VAR3,OBJECT);
  1292.           OBJECT^.VAR_TYPE:= TYPEX;
  1293.           OBJECT^.VAR_LEVEL:= BLOCK_NUM;
  1294.           OBJECT^.VAR_DISPLACEMENT:= LENGTH;
  1295.           LENGTH:= LENGTH + TYPE_LENGTH(OBJECT^.VAR_TYPE)
  1296.         END
  1297. END;
  1298.  
  1299.  
  1300.  
  1301. PROCEDURE TYPE_SYMBOL(VAR TYPEX: OBJECT_POINTER; STOPS: SYMBOLS);
  1302.  
  1303. (* TYPE SYMBOL = "INTEGER" | "BOOLEAN" *)
  1304.  
  1305. BEGIN
  1306.      IF SYMBOL = INTEGER1
  1307.         THEN
  1308.           BEGIN
  1309.             EXPECT(INTEGER1,STOPS);
  1310.             TYPEX:= INTEGER_TYPE
  1311.           END
  1312.      ELSE IF SYMBOL = BOOLEAN1
  1313.         THEN
  1314.           BEGIN
  1315.             EXPECT(BOOLEAN1,STOPS);
  1316.             TYPEX:= BOOLEAN_TYPE
  1317.           END
  1318.      ELSE
  1319.           BEGIN
  1320.             SYNTAX_ERROR(STOPS);
  1321.             TYPEX:= UNIVERSAL_TYPE
  1322.           END
  1323. END;
  1324.  
  1325. PROCEDURE ARRAY_GROUP(VAR LENGTH,UPPER_BOUND: INTEGER;
  1326.                       ELEMENT_TYPE: OBJECT_POINTER;
  1327.                       VAR INDEX_TYPE: OBJECT_POINTER; STOPS: SYMBOLS);
  1328.  
  1329. (* ARRAY_GROUP = NAME ARRAY_TAIL *)
  1330. VAR
  1331.    NAME,
  1332.    VALUE: INTEGER;
  1333.    ARRAY_: OBJECT_POINTER;
  1334. BEGIN
  1335.      NAMEX(NAME,STOPS + FIRST[ARRAY_TAIL2]);
  1336.      DEFINE(NAME,ARRAY3,ARRAY_);
  1337.      ARRAY_TAIL(LENGTH,UPPER_BOUND,ELEMENT_TYPE,INDEX_TYPE,STOPS);
  1338.      ARRAY_^.INDEX_TYPE:= INDEX_TYPE;
  1339.      ARRAY_^.ELEMENT_TYPE:= ELEMENT_TYPE;
  1340.      ARRAY_^.ARRAY_LEVEL:= BLOCK_NUM;
  1341.      ARRAY_^.ARRAY_DISPLACEMENT:= LENGTH;
  1342.      IF UPPER_BOUND <= 0
  1343.         THEN
  1344.             BEGIN
  1345.               ERROR(RANGE4);
  1346.               ARRAY_^.UPPER_BOUND:= -UPPER_BOUND
  1347.             END
  1348.         ELSE ARRAY_^.UPPER_BOUND:= UPPER_BOUND;
  1349.      LENGTH:= LENGTH + UPPER_BOUND * TYPE_LENGTH(ARRAY_^.ELEMENT_TYPE)
  1350. END;   { PROCEDURE ARRAY_GROUP }
  1351.  
  1352.  
  1353. PROCEDURE ARRAY_TAIL{(VAR LENGTH, UPPER_BOUND: INTEGER;
  1354.                       ELEMENT_TYPE: OBJECT_POINTER;
  1355.                       VAR INDEX_TYPE: POINTER; STOPS: SYMBOLS)};
  1356. { FORWARD REFERENCED }
  1357.  
  1358. (* ARRAY_TAIL = "," ARRAY_GROUP | "[" CONSTANT "]" *)
  1359.  
  1360. BEGIN
  1361.      IF SYMBOL = COMMA1
  1362.         THEN
  1363.           BEGIN
  1364.             EXPECT(COMMA1,STOPS + FIRST[ARRAY_GROUP2]);
  1365.             ARRAY_GROUP(LENGTH,UPPER_BOUND,ELEMENT_TYPE,INDEX_TYPE,STOPS)
  1366.           END
  1367.      ELSE IF SYMBOL = LEFT_BRACKET1
  1368.         THEN
  1369.           BEGIN
  1370.             EXPECT(LEFT_BRACKET1,STOPS + FIRST[CONSTANT2] + [RIGHT_BRACKET1]);
  1371.             CONSTANT(UPPER_BOUND,INDEX_TYPE,STOPS + [RIGHT_BRACKET1]);
  1372.             EXPECT(RIGHT_BRACKET1,STOPS)
  1373.           END
  1374.      ELSE SYNTAX_ERROR(STOPS)
  1375. END;   { PROCEDURE ARRAY_TAIL }
  1376.  
  1377.  
  1378.  
  1379. PROCEDURE VARIABLE_DEFINITION(VAR LENGTH: INTEGER; STOPS: SYMBOLS);
  1380.  
  1381. (* VARIABLE DEFINITION = TYPE SYMBOL  VARIABLE LIST |
  1382.                         TYPE SYMBOL  "ARRAY"  ARRAY_GROUP *)
  1383. VAR
  1384.    TYPEX,
  1385.    INDEX: OBJECT_POINTER;
  1386.    UP: INTEGER;
  1387.  
  1388. BEGIN
  1389.      TYPE_SYMBOL(TYPEX,STOPS + [ARRAY1] + FIRST[VARIABLE_LIST2] +
  1390.                  [LEFT_BRACKET1] + FIRST[CONSTANT2] + [RIGHT_BRACKET1]);
  1391.      IF SYMBOL = ARRAY1
  1392.         THEN
  1393.           BEGIN
  1394.             EXPECT(ARRAY1,STOPS + FIRST[VARIABLE_LIST2] + [LEFT_BRACKET1] +
  1395.                           FIRST[CONSTANT2] + [RIGHT_BRACKET1]);
  1396.             ARRAY_GROUP(LENGTH,UP,TYPEX,INDEX,STOPS + FIRST[ARRAY_TAIL2])
  1397.           END
  1398.      ELSE IF SYMBOL = NAME1
  1399.         THEN VARIABLE_LIST(LENGTH,TYPEX,STOPS)
  1400.      ELSE SYNTAX_ERROR(STOPS)
  1401. END;
  1402.  
  1403.  
  1404.  
  1405. PROCEDURE CONSTANT_DEFINITION(STOPS: SYMBOLS);
  1406.  
  1407. (* CONSTANT DEFINITION = "CONST" NAME "=" CONSTANT *)
  1408. VAR
  1409.    VALUE,
  1410.    NAME: INTEGER;
  1411.    CONSTX, TYPEX: OBJECT_POINTER;
  1412.  
  1413. BEGIN
  1414.      EXPECT(CONST1,STOPS + [NAME1,EQUAL1] + FIRST[CONSTANT2]);
  1415.      NAMEX(NAME,STOPS + [EQUAL1] + FIRST[CONSTANT2]);
  1416.      EXPECT(EQUAL1,STOPS + FIRST[CONSTANT2]);
  1417.      CONSTANT(VALUE,TYPEX,STOPS);
  1418.      DEFINE(NAME,CONST3,CONSTX);
  1419.      CONSTX^.CONST_VALUE:= VALUE;
  1420.      CONSTX^.CONST_TYPE:= TYPEX
  1421. END;
  1422.  
  1423. PROCEDURE DEFINITION(VAR LENGTH: INTEGER; STOPS: SYMBOLS);
  1424.  
  1425. (* DEFINITION = CONSTANT DEFINITION | VARIABLE DEFINITION |
  1426.                 PROCEDURE DEFINITION *)
  1427.  
  1428. BEGIN
  1429.      IF SYMBOL = CONST1
  1430.         THEN CONSTANT_DEFINITION(STOPS)
  1431.      ELSE IF SYMBOL IN FIRST[TYPE_SYMBOL2]
  1432.         THEN VARIABLE_DEFINITION(LENGTH,STOPS)
  1433.      ELSE IF SYMBOL = PROC1
  1434.         THEN PROCEDURE_DEFINITION(STOPS)
  1435.      ELSE SYNTAX_ERROR(STOPS)
  1436. END;
  1437.  
  1438.  
  1439.  
  1440. PROCEDURE DEFINITION_PART(VAR LENGTH: INTEGER; STOPS: SYMBOLS);
  1441.  
  1442. (* DEFINITION PART = { DEFINITION ";" }  *)
  1443.  
  1444. BEGIN
  1445.      LENGTH:= 3;
  1446.      SYNTAX_CHECK(STOPS + FIRST[DEFINITION2]);
  1447.      WHILE SYMBOL IN FIRST[DEFINITION2] DO
  1448.        BEGIN
  1449.          DEFINITION(LENGTH,STOPS + FIRST[DEFINITION2] + [SEMICOLON1]);
  1450.          EXPECT(SEMICOLON1,STOPS + FIRST[DEFINITION2])
  1451.        END
  1452. END;
  1453.  
  1454.  
  1455.  
  1456. PROCEDURE BLOCK{(VAR_LABEL, BEG_LABEL: RANGE;
  1457.                  STOPS: SYMBOLS)};        { FORWARD REFERENCED }
  1458.  
  1459. (* BLOCK = "BEGIN"  DEFINITION PART  STATEMENT PART  "END" *)
  1460. VAR
  1461.    VAR_LENGTH: INTEGER;
  1462. BEGIN
  1463.      NEW_BLOCK;
  1464.      EXPECT(BEGIN1,STOPS + FIRST[DEFINITION_PART2] + FIRST[STATEMENT_PART2] +
  1465.                    [END1]);
  1466.      DEFINITION_PART(VAR_LENGTH,STOPS + FIRST[STATEMENT_PART2] + [END1]);
  1467.      TABLE[VAR_LABEL]:= VAR_LENGTH;
  1468.      DEFINE_ADDRESS(BEG_LABEL);
  1469.      STATEMENT_PART(STOPS + [END1]);
  1470.      EXPECT(END1,STOPS);
  1471.      END_BLOCK
  1472. END;
  1473.  
  1474.  
  1475.  
  1476. PROCEDURE PROGRAMX(STOPS: SYMBOLS);
  1477.  
  1478. (* PROGRAM = BLOCK "." *)
  1479. VAR
  1480.    VAR_LABEL,
  1481.    BEG_LABEL: RANGE;
  1482. BEGIN
  1483.      STANDARD_BLOCK;
  1484.      NEW_LABEL(VAR_LABEL);
  1485.      NEW_LABEL(BEG_LABEL);
  1486.      EMIT3(PROG5,VAR_LABEL,BEG_LABEL);
  1487.      BLOCK(VAR_LABEL,BEG_LABEL,STOPS + [PERIOD1]);
  1488.      EXPECT(PERIOD1,STOPS);
  1489.      EMIT1(END_PROG5)
  1490. END;
  1491. {                                                                             }
  1492. {----                     END OF BNF RULE PROCEDURES                      ----}
  1493. {-----------------------------------------------------------------------------}
  1494.  
  1495. { PROCEDURE SECOND_PASS - GOES THROUGH THE TEMP CODE AND COMPUTES LABEL       }
  1496. {                         ADDRESSES, THEN WRITES CODE TO 'TEMP2.'.            }
  1497. PROCEDURE SECOND_PASS;
  1498. VAR
  1499.    OPERATION: OPERATION_PART;
  1500.    OPERATIONX,
  1501.    OPERAND1, OPERAND2,
  1502.    K: INTEGER;
  1503. BEGIN
  1504.   FOR K:= 1 TO ROW DO
  1505.     BEGIN
  1506.       OPERATIONX:= TEMP[K,1];
  1507.       WRITE(TEMP2FILE,OPERATIONX:6);
  1508.       OPERATION:= OPERATION_PART(OPERATIONX);
  1509.       IF OPERATION IN ONE_OPERANDS
  1510.          THEN
  1511.            BEGIN
  1512.              OPERAND1:= TEMP[K,2];
  1513.              IF OPERATION IN [ARROW5,BAR5]
  1514.                 THEN OPERAND1:= TABLE[OPERAND1];
  1515.              WRITE(TEMP2FILE,OPERAND1:6)
  1516.            END
  1517.       ELSE IF OPERATION IN TWO_OPERANDS
  1518.          THEN
  1519.            BEGIN
  1520.              OPERAND1:= TEMP[K,2];
  1521.              OPERAND2:= TEMP[K,3];
  1522.              IF OPERATION IN [PROC5,PROG5]
  1523.                 THEN
  1524.                   BEGIN
  1525.                     OPERAND1:= TABLE[OPERAND1];
  1526.                     OPERAND2:= TABLE[OPERAND2]
  1527.                   END;
  1528.              WRITE(TEMP2FILE,OPERAND1:6);
  1529.              WRITE(TEMP2FILE,OPERAND2:6)
  1530.            END;
  1531.       WRITELN(TEMP2FILE)
  1532.     END  { FOR K }
  1533. END;     { PROCEDURE SECOND_PASS }
  1534.  
  1535. {-----------------------------------------------------------------------------}
  1536. {----           PROCEDURE INITIALIZE - SETS UP FOR THE RUN                ----}
  1537. {                                                                             }
  1538. PROCEDURE INITIALIZE;
  1539. VAR
  1540.    FIL: FILE;
  1541. BEGIN
  1542.      IF EXIST('TEMP2.')
  1543.         THEN
  1544.           BEGIN
  1545.             ASSIGN(FIL,'TEMP2.');
  1546.             ERASE(FIL)
  1547.           END;
  1548.      IF EXIST('ERROR2.')
  1549.         THEN
  1550.           BEGIN
  1551.             ASSIGN(FIL,'ERROR2.');
  1552.             ERASE(FIL)
  1553.           END;
  1554.      ERROPENED:= FALSE;
  1555.      MAKE_FIRSTS;
  1556.      ROW:= 0;
  1557.      ADDRESS:= 1;
  1558.      CLRSCR;
  1559.      WRITELN(
  1560. 'PL PARSER - SCANS PL SCANNER CODE AND CONVERTS TO CODE FOR THE PL INTERPRETER'
  1561.      );
  1562.      LOWVIDEO;
  1563.      WRITELN(
  1564.    'PARSER V - ERROR RECOVERY, SCOPE AND TYPE ANALYSES, AND CODE GENERATION'
  1565.      );
  1566.      WRITE('AUTHOR:');
  1567.      NORMVIDEO;
  1568.      WRITE(' JAY MONFORT               ');
  1569.      LOWVIDEO;
  1570.      WRITE('FOR:');
  1571.      NORMVIDEO;
  1572.      WRITELN(' MATH 434, COMPILER DESIGN');
  1573.      LOWVIDEO;
  1574.      WRITE('DATE:');
  1575.      NORMVIDEO;
  1576.      WRITELN(' DECEMBER 11, 1986');
  1577.      WRITELN; WRITELN;
  1578.      OPEN_TEMP1;                       { OPEN SCANNER AND      }
  1579.      GOTOXY(20,9);
  1580.      LOWVIDEO;
  1581.      WRITE('LINE NUMBER: ');
  1582.      NORMVIDEO;
  1583.      OPEN_TEMP2                         {   INTERPRETER FILES....     }
  1584. END;    { PROCEDURE INITIALIZE }
  1585.  
  1586. {-----------------------------------------------------------------------------}
  1587. {----               PROCEDURE PARSE - STARTS UP THE PARSING               ----}
  1588. {                                                                             }
  1589. PROCEDURE PARSE;
  1590. BEGIN
  1591.      NEXTSYMBOL;
  1592.      PROGRAMX([ENDTEXT1]);
  1593.      SECOND_PASS
  1594. END;
  1595.  
  1596. {-----------------------------------------------------------------------------}
  1597. {----              PROCEDURE FINALIZE - ENDS EVERYTHING                   ----}
  1598. {                                                                             }
  1599. PROCEDURE FINALIZE;
  1600. VAR
  1601.    CHA: CHAR;
  1602. BEGIN
  1603.      FLUSH(TEMP2FILE);
  1604.      CLOSE(TEMP2FILE);
  1605.      CLOSE(TEMP1FILE);
  1606.      IF ERROPENED
  1607.         THEN
  1608.           BEGIN
  1609.             FLUSH(ERRFILE);
  1610.             CLOSE(ERRFILE);
  1611.             GOTOXY(10,11);
  1612.             WRITE('ERRORS FOUND IN SCANNER CODE - FILE ERROR2 EXISTS'^G^G);
  1613.             GOTOXY(20,13);
  1614.             WRITE('CONTINUE??=(Y/N)=>');
  1615.             REPEAT
  1616.                   READ(KBD,CHA)
  1617.             UNTIL UPCASE(CHA) IN ['Y','N'];
  1618.             IF UPCASE(CHA) = 'N'
  1619.                THEN HALT(100)
  1620.           END
  1621. END;   { PROCEDURE FINALIZE }
  1622.  
  1623.  
  1624.  
  1625. BEGIN           { PROGRAM PARSER }
  1626.      INITIALIZE;
  1627.      PARSE;
  1628.      FINALIZE
  1629. END.            { PROGRAM PARSER }