home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
modula2
/
alexcoco
/
alexfram
< prev
next >
Wrap
Text File
|
1987-07-16
|
7KB
|
271 lines
IMPLEMENTATION MODULE -->modulenamelex;
FROM Files IMPORT
ReadNBytes;
FROM SYSTEM IMPORT
ADR;
FROM FileIO IMPORT
con, WriteString;
CONST
buffersize = 2048; (*input buffer size*)
idmax = 4980; (*max.length of identifier-list*)
htmax = 599; (*max.length of hash table*)
CR = 15C;
LF = 12C;
EF = 4C;
-->declarations
TYPE
Buffer = ARRAY[0..buffersize-1] OF CHAR;
Charset = ARRAY[0..7] OF BITSET;
Class = ARRAY[0..classes-1] OF RECORD
set: Charset;
END;
Starttable = ARRAY[0..127] OF CARDINAL;
VAR
ch: CHAR; (*current input character*)
col: CARDINAL; (*current input columns*)
state: CARDINAL; (*current state*)
apx: CARDINAL; (*length of appendix*)
VAR
class: Class; (*generated character classes*)
comstart: Charset; (*set of comment start symbols*)
ignored: Charset; (*set of ignored characters in start state*)
starttab: Starttable; (*start state for every character*)
attr: CARDINAL; (*attribute value*)
filled: BOOLEAN; (*TRUE if attr is filled*)
VAR
inbuffer: Buffer;
ip: CARDINAL; (*ptr to next character in input buffer*)
ipmax: CARDINAL; (*ptr to last character in input buffer*)
VAR
id: ARRAY[0..idmax+20] OF CHAR; (*identifiers*)
idact: CARDINAL; (*last character IN id*)
idp: CARDINAL; (*last character of new token*)
keys: CARDINAL; (*position OF last keyword IN id*)
ht: ARRAY[0..htmax] OF INTEGER; (*hash table*)
VAR
oldch: ARRAY[0..160] OF CHAR; (*delayed input*)
oldcol: ARRAY[0..160] OF CARDINAL; (*columns of delayed input*)
oldip: CARDINAL; (*length of delayed input*)
eols: CARDINAL; (*nr.of EOLs in a comment*)
i: CARDINAL;
PROCEDURE Comment(): BOOLEAN;
VAR
level: CARDINAL;
och: CHAR;
ocol: CARDINAL;
PROCEDURE RememberEols;
BEGIN
IF eols>0 THEN
IF ch<>LF THEN PushInput(ch); END;
WHILE eols>0 DO PushInput(LF); PushInput(CR); DEC(eols); END;
NextCh;
END;
END RememberEols;
BEGIN (*Comment*)
level:=1; eols:=0;
-->comment
END Comment;
PROCEDURE CutAppendix;
BEGIN
PushInput(ch);
WHILE apx>0 DO
PushInput(id[idp]); DEC(idp); DEC(apx);
END;
NextCh;
END CutAppendix;
PROCEDURE Element(x:CARDINAL; set:Charset): BOOLEAN;
BEGIN RETURN (x MOD 16) IN set[x DIV 16]; END Element;
PROCEDURE GetSy(VAR token:CARDINAL);
VAR typ,column,spix: CARDINAL;
PROCEDURE Error;
BEGIN typ:=errortoken; END Error;
BEGIN (*GetSy*)
IF filled (*attribute available*)
THEN token:=attr; filled:=FALSE;
ELSE
-->GetSy1
column:=col; idp:=idact;
IF Element(ORD(ch),ignored)
THEN ShiftIgnore(starttab[ORD(ch)]);
ELSE Shift(starttab[ORD(ch)]);
END;
LOOP
CASE state OF
1:
-->GetSy2
ELSE Error; NextCh; EXIT;
END; (*CASE*)
END; (*LOOP*)
token:=256*typ+column;
END;
END GetSy;
PROCEDURE GetVal(spix:CARDINAL;VAR name:ARRAY OF CHAR;VAR l:CARDINAL);
VAR i: CARDINAL;
BEGIN
i:=spix; l:=0;
WHILE (id[i]<>0C) AND (l<=HIGH(name)) DO
name[l]:=id[i]; INC(i); INC(l);
END;
END GetVal;
PROCEDURE Hash(VAR spix: CARDINAL);
VAR
h,l: CARDINAL;
d: INTEGER;
PROCEDURE Equal(x,y,l:CARDINAL):BOOLEAN;
VAR i: CARDINAL;
BEGIN
i:=0;
WHILE (i<l) AND (id[x+i]=id[y+i]) DO INC(i); END;
RETURN i=l;
END Equal;
BEGIN (*Hash*)
INC(idp); id[idp]:=0C;
l:=idp-idact; spix:=idact+1;
h:=(ORD(id[spix])*7 + ORD(id[spix+1]) + l) * 17 MOD htmax;
d:= -htmax;
LOOP
IF ht[h]=0 THEN (*new identifier*)
ht[h]:=spix; idact:=idp;
EXIT;
ELSIF Equal(ht[h],spix,l) THEN (*old identifier*)
spix:=ht[h]; EXIT;
ELSE (*collision*)
d:=d+2;
IF d=htmax THEN
WriteString(con,"$--- Hash table full$"); HALT;
END;
h:=(h+CARDINAL(ABS(d))) MOD htmax;
END;
END; (*LOOP*)
IF idp>idmax THEN
WriteString(con,"$--- Name list full$"); HALT;
END;
END Hash;
PROCEDURE InitClass(nr,x1,x2,x3,x4,x5,x6,x7,x8:CARDINAL);
BEGIN
WITH class[nr] DO
set[0]:=BITSET(x1); set[1]:=BITSET(x2);
set[2]:=BITSET(x3); set[3]:=BITSET(x4);
set[4]:=BITSET(x5); set[5]:=BITSET(x6);
set[6]:=BITSET(x7); set[7]:=BITSET(x8);
END;
END InitClass;
PROCEDURE InitIgnored(x1,x2,x3,x4,x5,x6,x7,x8:CARDINAL);
BEGIN
ignored[0]:=BITSET(x1); ignored[1]:=BITSET(x2);
ignored[2]:=BITSET(x3); ignored[3]:=BITSET(x4);
ignored[4]:=BITSET(x5); ignored[5]:=BITSET(x6);
ignored[6]:=BITSET(x7); ignored[7]:=BITSET(x8);
END InitIgnored;
PROCEDURE InitStartTab(base,x1,x2,x3,x4,x5,x6,x7,x8:CARDINAL);
BEGIN
starttab[base]:=x1; starttab[base+1]:=x2;
starttab[base+2]:=x3; starttab[base+3]:=x4;
starttab[base+4]:=x5; starttab[base+5]:=x6;
starttab[base+6]:=x7; starttab[base+7]:=x8;
END InitStartTab;
PROCEDURE Keyword(spix:CARDINAL; VAR keynr:CARDINAL): BOOLEAN;
BEGIN
IF spix<=keys
THEN keynr:=ORD(id[spix-1]); RETURN TRUE;
ELSE RETURN FALSE;
END;
END Keyword;
PROCEDURE NewKey(sy:CARDINAL; key:ARRAY OF CHAR);
VAR i: CARDINAL;
BEGIN
INC(idact); id[idact]:=CHR(sy); idp:=idact;
FOR i:=0 TO HIGH(key) DO INC(idp); id[idp]:=key[i]; END;
Hash(keys); (*keys contains the last keyword spix at any time*)
END NewKey;
PROCEDURE NextCh; (*return global variable ch*)
BEGIN
IF oldip>0
THEN
DEC(oldip); ch:=oldch[oldip]; col:=oldcol[oldip];
ELSE
IF ip>=ipmax THEN
ipmax := ReadNBytes(src,ADR(inbuffer),buffersize);
IF ipmax=0 THEN inbuffer[0]:=EF; END;
ip:=0;
END;
ch:=inbuffer[ip]; INC(ip);
IF ch=LF THEN col:=0; INC(eols); ELSE INC(col); END;
END;
END NextCh;
PROCEDURE PushInput(ch:CHAR);
BEGIN
oldch[oldip]:=ch; oldcol[oldip]:=col; INC(oldip);
END PushInput;
PROCEDURE Shift(s:CARDINAL);
BEGIN
INC(idp); id[idp]:=ch; apx:=0; NextCh;
state:=s;
END Shift;
PROCEDURE ShiftIgnore(s:CARDINAL);
BEGIN
apx:=0; NextCh;
state:=s;
END ShiftIgnore;
PROCEDURE ShiftLA(s:CARDINAL);
BEGIN
INC(idp); id[idp]:=ch; INC(apx); NextCh;
state:=s;
END ShiftLA;
BEGIN (*Scanner*)
ip:=buffersize; ipmax:=ip; oldip:=0; (*init input*)
col:=0; ch:=" "; eols:=0;
filled:=FALSE;
FOR i:=0 TO htmax-1 DO ht[i]:=0; END; (*init name list*)
idact:=0;
-->initializations
END -->modulenamelex.