-- file PGSScan.Mesa rewritten by PGS, 29-Aug-80 9:27
-- file PGSScan.Mesa
-- syntax last modified by Satterthwaite, 7-Jan-80 11:31
-- code last modified by Satterthwaite, July 14, 1980 2:53 PM
DIRECTORY
PGS1: TYPE USING [ErrorContext, InputLoc, locateindex, Token],
ParseTable: FROM "PGSParseTable" USING [
ActionEntry, EndMarker, Handle, HashIndex, Production, ProductionInfo,
tokenID, tokenNUM, tokenTAB3, tokenTAB4, TSymbol, VocabHashEntry],
PGScondefs: TYPE;
Scanner: PROGRAM
IMPORTS PGS1, PGScondefs
EXPORTS PGS1, PGScondefs =
BEGIN OPEN PGS1, ParseTable, PGScondefs;
hashTab: POINTER TO ARRAY HashIndex OF VocabHashEntry;
scanTab: POINTER TO ARRAY CHARACTER [40C..177C] OF TSymbol;
vocab: STRING;
vocabIndex: POINTER TO ARRAY TSymbol OF CARDINAL;
check: CARDINAL = 3;
warning: CARDINAL = 0;
specErrorCases: CARDINAL = 5;
token, numRhsChars: CARDINAL;
lineWidth: INTEGER;
insertFlag: CARDINAL;
hashChain: DESCRIPTOR FOR ARRAY [1..symtabsize/4] OF CARDINAL;
ProductionArray: TYPE = ARRAY Production OF ProductionInfo;
-- local data base (supplied by parser)
v: DESCRIPTOR FOR ARRAY OF UNSPECIFIED;
l: DESCRIPTOR FOR ARRAY OF CARDINAL;
q: DESCRIPTOR FOR ARRAY OF ActionEntry;
prodData: POINTER TO ProductionArray;
-- initialization/termination
AssignDescriptors: PUBLIC PROC [
qd: DESCRIPTOR FOR ARRAY OF ActionEntry,
vd: DESCRIPTOR FOR ARRAY OF UNSPECIFIED,
ld: DESCRIPTOR FOR ARRAY OF CARDINAL,
pp: POINTER TO ProductionArray] =
{q ← qd; v ← vd; l ← ld; prodData ← pp};
outtoken: PUBLIC PROC [symbol:CARDINAL] RETURNS [CARDINAL] =
BEGIN
IF symbol=0 THEN {outstring["* * *"]; RETURN[5]};
FOR i:CARDINAL IN [0..syminfo[symbol].length)
DO outchar[symtab[symbol*tokensize+i],1] ENDLOOP;
RETURN [syminfo[symbol].length]
END;
-- the interpretation rules
prix, chix: CARDINAL; --indexes into prodinfo and rhschar
rhsFlag: BOOLEAN;
lastSymbol, lhsDef: CARDINAL;
ProcessQueue: PUBLIC PROC [qI, top: CARDINAL] =
BEGIN qj,i,j,k: CARDINAL;
opt: Options;
-- local procedures
PrintTableHead: PROC [c: CHARACTER]=
BEGIN IF flags[echo] THEN
{outeol[2];outstring["||TABLE"]; outchar[c,1]; outeol[1]}
END;
SetRuleChain: PROC [rule: CARDINAL, chain: BOOLEAN] =
BEGIN
FixLastProd[];
IF prix=LENGTH[prodinfo] THEN --production table overflow
prodinfo ← LOOPHOLE[expand[prodinfo,SIZE[prodrecord],LENGTH[prodinfo]/8]];
prodinfo[prix].chain ← chain;
IF rule>maxrule THEN Error[check+10,-5,InputLoc[]] ELSE prodinfo[prix].rule ← rule
END;
FixLastProd: PROC =
BEGIN prodinfo[prix-1].lhs ← lhsDef;
IF prodinfo[prix-1].count=0 THEN tokeninfo[lhsDef-eofile].empty ← TRUE;
IF rhsFlag THEN -- too many rhschars
{rhsFlag ← FALSE; Error[check+5, (prix-1+specErrorCases), InputLoc[]]};
END;
ProdHeader: PROC [new:BOOLEAN] =
BEGIN
prodinfo[prix].index ← chix;
IF lhsDef>eofile THEN
BEGIN IF tokeninfo[lhsDef-eofile].count=alternatelim THEN
BEGIN Error[check+1, lhsDef,InputLoc[]]; --too many alternatives
tokeninfo[lhsDef-eofile].count ←1
END;
tokeninfo[lhsDef-eofile].count ← tokeninfo[lhsDef-eofile].count + 1;
END;
IF flags[echo] THEN
BEGIN lineWidth ← outbuflim-tokensize-14;
outeol[IF new THEN 2 ELSE 1];outnum[prix,3];
outstring[IF prodinfo[prix].chain THEN " C " ELSE " "];
outnum[prodinfo[prix].rule,3]; outchar[' ,2];
outchar[' ,tokensize-(IF new THEN outtoken[lhsDef] ELSE 0)];
outstring[IF new THEN " ::= " ELSE " | "];
END;
prix ← prix+1
END;
LhsSymbol: PROC [symbol:CARDINAL] =
BEGIN lhsDef ← symbol;
IF lhsDef<=eofile THEN Error[check+4,lhsDef,InputLoc[]]
-- undefined or terminal symbol before ::=
ELSE
IF tokeninfo[lhsDef-eofile].index = 0 THEN tokeninfo[lhsDef-eofile].index ← prix
ELSE Error[check+2,lhsDef,InputLoc[]]; --multiple definitions
ProdHeader[TRUE];
END;
-- end of local procedures
FOR qj IN [0..qI)
DO top ← top-q[qj].tag.pLength+1;
SELECT prodData[q[qj].transition].rule FROM
0 => -- TYPE: ParseTable MODULE: PGSParseTable.mesa
-- BINARY: PGSParseData.bcd INTERFACE: SELF
-- GOAL: grammar
-- TERMINALS:
-- symbol num '? '| "::=" 'C "||TABLE1" "||TABLE2" "||TABLE3"
-- "||TABLE4" "||INPUT" "||CHAIN" "||LISTS" "||PRINTLR"
-- "||PRINTLALR" "||FIRST" "||IDS" "GOAL"
-- ALIASES: symbol tokenID num tokenNUM '? tokenQUERY
-- "||TABLE3" tokenTAB3 "||TABLE4" tokenTAB4 '? InitialSymbol
-- PRODUCTIONS:
-- grammar ::= '? head ruleset
BEGIN FixLastProd[]; numprod ← prix-1; numRhsChars ← chix-1; i ← 1;
IF flags[echo] THEN outeol[1];
IF numprod > psslim OR totaltokens > psslim THEN Error[check+6,0,InputLoc[]];
FreeSegment[BASE[hashChain]];
WHILE syminfo[i].used AND i<=totaltokens
DO IF i>eofile AND tokeninfo[i-eofile].index = 0 THEN EXIT; i ← i+1;
ENDLOOP;
IF i <= totaltokens THEN
BEGIN defflag:BOOLEAN ← FALSE;
lineWidth ← 0; Error[warning+3,0,InputLoc[]]; seterrstream[];
FOR i IN [i..totaltokens]
DO j ← 0; IF ~syminfo[i].used THEN j ← j+1;
IF i > eofile AND tokeninfo[i-eofile].index = 0 THEN j ← j+2;
IF j # 0 THEN
BEGIN
IF (lineWidth ← lineWidth+(k←(11+j)/2)) > outbuflim
THEN {outeol[1]; lineWidth ← k};
outnum[i,5];
IF j#2 THEN outchar['U,1] ELSE defflag ← TRUE;
IF j>1 THEN outchar['D,1]
END;
ENDLOOP;
outeol[1]; resetoutstream[];
IF defflag THEN
Error[check+3,-2,InputLoc[]]; -- nonterminal used but not defined
END;
FOR i IN [1..numprod]
DO IF prodinfo[i].chain THEN
IF prodinfo[i].count # 1 OR rhschar[prodinfo[i].index] <= eofile THEN
BEGIN Error[warning+2, -(i+specErrorCases), InputLoc[]];
prodinfo[i].chain ← FALSE;
END;
ENDLOOP;
END;
1 => -- head ::= directives terminals nonterminals "||TABLE4"
-- head ::= directives terminals nonterminals aliases "||TABLE4"
BEGIN totaltokens ← lastSymbol; PrintTableHead['4];
tokeninfo ← LOOPHOLE[makearray[totaltokens-eofile+1,SIZE[tokenrecord]]];
prodinfo ← LOOPHOLE[makearray[maxprod+1,SIZE[prodrecord]]];
rhschar ← LOOPHOLE[makearray[maxrhssymbols+1,SIZE[CARDINAL]]];
FOR i IN [0..totaltokens-eofile]
DO tokeninfo[i] ← [count:0, empty:FALSE, index:0] ENDLOOP;
prodinfo[0] ← [count:2, rule:0, chain:FALSE, lhs:0, index:0];
FOR i IN [1..maxprod]
DO prodinfo[i] ← [count:0, rule:0, chain:FALSE, lhs:0, index:0];
ENDLOOP;
IF flags[echo] THEN
BEGIN outeol[1]; outchar[' ,20]; outstring["GOAL ::= "];
[] ← outtoken[eofile+1]; outchar[' ,1]; [] ← outtoken[eofile]
END;
rhschar[0] ← eofile+1; rhschar[1] ← eofile;
syminfo[eofile+1].used ← syminfo[eofile].used ← TRUE;
prix ← 1; chix ← 2; lhsDef ← 0; rhsFlag ← FALSE;
END;
2 => -- directives ::=
BEGIN FOR opt IN [FIRST[Options]..LAST[Options]]
DO flags[opt] ← FALSE ENDLOOP;
l[top] ← InputLoc[];
END;
3 => -- directive ::= "||INPUT"
{flags[echo] ← TRUE; setoutstream[".echo"]};
4 => -- directive ::= "||CHAIN"
flags[chain] ← TRUE;
5 => -- directive ::= "||LISTS"
flags[lists] ← TRUE;
6 => -- directive ::= "||PRINTLR"
flags[printlr] ← TRUE;
7 => -- directive ::= "||PRINTLALR"
flags[printlalr] ← TRUE;
8 => -- directive ::= "||FIRST"
flags[first] ← TRUE;
9 => -- directive ::= "||IDS"
flags[ids] ← TRUE;
10 => -- terminals ::= "||TABLE1"
BEGIN
IF flags[echo] THEN
BEGIN outeol[1];
FOR opt IN [FIRST[Options]..LAST[Options]]
DO IF flags[opt] THEN outstring[
SELECT opt FROM
echo => "||INPUT "L,
chain => "||CHAIN "L,
lists => "||LISTS "L,
printlr => "||PRINTLR "L,
printlalr => "||PRINTLALR "L,
first => "||FIRST "L,
ENDCASE => "||IDS "L];
ENDLOOP;
END;
PrintTableHead['1];
END;
11 => -- terminals ::= terminals discard symbol
-- nonterminals ::= nonterminals discard symbol
BEGIN lastSymbol ← v[top+2];
IF flags[echo] THEN
BEGIN outnum[lastSymbol, 3]; outchar[' , 2];
[] ← outtoken[lastSymbol];
outeol[1]
END;
END;
12 => -- nonterminals ::= "||TABLE2"
BEGIN PrintTableHead['2]; eofile ← lastSymbol;
nextalias ← 0; -- assert TABLE3 empty in case it is omitted
END;
13 => -- aliases ::= "||TABLE3"
BEGIN PrintTableHead['3];
aliases ← LOOPHOLE[makearray[64,SIZE[aliasrecord]]];
END;
14 => -- aliases ::= aliases symbol symbol
BEGIN IF v[top+1]>eofile THEN Error[check+7,v[top+1],InputLoc[]];
IF v[top+2]<=eofile THEN Error[check+8,v[top+2],InputLoc[]];
IF nextalias=LENGTH[aliases] THEN
aliases ← LOOPHOLE[expand[aliases,SIZE[aliasrecord],LENGTH[aliases]/8]];
aliases[nextalias] ← [v[top+1],v[top+2]]; nextalias ← nextalias+1;
IF flags[echo] THEN
BEGIN outchar[' ,tokensize+1-outtoken[v[top+1]]]; outchar[' ,1];
j ← v[top+2]*tokensize;
FOR i IN [j..j+tokensize) WHILE symtab[i]#0C DO outchar[symtab[i],1] ENDLOOP;
outeol[1];
END;
END;
15 => -- discard ::=
l[top] ← InputLoc[]; -- keep the parser error recovery happy
16 => -- rulegroup ::= symbol "::="
{SetRuleChain[prix, FALSE]; LhsSymbol[v[top]]};
17 => -- rulegroup ::= prefix symbol "::="
LhsSymbol[v[top+1]];
18 => -- rulegroup ::= rulegroup symbol "::="
{SetRuleChain[prix, FALSE]; LhsSymbol[v[top+1]]};
19 => -- rulegroup ::= rulegroup prefix symbol "::="
LhsSymbol[v[top+2]];
20 => -- rulegroup ::= rulegroup '|
{SetRuleChain[prix, FALSE]; ProdHeader[FALSE]};
21 => -- rulegroup ::= rulegroup prefix '|
ProdHeader[FALSE];
22 => -- rulegroup ::= rulegroup symbol
BEGIN i ← v[top+1]; syminfo[i].used ← TRUE;
IF i=eofile OR i=eofile+1 THEN Error[check+9,0,InputLoc[]]; --goal symbols
IF flags[echo] THEN
BEGIN IF lineWidth<syminfo[i].length THEN
BEGIN outeol[1]; outchar[' ,tokensize+18];
lineWidth ← outbuflim - tokensize-18;
END;
IF (lineWidth ← (lineWidth-outtoken[i]-1)) > 0 THEN outchar[' , 1];
END;
IF chix=LENGTH[rhschar] THEN
rhschar ← LOOPHOLE[expand[rhschar,SIZE[CARDINAL],LENGTH[rhschar]/8]];
rhschar[chix]←i; chix ← chix +1;
IF prodinfo[prix-1].count = rhslim
THEN {prodinfo[prix-1].count ← 1; rhsFlag ← TRUE};
prodinfo[prix-1].count ← prodinfo[prix-1].count+1;
END;
23 => -- prefix ::= num
SetRuleChain[v[top], FALSE];
24 => -- prefix ::= num num
-- prefix ::= '? num
SetRuleChain[v[top+1], FALSE];
25 => -- prefix ::= discard 'C
SetRuleChain[prix, TRUE];
26 => -- prefix ::= discard 'C num
SetRuleChain[v[top+2], TRUE];
27 => -- prefix ::= '?
SetRuleChain[prix, FALSE];
28 => -- directives ::= directives directive
-- discard ::= num
-- discard ::= '?
-- ruleset ::=C rulegroup
-- ruleset ::= goalrule rulegroup
-- goalrule ::= "GOAL" "::=" symbol symbol
NULL;
ENDCASE => ERROR;
ENDLOOP;
END;
-- the following procedure is called from the ScanReset if no errors
FinishInput: PROCEDURE =
BEGIN emptyflag: BOOLEAN ← TRUE;
i,j,k,prix,chix: CARDINAL;
-- compute nonterminals deriving empty
WHILE emptyflag
DO emptyflag ← FALSE;
FOR i IN [1..totaltokens-eofile] -- each nonterminal
DO IF tokeninfo[i].empty THEN LOOP; --which does not derive empty
j ← tokeninfo[i].index;
FOR prix IN [j..j+tokeninfo[i].count)
-- each production of the nonterminal
DO k ← prodinfo[prix].index;
FOR chix IN [k..k+prodinfo[prix].count) -- each rhs character
DO
IF rhschar[chix]<=eofile OR ~tokeninfo[rhschar[chix]-eofile].empty THEN EXIT;
REPEAT FINISHED =>
{tokeninfo[i].empty ← emptyflag ← TRUE; EXIT};
ENDLOOP
ENDLOOP
ENDLOOP
ENDLOOP;
checkout[];
END;
-- the following procedure outputs the data structure contents in the tables:
-- PRODUCTIONINFO TOKENINFO SYMINFO
-- num count rule chain lhs index count empty index link used length symbol
-- 4 1 3 5 1 4 5 2 3 1 5 2 4 1 3 1 ...
checkout: PUBLIC PROC =
BEGIN i: CARDINAL;
IF flags[ids] THEN
BEGIN seterrstream[]; outeol[1];
outstring[" PRODUCTIONINFO TOKENINFO SYMINFO"];
FOR i IN [0..MAX[numprod,totaltokens]]
DO outeol[1]; outnum[i,4]; outchar[' ,1];
IF i>numprod THEN outchar[' ,20] ELSE
BEGIN outnum[prodinfo[i].count,3]; outnum[prodinfo[i].rule,5];
outchar[IF prodinfo[i].chain THEN 'C ELSE ' , 1];
outnum[prodinfo[i].lhs,4]; outnum[prodinfo[i].index,5]; outchar[' ,2];
END;
IF i<=totaltokens AND i>0 THEN
BEGIN IF i<=eofile THEN outchar[' ,11] ELSE
BEGIN outnum[tokeninfo[i-eofile].count,3];
outchar[IF tokeninfo[i-eofile].empty THEN 'E ELSE ' ,1];
outnum[tokeninfo[i-eofile].index,5]; outchar[' ,2]
END;
outnum[syminfo[i].link,4]; outchar[IF syminfo[i].used THEN 'U ELSE ' ,1];
outnum[syminfo[i].length,3]; outchar[' ,1]; [] ← outtoken[i];
END
ENDLOOP;
outeol[1]; outstring["RHSCHAR"]; lineWidth ← outbuflim;
FOR i IN [0..numRhsChars]
DO lineWidth ← lineWidth+tokensize+1;
IF lineWidth > outbuflim THEN {outeol[1]; outnum[i,4]; lineWidth ← 4};
outchar[' ,1]; [] ← outtoken[rhschar[i]];
ENDLOOP;
outeol[1]; resetoutstream[];
END;
END;
-- error recovery
TokenValue: PUBLIC PROC [s: TSymbol] RETURNS [UNSPECIFIED] = {RETURN [0]};
-- text input and error routines
NUL: CHARACTER = 0C;
tB: POINTER TO PACKED ARRAY OF CHARACTER;
tI, tMax: [0..TextChars];
tOrigin, tLimit: CARDINAL;
tEnded: BOOLEAN;
FillTextBuffer: PROC =
BEGIN tOrigin ← tLimit;
IF tEnded THEN tMax ← 0 ELSE
{[tB, tMax, tEnded] ← nextbuffer[]; tLimit ← tOrigin + tMax};
IF tMax = 0 THEN {tB[0] ← NUL; tMax ← 1};
tI ← 0;
END;
buffer: STRING = [tokensize]; -- token assembly area
nTokens: CARDINAL; -- token count
nErrors: CARDINAL; -- lexical errors
char: CHARACTER; -- current (most recently scanned) character
NextChar: PROC = -- also expanded inline within Atom
BEGIN IF (tI←tI+1) = tMax THEN FillTextBuffer[];
char ← tB[tI];
END;
Atom: PUBLIC PROC RETURNS [t: Token] =
BEGIN OPEN t;
LocateToken: PROC [string: STRING] RETURNS [CARDINAL] =
BEGIN -- returns token corresponding to string
i,j,k: CARDINAL;
j ← hashChain[(string.length*256+LOOPHOLE[string[0],CARDINAL])
MOD (symtabsize/4) + 1];
WHILE j # 0
DO IF syminfo[j].length = string.length THEN
BEGIN i ← j*tokensize;
FOR k IN [0..string.length)
DO IF symtab[i+k]#string[k] THEN EXIT
REPEAT FINISHED => RETURN[j]
ENDLOOP;
END;
j ← syminfo[j].link;
ENDLOOP;
RETURN [0]
END;
TokenToSymTab: PROC [string: STRING, token: CARDINAL] =
BEGIN i,j: CARDINAL;
i ← token*tokensize;
FOR j IN [0..string.length) DO symtab[i+j] ← string[j] ENDLOOP;
syminfo[token].length ← string.length; syminfo[token].used ← FALSE;
j ← (string.length*256+LOOPHOLE[string[0],CARDINAL])
MOD (symtabsize/4) + 1;
syminfo[token].link ← hashChain[j]; hashChain[j] ← token;
END;
TokenOrId: PROC [sub:CARDINAL]=
BEGIN j, s1, s2: CARDINAL;
h: HashIndex;
WHILE char ~IN [NUL..' ]
DO IF sub<tokensize THEN buffer[sub] ← char;
sub ← sub + 1; NextChar[];
ENDLOOP;
IF sub>tokensize
THEN {buffer.length←sub←tokensize; Error[1,-1,index]}; --overlength
IF sub = 1 THEN
BEGIN class ← scanTab[buffer[0]];
IF class # 0 THEN RETURN
END;
j ← buffer[0] - 0C;
h ← ((j*128-j) + CARDINAL[buffer[sub-1]-0C]) MOD LAST[HashIndex] + 1;
WHILE (j ← hashTab[h].symbol) # 0
DO IF vocabIndex[j]-(s2←vocabIndex[j-1]) = sub THEN
FOR s1 IN [0 .. sub)
DO IF buffer[s1] # vocab[s2] THEN EXIT;
s2 ← s2+1;
REPEAT FINISHED =>
BEGIN IF j = tokenTAB3 THEN insertFlag ← 2 ELSE
IF j = tokenTAB4 THEN insertFlag ← 3;
IF j<=tokenNUM THEN EXIT;
class ← j; RETURN
END;
ENDLOOP;
IF (h ← hashTab[h].link) = 0 THEN EXIT;
ENDLOOP;
buffer.length←sub; class←tokenID; value←LocateToken[buffer];
SELECT insertFlag FROM
1 =>
-- reading terminals and nonterminals
IF value # 0 THEN Error[check+2,value,index] -- multiply defined symbol
ELSE
BEGIN IF token=LENGTH[symtab] THEN
BEGIN symtab ← LOOPHOLE[
expand[LOOPHOLE[symtab],wordsfortoken,LENGTH[symtab]/16]];
syminfo ← LOOPHOLE[expand[syminfo,SIZE[symtabrecord],LENGTH[syminfo]/16]];
END;
TokenToSymTab[buffer, token]; value ← token; token ← token+1;
END;
2 =>
-- processing aliases
IF value=0 THEN
BEGIN s1 ← token*tokensize;
IF token=LENGTH[symtab] THEN
symtab ← LOOPHOLE[
expand[LOOPHOLE[symtab],wordsfortoken,LENGTH[symtab]/16]];
FOR j IN [0..buffer.length) DO symtab[s1+j] ← buffer[j] ENDLOOP;
value ← token; token ← token+1;
END;
3 =>
-- processing productions
IF value = 0 THEN Error[check+3,-3,index]; --symbol not defined
ENDCASE;
END;
DO WHILE char IN [NUL..' ]
DO SELECT char FROM
ControlZ =>
UNTIL char = CR
DO
IF (tI←tI+1) = tMax
THEN {IF tEnded THEN GO TO EndFile; FillTextBuffer[]};
char ← tB[tI];
ENDLOOP;
ENDCASE;
IF (tI←tI+1) = tMax
THEN {IF tEnded THEN GO TO EndFile; FillTextBuffer[]};
char ← tB[tI];
ENDLOOP;
index ← tOrigin + tI; value ← 0;
SELECT char FROM
IN ['0..'9] =>
BEGIN val:CARDINAL; valid:BOOLEAN;
maxval:CARDINAL=6553; maxd:CARDINAL = 5;
valid ← TRUE; val ← 0;
WHILE char IN ['0..'9]
DO IF valid THEN
BEGIN d:[0..9];
d ← char-'0; val ← 10*val +d;
valid ← val<maxval OR (val=maxval AND d<=maxd);
END;
NextChar[];
ENDLOOP;
IF ~valid THEN val ←maxval*10+maxd;
class ← tokenNUM; value ← val; GO TO GotNext;
END;
'- =>
BEGIN pChar: CHARACTER;
NextChar[];
IF char # '- THEN {buffer[0] ← '-; TokenOrId[1]; GO TO GotNext};
char ← NUL;
DO pChar ← char;
IF (tI←tI+1) = tMax
THEN {IF tEnded THEN GO TO EndFile; FillTextBuffer[]};
char ← tB[tI];
SELECT char FROM
'- => IF pChar = '- THEN EXIT;
CR => EXIT;
ENDCASE;
ENDLOOP;
NextChar[];
END;
ENDCASE => {TokenOrId[0]; GO TO GotNext};
REPEAT
GotNext => NULL;
EndFile =>
BEGIN
FillTextBuffer[]; char ← tB[tI];
class ← EndMarker; index ← tOrigin; value ← 0;
END;
ENDLOOP;
nTokens ← nTokens + 1;
RETURN
END;
-- initialization/finalization
ScanInit: PUBLIC PROC [tablePtr: ParseTable.Handle] =
BEGIN i: CARDINAL;
hashTab ← @tablePtr.scanTable.hashTab;
scanTab ← @tablePtr.scanTable.scanTab;
vocab ← LOOPHOLE[@tablePtr.scanTable.vocabBody, STRING];
vocabIndex ← @tablePtr.scanTable.vocabIndex;
tLimit ← 0; tMax ← 0; tEnded ← FALSE;
FillTextBuffer[]; char ← tB[tI];
nTokens ← nErrors ← 0; buffer.length ← tokensize;
-- initialise symbol table
token ← 1; insertFlag ← 1;
symtab ← LOOPHOLE[makearray[symtabsize+1,wordsfortoken]];
syminfo ← LOOPHOLE[makearray[symtabsize+1,SIZE[symtabrecord]]];
FOR i IN [1..symtabsize]
DO syminfo[i] ← [link:0, length:0, used:FALSE] ENDLOOP;
hashChain ← DESCRIPTOR[AllocateSegment[symtabsize/4],symtabsize/4];
FOR i IN [1..symtabsize/4] DO hashChain[i] ← 0 ENDLOOP;
END;
ScanReset: PUBLIC PROC [pErrors: CARDINAL] RETURNS [CARDINAL, CARDINAL] =
BEGIN
IF (pErrors+nErrors)=0 THEN FinishInput[]; RETURN [nTokens, nErrors]
END;
-- error handling
ResetScanIndex: PUBLIC PROC [index: CARDINAL] =
BEGIN
IF index = tLimit THEN {FillTextBuffer[]; char ← tB[tI]; RETURN};
IF index < tOrigin THEN
BEGIN tLimit ← locateindex[index]; tMax ← 0; tEnded ← FALSE;
FillTextBuffer[];
END;
tI ← index - tOrigin; char ← tB[tI];
END;
Error: PROC [code: CARDINAL, control: INTEGER, index: CARDINAL]=
BEGIN
ErrorContext[ SELECT code FROM
1 => "WARNING - Overlength symbol (increase TOKENSIZE?) truncated to - "L,
2 => "WARNING - Not a chain production - "L,
3 => "WARNING - Unused(U) or undefined(D)symbols (refer to TABLE1 and 2)"L,
4 => "ERROR - Nonterminal with too many rules (increase ALTERNATELIM?) - "L,
5 => "ERROR - Multiple definitions of symbol - "L,
6 => "ERROR - Symbol not defined - "L,
7 => "ERROR - Terminal precedes ::= - "L,
8 => "ERROR - Too many rhs symbols in production (increase RHSLIM?) - "L,
9 => "ERROR - Internal field will overflow - increase PSSLIM"L,
10 => "ERROR - Aliased symbol not a terminal symbol - "L,
11 => "ERROR - Aliases must not be terminal symbols - "L,
12 => "ERROR - Goal symbols used in rhs"L,
13 => "ERROR - Number greater than "L,
ENDCASE => NIL,
index];
IF code>check THEN nErrors ← nErrors+1;
SELECT -control FROM
<0 => [] ← outtoken[control];
0 => NULL;
1 => outstring[buffer];
2 => outstring["see previous message"L];
3 => {outstring[buffer]; outstring[" not in TABLE1 or 2"L]};
4 => NULL; -- not used
5 => outstring["MAXRULE"L];
ENDCASE => outnum[-control-specErrorCases, 5];
outeol[2];
IF code<=check THEN warningslogged ← TRUE;
resetoutstream[];
END;
END.