{########################################################################## #### #### #### Full module name: CONSTANT_TABLE_MODULE_FOR_TYPE_CHECKER_PROGRAM.#### #### File name: CONSTTAB.PAS. #### #### Support modules reqd: PASLIB.ERL. #### #### Run time environment: . #### #### Compile time environment: MT MicroSYSTEMS Pascal/MT+v5.25. #### #### Link time environment: MT MicroSYSTEMS Linkmt v5.1. #### #### Copyright (C) 1982 by Haldo Products, Inc. All rights reserved. #### #### 56 Camille Ln, E. Patchogue, NY 11772 #### #### Programmer: Lawrence Adkins. #### #### Module Development/Maintenance History: #### 6-NOV-81 Vers 1.0. File just created. 12-NOV-81 Development of this version completed. 9-JAN-82 Vers 2.0. development begins. 1-MAR-82 Development of this version complete. 19-APR-82 Vers 2.2. No changes made. #### #### ##########################################################################} MODULE CONSTANT_TABLE_HANDLER; {$I B:TYPECHK.DEC } { list of all our type declarations } VAR last_ct_entry: natural; { last filled element of const table } token: EXTERNAL tokentype; tokenbuf: EXTERNAL string132; exit_keywords: EXTERNAL SET OF tokentype; last_entry_point_name: EXTERNAL string132; outfile: EXTERNAL text; debug: EXTERNAL boolean; EXTERNAL PROCEDURE get_next_token; EXTERNAL PROCEDURE error (pascal_error_no: integer); EXTERNAL PROCEDURE @hlt; {###########################################################################} {--- Initialize the variables in this module } {###########################################################################} PROCEDURE cminit_constant_table_module (VAR const_table: ARRAY [ctlobound..cthibound: natural] OF t_const_tab_rec); BEGIN WITH const_table [1] DO BEGIN const_id := 'MAXINT'; actual_value := 32767 END; WITH const_table [2] DO BEGIN const_id := 'FALSE'; actual_value := 0 END; WITH const_table [3] DO BEGIN const_id := 'TRUE'; actual_value := 1 END; WITH const_table [4] DO BEGIN const_id := 'NIL'; actual_value := 0 END; last_ct_entry := 4 END; {#############################################################################} (*-- First we will skip past the and --- syntax until we hit a token defined in the exit_keyword set. *) (*-- Then we will parse the following Pascal/MT+ BNF productions: --- ::= | --- CONST {; } ; --- --- ::= = --- ::= --- *) {#############################################################################} PROCEDURE cmadd_new_constants_to_const_table (VAR const_table: ARRAY [ctlobound..cthibound: natural] OF t_const_tab_rec); CONST action_message = 'Handling Constants...'; BEGIN writeln (action_message); writeln (outfile, action_message); exit_keywords := [tokconst, toktype, tokvar, tokproc, tokfunc, tokbegin, tokexternal]; REPEAT get_next_token { skip prog heading and label declarations } UNTIL (token IN exit_keywords); WHILE token = tokconst DO BEGIN get_next_token; { should be constant identifier } REPEAT last_entry_point_name := tokenbuf; cminc_last_ct_entry_index (cthibound); WITH const_table [last_ct_entry] DO BEGIN const_id := tokenbuf; get_next_token; { should be tokequal } get_next_token; { should be const_id, number, sign, or string } cmfinish_parsing_constant_value (actual_value, const_table); cmremove_duplicate_const_entry (const_table) END; get_next_token; { should be semicolon } IF debug THEN error (0); get_next_token { should be const_id or new keyword } UNTIL (token IN exit_keywords); END END; {#############################################################################} (*-- Assuming that the first symbol has already been scanned, --- Here we will finish parsing the following Pascal/MT+ BNF productions: --- ::= | | --- | | --- --- ::= | --- ::= . | --- . E | --- E --- ::= {} --- ::= | --- ::= + | - --- ::= --- ::= ' {} ' | '' --- *) {#############################################################################} PROCEDURE cmfinish_parsing_constant_value (VAR actual_value: integer; VAR const_table: ARRAY [ctlobound..cthibound: natural] OF t_const_tab_rec); VAR sign: integer; BEGIN sign := +1; IF (token = tokplus) OR (token = tokminus) THEN BEGIN IF TOKEN = tokminus THEN sign := -1; get_next_token; { should be const_id or unsigned number } END; CASE token OF tokidentifier: BEGIN { look up it's integer value in the table } IF cmfind_const_id (actual_value, const_table) THEN actual_value := actual_value * sign ELSE actual_value := 0 END; tokintnum, tokbytenum, tokrealnum: BEGIN { make the characters into an integer } cmxlate_const_value (actual_value, const_table); actual_value := actual_value * sign END; toklitstring: BEGIN { take the ordinal value of just the first character } IF length (tokenbuf) > 0 THEN actual_value := ord (tokenbuf[1]) ELSE actual_value := 0 END END END; {############################################################################} {---- Check for identical identifier earlier in the table, if match, ----- compare entries, and erase latter entry. } {############################################################################} PROCEDURE cmremove_duplicate_const_entry (VAR const_table: ARRAY [ctlobound..cthibound: natural] OF t_const_tab_rec); VAR i: integer; BEGIN FOR i := 1 TO (last_ct_entry - 1) DO WITH const_table [i] DO IF const_id = const_table [last_ct_entry].const_id THEN BEGIN IF actual_value <> const_table [last_ct_entry].actual_value THEN error (101); { id declared elsewhere with different value } last_ct_entry := last_ct_entry - 1; exit END END; {#############################################################################} {--- Search out specified identifier in constant table. If found, ---- return the index, and true, meaning found. } {#############################################################################} FUNCTION cmfind_const_id (VAR ret_val: integer; VAR const_table: ARRAY [ctlobound..cthibound: natural] OF t_const_tab_rec): boolean; VAR i : integer; name_to_find: alfa; BEGIN ret_val := 0; cm_find_const_id := false; name_to_find := tokenbuf; {shorten length down to alfalen chars} FOR i := 1 TO last_ct_entry DO WITH const_table[i] DO IF const_id = name_to_find THEN BEGIN ret_val := actual_value; cmfind_const_id := true; exit END END; {############################################################################} (*-- Assuming we have already scanned the first symbol, --- Here we will finish parsing the following Pascal/MT+ BNF productions: --- ::= $ | --- ::= {} --- *) {############################################################################} PROCEDURE cmxlate_const_value (VAR ret_val: integer; VAR const_table: ARRAY [ctlobound..cthibound: natural] OF t_const_tab_rec); VAR i, offset, first, last, base: byte; BEGIN last := length(tokenbuf); ret_val := 0; IF tokenbuf[1] = '$' THEN BEGIN first := 2; base := 16 END ELSE BEGIN first := 1; base := 10 END; FOR i := first TO last DO BEGIN IF tokenbuf[i] <= '9' THEN offset := 48 ELSE offset := 65; ret_val := (ret_val * base) + (ord(tokenbuf[i]) - offset) END END; {############################################################################} {--- Bump the index into the constant table by one. Error if overflow. } {############################################################################} PROCEDURE cminc_last_ct_entry_index (max_const_elements: natural); VAR i: integer; BEGIN IF last_ct_entry >= max_const_elements THEN BEGIN writeln; writeln ('Const table overflow. Last id: ', last_entry_point_name); close (outfile, i); @hlt END; last_ct_entry := last_ct_entry + 1 END; {#############################################################################} {--- Display the current contents of the constant table } {#############################################################################} PROCEDURE cmdump_constant_table (VAR outfile: text; VAR const_table: ARRAY [ctlobound..cthibound: natural] OF t_const_tab_rec); VAR i: integer; BEGIN writeln (outfile); writeln (outfile, '--- Constant Table Dump --- '); writeln (outfile, 'name':30, 'value':10); FOR i := 1 TO last_ct_entry DO WITH const_table[i] DO writeln (outfile, i:10, const_id:20, actual_value:10); writeln (outfile) END; {#############################################################################} (*-- Assuming that the first symbol has already been scanned, --- here we will finish parsing the following Pascal/MT+ BNF production : --- ::= ( {, } ) --- *) {#############################################################################} PROCEDURE cmstore_scalar_type_values (VAR n_of_values: integer; VAR const_table: ARRAY [ctlobound..cthibound: natural] OF t_const_tab_rec); BEGIN n_of_values := 0; REPEAT get_next_token; { should be scalar value identifier } cminc_last_ct_entry_index (cthibound); WITH const_table [last_ct_entry] DO BEGIN const_id := tokenbuf; actual_value := n_of_values END; n_of_values := n_of_values + 1; cmremove_duplicate_const_entry (const_table); get_next_token { should be comma or right paren } UNTIL token = tokrparen END; MODEND.