| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- IMPLEMENTATION MODULE M2S; (*NW 17.8.83 / 31.3.85*)
- FROM SYSTEM IMPORT LONG;
- FROM FileSystem IMPORT
- File, Response, Lookup, ReadChar, WriteChar, GetPos, SetPos, Close;
- CONST KW = 42; (*number of keywords*)
- maxDig = 7;
- maxCard = 177777B;
- maxExp = 38;
- IdBufLim = IdBufLeng - 100;
- FNM = 300C;
- ERR = 301C;
- VAR ch: CHAR; (*current character*)
- id0, id1: CARDINAL; (*indices of identifier buffer*)
- keyTab: ARRAY [0..KW-1] OF
- RECORD sym: Symbol; ind: CARDINAL END;
- K: CARDINAL;
- pow: ARRAY [0..5] OF REAL;
- lastPos: CARDINAL;
- errDat,
- errLog: File;
- PROCEDURE Times16(x: LONGINT): LONGINT;
- CODE 216B; 216B; 216B; 216B
- END Times16;
- PROCEDURE ErrorBlock(errPos: LONGINT; errCod: CARDINAL);
- VAR i: CARDINAL;
- conv: RECORD
- CASE :CARDINAL OF
- 0: long: LONGINT
- | 1: sys: ARRAY [0..3] OF CHAR;
- END;
- END;
- BEGIN
- IF errPos >= 2D THEN errPos := errPos - 2D END;
- WriteChar(errDat, ERR);
- WITH conv DO
- long := errPos; FOR i := 3 TO 0 BY -1 DO WriteChar(errDat, sys[i]) END;
- END;
- WriteChar(errDat, CHR(errCod MOD 256)); WriteChar(errDat, CHR(errCod DIV 256));
- END ErrorBlock;
- PROCEDURE Mark(n: CARDINAL);
- VAR k, p0, p1: CARDINAL; buf: CHAR;
- dig: ARRAY [0..3] OF CARDINAL;
- BEGIN scanerr := TRUE; k := 4; GetPos(source, p0, p1);
- IF lastPos + 8 < p1 THEN
- ErrorBlock(LONG(p0, p1), n);
- IF lastPos + 100 < p1 THEN
- lastPos := p1 - 100; SetPos(source, p0, lastPos);
- WriteChar(errLog, 36C); WriteChar(errLog, 36C);
- REPEAT ReadChar(source, buf); INC(lastPos)
- UNTIL (buf = 36C) OR (lastPos = p1)
- ELSE SetPos(source, p0, lastPos)
- END ;
- WHILE lastPos < p1 DO
- ReadChar(source, buf); WriteChar(errLog, buf); INC(lastPos)
- END ;
- WriteChar(errLog, " ");
- REPEAT WriteChar(errLog, "*"); DEC(k) UNTIL k = 0;
- REPEAT dig[k] := n MOD 10; n := n DIV 10; INC(k) UNTIL n = 0;
- REPEAT DEC(k); WriteChar(errLog, CHR(dig[k] + 60B)) UNTIL k = 0;
- WriteChar(errLog, " ")
- END
- END Mark;
- PROCEDURE GetCh;
- BEGIN ReadChar(source, ch)
- END GetCh;
-
- PROCEDURE Diff(i, j: CARDINAL): INTEGER;
- VAR k: CARDINAL;
- BEGIN k := ORD(IdBuf[i]);
- LOOP
- IF k = 0 THEN RETURN 0
- ELSIF IdBuf[i] # IdBuf[j] THEN
- RETURN INTEGER(ORD(IdBuf[i])) - INTEGER(ORD(IdBuf[j]))
- ELSE INC(i); INC(j); DEC(k)
- END
- END
- END Diff;
- PROCEDURE KeepId;
- BEGIN id := id1
- END KeepId;
-
- PROCEDURE String(termCh: CHAR);
- BEGIN id1 := id + 1;
- IF id1 > IdBufLim THEN Mark(91); id1 := 1 END ;
- LOOP GetCh;
- IF ch = termCh THEN EXIT END ;
- IF ch < " " THEN Mark(45); EXIT END ;
- IdBuf[id1] := ch; INC(id1)
- END ;
- GetCh; IdBuf[id] := CHR(id1-id); (*length*)
- IF IdBuf[id] = 2C THEN
- sym := number; numtyp := 3; intval := ORD(IdBuf[id+1])
- ELSE sym := string;
- IF IdBuf[id] = 1C THEN (*empty string*)
- IdBuf[id1] := 0C; INC(id1); IdBuf[id] := 2C
- END
- END
- END String;
- PROCEDURE Identifier;
- VAR k, l, m: CARDINAL;
- BEGIN id1 := id + 1;
- IF id1 > IdBufLim THEN Mark(91); id1 := 1 END;
- REPEAT
- IdBuf[id1] := ch; INC(id1); GetCh
- UNTIL (ch < "0") OR ("9" < ch) & (CAP(ch) < "A") OR ("Z" < CAP(ch));
- IdBuf[id] := CHR(id1-id); (*Length*)
- k := 0; l := KW;
- REPEAT m := (k + l) DIV 2;
- IF Diff(id, keyTab[m].ind) <= 0 THEN l := m ELSE k := m + 1 END
- UNTIL k >= l;
- IF (k < KW) & (Diff(id, keyTab[k].ind) = 0) THEN sym := keyTab[k].sym
- ELSE sym := ident
- END
- END Identifier;
- PROCEDURE Number;
- VAR i, j, l, d, e, n: CARDINAL;
- x, f: REAL;
- d0, d1: LONGINT;
- neg: BOOLEAN;
- lastCh: CHAR;
- dig: ARRAY [0..31] OF CHAR;
- PROCEDURE Ten(e: CARDINAL): REAL;
- VAR k: CARDINAL; u: REAL;
- BEGIN k := 0; u := 1.0;
- WHILE e > 0 DO
- IF ODD(e) THEN u := pow[k] * u END ;
- e := e DIV 2; INC(k)
- END ;
- RETURN u
- END Ten;
- BEGIN sym := number; i := 0;
- REPEAT dig[i] := ch; INC(i); GetCh
- UNTIL (ch < "0") OR ("9" < ch) & (CAP(ch) < "A") OR ("Z" < CAP(ch));
- lastCh := ch; j := 0;
- WHILE (j < i) & (dig[j] = "0") DO INC(j) END ;
- IF ch = "." THEN GetCh;
- IF ch = "." THEN
- lastCh := 0C; ch := 177C (*ellipsis*)
- END
- END ;
- IF lastCh = "." THEN (*decimal point*)
- x := 0.0; l := 0;
- WHILE j < i DO (*read int part*)
- IF l < maxDig THEN
- IF dig[j] > "9" THEN Mark(40) END ;
- x := x * 10.0 + FLOAT(ORD(dig[j])-60B); INC(l)
- ELSE Mark(41)
- END;
- INC(j)
- END ;
- l := 0; f := 0.0;
- WHILE ("0" <= ch) & (ch <= "9") DO (*read fraction*)
- IF l < maxDig THEN
- f := f * 10.0 + FLOAT(ORD(ch)-60B); INC(l)
- END ;
- GetCh
- END ;
- x := f / Ten(l) + x; e := 0; neg := FALSE;
- IF ch = "E" THEN GetCh;
- IF ch = "-" THEN
- neg := TRUE; GetCh
- ELSIF ch = "+" THEN GetCh
- END ;
- WHILE ("0" <= ch) & (ch <= "9") DO (*read exponent*)
- e := e * 10 + ORD(ch)-60B;
- GetCh
- END
- END ;
- IF neg THEN
- IF e <= maxExp THEN x := x / Ten(e) ELSE x := 0.0 END
- ELSE
- IF e <= maxExp THEN f := Ten(e);
- IF MAX(REAL) / f >= x THEN x := f*x ELSE Mark(41) END
- ELSE Mark(41)
- END
- END ;
- numtyp := 4; realval := x
- ELSE (*integer*)
- lastCh := dig[i-1];
- IF lastCh = "B" THEN
- DEC(i); intval := 0; numtyp := 1;
- WHILE j < i DO
- d := ORD(dig[j]) - 60B;
- IF (d < 10B) & ((maxCard - d) DIV 10B >= intval) THEN
- intval := 10B * intval + d
- ELSE Mark(29); intval := 0
- END ;
- INC(j)
- END
- ELSIF lastCh = "H" THEN DEC(i);
- IF i <= j+4 THEN
- numtyp := 1; intval := 0;
- WHILE j < i DO
- d := ORD(dig[j]) - 60B;
- IF d > 26B THEN Mark(29); d := 0
- ELSIF d > 9 THEN d := d-7
- END ;
- intval := 10H * intval + d; INC(j)
- END
- ELSIF i <= j+8 THEN
- numtyp := 2; dblval := 0D;
- REPEAT d := ORD(dig[j]) - 60B;
- IF d > 26B THEN Mark(29); d := 0
- ELSIF d > 9 THEN d := d-7
- END ;
- dblval := Times16(dblval) + LONG(0,d); INC(j)
- UNTIL j = i
- ELSE Mark(29); numtyp := 2
- END
- ELSIF lastCh = "D" THEN
- DEC(i); d1 := 0D; numtyp := 2;
- WHILE j < i DO
- d := ORD(dig[j]) - 60B;
- IF d < 10 THEN (*no overflow check*)
- d1 := d1 + d1; d0 := d1 + d1; d1 := d0 + d0 + d1 + LONG(0, d)
- ELSE Mark(29); d1 := 0D
- END ;
- INC(j)
- END ;
- dblval := d1
- ELSIF lastCh = "C" THEN
- DEC(i); intval := 0; numtyp := 3;
- WHILE j < i DO
- d := ORD(dig[j]) - 60B; intval := 10B * intval + d;
- IF (d >= 10B) OR (intval >= 400B) THEN
- Mark(29); intval := 0
- END ;
- INC(j)
- END
- ELSE (*decimal?*)
- numtyp := 1; intval := 0;
- WHILE j < i DO
- d := ORD(dig[j]) - 60B;
- IF (d < 10) & ((maxCard-d) DIV 10 >= intval) THEN
- intval := 10*intval + d
- ELSE Mark(29); intval := 0
- END ;
- INC(j)
- END
- END
- END
- END Number;
- PROCEDURE GetSym;
- VAR xch: CHAR;
- PROCEDURE Comment;
- BEGIN GetCh;
- REPEAT
- WHILE (ch # "*") & (ch > 0C) DO
- IF ch = "(" THEN GetCh;
- IF ch = "*" THEN Comment END
- ELSE GetCh
- END
- END ;
- GetCh
- UNTIL (ch = ")") OR (ch = 0C);
- IF ch > 0C THEN GetCh ELSE Mark(42) END
- END Comment;
- BEGIN
- LOOP (*ignore control characters*)
- IF ch <= " " THEN
- IF ch = 0C THEN ch := " "; EXIT ELSE GetCh END ;
- ELSIF ch > 177C THEN GetCh
- ELSE EXIT
- END
- END ;
- CASE ch OF (* " " <= ch <= 177C *)
- " " : sym := eof; ch := 0C |
- "!" : sym := null; GetCh |
- '"' : String('"') |
- "#" : sym := neq; GetCh |
- "$" : sym := null; GetCh |
- "%" : sym := null; GetCh |
- "&" : sym := and; GetCh |
- "'" : String("'") |
- "(" : GetCh;
- IF ch = "*" THEN Comment; GetSym
- ELSE sym := lparen
- END |
- ")" : sym := rparen; GetCh|
- "*" : sym := times; GetCh |
- "+" : sym := plus; GetCh |
- "," : sym := comma; GetCh |
- "-" : sym := minus; GetCh |
- "." : GetCh;
- IF ch = "." THEN GetCh; sym := ellipsis
- ELSE sym := period
- END |
- "/" : sym := slash; GetCh |
- "0".."9": Number |
- ":" : GetCh;
- IF ch = "=" THEN GetCh; sym := becomes
- ELSE sym := colon
- END |
- ";" : sym := semicolon; GetCh |
- "<" : GetCh;
- IF ch = "=" THEN GetCh; sym := leq
- ELSIF ch = ">" THEN GetCh; sym := neq
- ELSE sym := lss
- END |
- "=" : sym := eql; GetCh |
- ">" : GetCh;
- IF ch = "=" THEN GetCh; sym := geq
- ELSE sym := gtr
- END |
- "?" : sym := null; GetCh |
- "@" : sym := null; GetCh |
- "A".."Z": Identifier |
- "[" : sym := lbrak; GetCh |
- "\" : sym := null; GetCh |
- "]" : sym := rbrak; GetCh |
- "^" : sym := arrow; GetCh |
- "_" : sym := becomes; GetCh |
- "`" : sym := null; GetCh |
- "a".."z": Identifier |
- "{" : sym := lbrace; GetCh|
- "|" : sym := bar; GetCh |
- "}" : sym := rbrace; GetCh|
- "~" : sym := not; GetCh |
- 177C : sym := ellipsis; GetCh
- END
- END GetSym;
- PROCEDURE Enter(name: ARRAY OF CHAR): CARDINAL;
- VAR j, l: CARDINAL;
- BEGIN l := HIGH(name)+2; id1 := id;
- IF id1+l < IdBufLeng THEN
- IdBuf[id] := CHR(l); INC(id);
- FOR j := 0 TO l-2 DO IdBuf[id] := name[j]; INC(id) END
- END ;
- RETURN id1
- END Enter;
- PROCEDURE InitScanner(VAR name: ARRAY OF CHAR);
- VAR i: INTEGER;
- BEGIN ch := " "; scanerr := FALSE; lastPos := 0;
- IF id0 = 0 THEN
- id0 := id; Lookup(errLog, "DK.err.LST", TRUE);
- Lookup(errDat, "DK.err.DAT", TRUE)
- ELSE id := id0; WriteChar(errLog, "-"); WriteChar(errLog, 36C)
- END;
- WriteChar(errDat, FNM); i := 0;
- WHILE name[i] > 0C DO
- WriteChar(errDat, name[i]); WriteChar(errLog, name[i]); i := i+1
- END ;
- WriteChar(errLog, " "); WriteChar(errDat, 0C)
- END InitScanner;
-
- PROCEDURE CloseScanner;
- BEGIN Close(errLog); Close(errDat)
- END CloseScanner;
-
- PROCEDURE EnterKW(sym: Symbol; name: ARRAY OF CHAR);
- VAR l, L: CARDINAL;
- BEGIN
- keyTab[K].sym := sym;
- keyTab[K].ind := id;
- l := 0; L := HIGH(name);
- IdBuf[id] := CHR(L+2); INC(id);
- WHILE l <= L DO
- IdBuf[id] := name[l];
- INC(id); INC(l)
- END;
- INC(K)
- END EnterKW;
-
- BEGIN K := 0; IdBuf[0] := 1C; id := 1; id0 := 0;
- pow[0] := 1.0E1;
- pow[1] := 1.0E2;
- pow[2] := 1.0E4;
- pow[3] := 1.0E8;
- pow[4] := 1.0E16;
- pow[5] := 1.0E32;
- EnterKW(by,"BY");
- EnterKW(do,"DO");
- EnterKW(if,"IF");
- EnterKW(in,"IN");
- EnterKW(of,"OF");
- EnterKW(or,"OR");
- EnterKW(to,"TO");
- EnterKW(and,"AND");
- EnterKW(div,"DIV");
- EnterKW(end,"END");
- EnterKW(for,"FOR");
- EnterKW(mod,"MOD");
- EnterKW(not,"NOT");
- EnterKW(set,"SET");
- EnterKW(var,"VAR");
- EnterKW(case,"CASE");
- EnterKW(code,"CODE");
- EnterKW(else,"ELSE");
- EnterKW(exit,"EXIT");
- EnterKW(from,"FROM");
- EnterKW(loop,"LOOP");
- EnterKW(then,"THEN");
- EnterKW(type,"TYPE");
- EnterKW(with,"WITH");
- EnterKW(array,"ARRAY");
- EnterKW(begin,"BEGIN");
- EnterKW(const,"CONST");
- EnterKW(elsif,"ELSIF");
- EnterKW(until,"UNTIL");
- EnterKW(while,"WHILE");
- EnterKW(export,"EXPORT");
- EnterKW(import,"IMPORT");
- EnterKW(module,"MODULE");
- EnterKW(record,"RECORD");
- EnterKW(repeat,"REPEAT");
- EnterKW(return,"RETURN");
- EnterKW(forward,"FORWARD");
- EnterKW(pointer,"POINTER");
- EnterKW(procedure,"PROCEDURE");
- EnterKW(qualified,"QUALIFIED");
- EnterKW(definition,"DEFINITION");
- EnterKW(implementation,"IMPLEMENTATION");
- END M2S.
|