📄 makescan.p
字号:
(*==================================== MAKESCAN reads tables file produced by scangen and writes C variable definitions on standard output for appropriate tables to be linked into the scanner======================================*)program makescan (tables, output);#include "scanner.h"const HASH_TABLE_SIZE = 3001; {3001 is prime} MAX_CHAR_CODE = 127; MAX_CHAR_CLASS = 45; MAX_SCANNER_STATE = 60; MAX_RESERVE_WORD = 50; ERROR = 0; MOVE_APPEND = 1; MOVE_NO_APPEND = 2; HALT_APPEND = 3; HALT_NO_APPEND = 4; HALT_REUSE = 5; type HashTableIndex = 1..HASH_TABLE_SIZE; CharClass = 0..MAX_CHAR_CLASS; ScannerState = 0..MAX_SCANNER_STATE; ScannerAction = ERROR..HALT_REUSE; ReserveWord = 1..MAX_RESERVE_WORD; StateVector = record case action : ScannerAction of MOVE_APPEND, MOVE_NO_APPEND : (nextState : ScannerState); HALT_APPEND, HALT_NO_APPEND, HALT_REUSE : (major : MajorTokenNum; minor : MinorTokenNum) end; StateInfoRec = record case terminal : Boolean of true : (defaultMajor : MajorTokenNum; defaultMinor : MinorTokenNum) end; ReserveArrayRec = record major : MajorTokenNum; minor : MinorTokenNum; ssLoc : StringSpaceIndex; end;var tables : text; scannerStringSpace : array[1..MAX_STRING_SPACE] of char; nextFreeStringSpace : StringSpaceIndex; hashTable : array[HashTableIndex] of StringSpaceIndex; reserveWordArray : array[1..MAX_RESERVE_WORD] of ReserveArrayRec; charClassArray : array[0..MAX_CHAR_CODE] of CharClass; stateMatrix : array[1..MAX_SCANNER_STATE, 1..MAX_CHAR_CLASS] of StateVector; stateInfoArray : array[1..MAX_SCANNER_STATE] of StateInfoRec; {keeps track of which states are terminal, and for what} numReserveWords : ReserveWord; endOfFile : MajorTokenNum; scannerNumTerms : MajorTokenNum; startState : ScannerState; maxReserveLocation : StringSpaceIndex; idMajorNum : MajorTokenNum; idMinorNum : MinorTokenNum;(******** Inserts a character into the next available slot in StringSpace. Checks against overflow. Converts all lower-case characters to upper case, on the assumption that case is insignificant. ********)procedure InsertStringSpace (ch : char);begin if nextFreeStringSpace = MAX_STRING_SPACE then begin {we are about to overflow} message ('Out of room in scanner string storage area.'); halt; end; if ch in ['a'..'z'] then ch := chr (ord (ch) - (ord ('a') - ord ('A'))); scannerStringSpace[nextFreeStringSpace] := ch; nextFreeStringSpace := nextFreeStringSpace + 1end; {InsertStringSpace}(******** produce C generate_code initialized globals for all static variables ********)procedure OutputTables;var i, j : integer;begin writeln('#include "scantab.h"'); write ('char st_string_space[', MAX_STRING_SPACE:1, '] = "'); for i := 1 to nextFreeStringSpace - 1 do if scannerStringSpace[i] = chr (NULL) then write ('\0') else write (scannerStringSpace[i]); writeln ('";'); writeln ('short st_used_strings = ', nextFreeStringSpace:1, ';'); writeln ('reserve_array_t st_reserved_words[] = {'); for i := 1 to numReserveWords-1 do begin with reserveWordArray[i] do writeln (' {', major:1, ', ', minor:1, ', ', (ssLoc - 1):1, '},'); end; with reserveWordArray[numReserveWords] do writeln (' {', major:1, ', ', minor:1, ', ', (ssLoc - 1):1, '}};'); write ('char st_char_class[] = {'); for i := 0 to MAX_CHAR_CODE-1 do begin if i mod 5 = 0 then begin writeln; write (tab); end; write ((charClassArray[i]-1):1, ', '); (* !!GCH *) end; writeln (charClassArray[MAX_CHAR_CODE]:1, '};'); (* !!GCH *) writeln ('state_vector_t st_state_matrix[', MAX_SCANNER_STATE:1, '][', MAX_CHAR_CLASS:1, '] = {'); for i := 1 to MAX_SCANNER_STATE do begin writeln(' { '); for j := 1 to MAX_CHAR_CLASS do begin with stateMatrix[i,j] do begin write (' {', action:1, ','); case action of ERROR : write ('0,0,0}'); MOVE_APPEND, MOVE_NO_APPEND : write ((nextState-1):1, ',0,0}'); (* !!GCH *) HALT_APPEND, HALT_NO_APPEND, HALT_REUSE : write ('0,', major:1, ',', minor:1,'}'); end; (*case*) if (j <> MAX_CHAR_CLASS) then writeln (','); end; (*with*) end; (*for j*) if (i = MAX_SCANNER_STATE) then writeln(' } ') else writeln(' }, '); end; (*for i*) writeln('};'); writeln ('state_info_t st_state_info [] = {'); for i := 1 to MAX_SCANNER_STATE do with stateInfoArray[i] do begin if terminal then write (' { true, ', defaultMajor:1, ', ', defaultMinor:1, ' }') else write (' { false, 0, 0 }'); if i = MAX_SCANNER_STATE then writeln ('};') else writeln (','); end; (*with*) writeln ('char st_num_reserved_words = ', numReserveWords:1, ';'); writeln ('char st_end_of_file = ', endOfFile:1, ';'); writeln ('char st_num_terminals = ', scannerNumTerms:1, ';'); writeln ('char st_start_state = ', (startState-1):1, ';'); (* GCH!! *) writeln ('short st_max_reserve_location = ', maxReserveLocation:1, ';'); writeln ('char st_id_major_num = ', idMajorNum:1, ';'); writeln ('char st_id_minor_num = ', idMinorNum:1, ';');end; (*OutputTables*)(******** Establishes initial values for all static variables in this module. tables contains output from the DFA generator and is passed here from main module. ********)procedure Initialize;var i : HashTableIndex; j : 0..MAX_CHAR_CODE; numStates : ScannerState; numClasses : CharClass; numLists : integer; (******** Inserts all reserved words into hashTable, reserveWordArray, and scannerStringSpace. ********) procedure HashReserveWords (numReserveWords : ReserveWord); var ch : char; i : ReserveWord; start : StringSpaceIndex; begin for i := 1 to numReserveWords do begin start := nextFreeStringSpace; read (tables, ch); repeat InsertStringSpace (ch); read (tables, ch); until ch = BLANK; InsertStringSpace (chr (NULL)); with reserveWordArray[i] do begin read (tables, major, minor); if (major >= endOfFile) then endOfFile := major + 1; ssLoc := start; (*start will be changed iff this reserve word is a duplicate*) if start <> ssLoc then begin message (scannerStringSpace); message ('***** INTERNAL ERROR: ', 'multiple identical keywords.'); halt; end; end; (*with*) readln (tables); end end; (*HashReserveWords*) (******** Initializes stateMatrix and stateInfoArray. ********) procedure CreateStateMatrix (numStates : ScannerState; numClasses : CharClass); var i : ScannerState; j : CharClass; x : integer; (*dummy variable for read-in*) begin for i := 1 to numStates do begin stateInfoArray[i].terminal := false; (*at least temporarily*) for j := 1 to numClasses do with stateMatrix[i,j] do begin read (tables, x); action := x; if action <> ERROR then if action in [MOVE_APPEND, MOVE_NO_APPEND] then begin read (tables, x); nextState := x end else begin read (tables, x); major := x; if (major >= endOfFile) then (*we want endOfFile one greater than top token*) endOfFile := major + 1; read (tables, x); minor := x; if action = HALT_REUSE then with stateInfoArray[i] do begin (*load terminal values*) terminal := true; defaultMajor := major; defaultMinor := minor end (*inner with*) end end (*with*) end (*for*) end; (*CreateStateMatrix*)begin (*Initialize*) nextFreeStringSpace := 1; for i := 1 to HASH_TABLE_SIZE do hashTable[i] := NULL; reset (tables); read (tables, numStates, startState, numClasses, numReserveWords, numLists); if numLists <> 1 then begin message (' '); message ('***** INTERNAL ERROR: Scanner does not accept multiple'); message (' classes of reserve words.'); halt end; readln (tables); for j := 0 to MAX_CHAR_CODE do read (tables, charClassArray[j]); readln (tables); read (tables, idMajorNum, idMinorNum); readln (tables); endOfFile := 0; (*Increased by HashReserveWords and CreateStateMatrix*) HashReserveWords (numReserveWords); maxReserveLocation := nextFreeStringSpace - 1; CreateStateMatrix (numStates, numClasses); scannerNumTerms := endOfFile; (*return so can check with parser*)end; (*Initialize*)begin (*main*) Initialize; OutputTables;end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -