home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-07-02 | 33.8 KB | 1,262 lines |
- (*************************************************************************
-
- $RCSfile: OCS.mod $
- Description: Implements the lexical scanner and error reporting
-
- Created by: fjc (Frank Copeland)
- $Revision: 5.16 $
- $Author: fjc $
- $Date: 1995/06/15 18:10:46 $
-
- Copyright © 1990-1993, ETH Zuerich
- Copyright © 1993-1995, Frank Copeland
- This module forms part of the OC program
- See OC.doc for conditions of use and distribution
-
- Log entries are at the end of the file.
-
- *************************************************************************)
-
- <* STANDARD- *> <* MAIN- *>
-
- MODULE OCS;
-
- IMPORT
- SYS := SYSTEM, Kernel, Files, Str := Strings, OCRev, s := OCStrings,
- OCM, OCOut;
-
- (* --- Exported objects ----------------------------------------------- *)
-
- (* Symbols *)
-
- CONST
- null * = 0; times * = 1; slash * = 2; div * = 3; mod * = 4;
- and * = 5; plus * = 6; minus * = 7; or * = 8; eql * = 9;
- neq * = 10; lss * = 11; leq * = 12; gtr * = 13; geq * = 14; in * = 15;
- is * = 16; arrow * = 17; period * = 18; comma * = 19; colon * = 20;
- upto * = 21; rparen * = 22; rbrak * = 23; rbrace * = 24; of * = 25;
- then * = 26; do * = 27; to * = 28; lparen * = 29; lbrak * = 30;
- lbrace * = 31; not * = 32; becomes * = 33; number * = 34; nil * = 35;
- string * = 36; ident * = 37; semicolon * = 38; bar * = 39; end * = 40;
- else * = 41; elsif * = 42; until * = 43; if * = 44; case * = 45;
- while * = 46; repeat * = 47; loop * = 48; with * = 49; exit * = 50;
- return * = 51; array * = 52; record * = 53; pointer * = 54;
- begin * = 57; const * = 58; type * = 59; var * = 60; procedure * = 61;
- import * = 62; module * = 63; eof * = 65; by * = 66; for * = 67;
- endCmd = 68; new = 69; revert = 70; stack = lss; unstack = gtr;
-
- CONST
- maxStrLen = 256;
-
- (* name, numtyp, intval, realval, lrlval are implicit results of Get () *)
-
- VAR
- numtyp * : INTEGER; (* 1 = char, 2 = integer, 3 = real, 4 = longreal *)
- intval * : LONGINT;
- realval * : REAL;
- lrlval * : LONGREAL;
- name * : ARRAY maxStrLen OF CHAR;
-
- (* Pragmas *)
-
- CONST
-
- typeChk * = 0; ovflChk * = 1; indexChk * = 2; rangeChk * = 3;
- caseChk * = 4; nilChk * = 5; returnChk * = 6; stackChk * = 7;
- longVars * = 8; clearVars * = 9; assertChk * = 10; copyArrays * = 11;
- saveRegs * = 12; saveAllRegs * = 13; entryExitCode * = 14;
- deallocPars * = 15;
-
- lastStacked = assertChk; numPragmas = 16; pragmaCode = 100;
-
- TYPE
-
- PragmaArray = ARRAY numPragmas OF BOOLEAN;
- PragmaPtr = POINTER TO PragmaRec;
- PragmaRec = RECORD
- next : PragmaPtr;
- pragma : ARRAY lastStacked + 1 OF BOOLEAN;
- END;
-
- VAR
- pragma *, defaultPragma * : PragmaArray;
- pragmaStk : PragmaPtr;
-
- (* Options *)
-
- CONST
-
- standard * = 0; initialise * = 1; main * = 2; warnings * = 3;
- register * = 4; debug = 5; smallcode = 6; smalldata = 7; resident = 8;
-
- numOptions = 9; rdOnlyOptions = debug; optionCode = 200;
-
- VAR
-
- allowOptions * : BOOLEAN;
- option *, defaultOption * : ARRAY numOptions OF BOOLEAN;
-
- (* Source control *)
-
- CONST
-
- selectorLen = 32;
-
- TYPE
-
- SelectionPtr = POINTER TO SelectionRec;
- SelectionRec = RECORD
- next : SelectionPtr;
- scan, inSelection, selected : BOOLEAN;
- END;
-
- Selector = POINTER TO SelectorRec;
- SelectorRec = RECORD
- next : Selector;
- name : ARRAY selectorLen OF CHAR;
- value : BOOLEAN;
- END;
-
- VAR
-
- scan, inSelection, selected : BOOLEAN;
- selectionStk : SelectionPtr;
- selectors, OberonA : Selector;
-
- (* Errors and warnings *)
-
- VAR
-
- scanerr *, warned * : BOOLEAN;
-
-
- (* --- Local objects ---------------------------------------------------- *)
-
- CONST
- hashSize = 43; (* size of hash table *)
- maxDig = 32;
- DigitString = "0123456789ABCDEF";
-
- TYPE
- HashTab = ARRAY hashSize OF RECORD
- symb, alt, alt2 : INTEGER;
- id : ARRAY 16 OF CHAR;
- END; (* HashTab *)
-
- VAR
- R : Files.Rider;
- W : Files.Rider;
- ch : CHAR; (* current character *)
- lastpos : LONGINT; (* error position in file *)
- i : INTEGER;
- keyTab, cmdTab : HashTab;
- errorFile : Files.File;
- Digit : ARRAY 17 OF CHAR;
- line *, col * : INTEGER;
- bumpLine : BOOLEAN;
- errorFileName : ARRAY 256 OF CHAR;
-
-
- (*------------------------------------*)
- PROCEDURE Search ( VAR hashTab : HashTab; name : ARRAY OF CHAR ) : INTEGER;
-
- VAR i, k, sym : INTEGER;
-
- <*$CopyArrays-*>
- BEGIN (* Search *)
- i := 0; k := 0; sym := -1;
-
- <*$ < OvflChk- *>
- REPEAT INC (k, ORD (name [i])); INC (i)
- UNTIL name [i] = 0X;
- k := (k + i) MOD hashSize; (* hash function *)
- <*$ > *>
-
- IF (hashTab [k].symb # 0) & (hashTab [k].id = name) THEN
- sym := hashTab [k].symb;
- ELSE
- i := k; k := hashTab [i].alt;
- IF (hashTab [k].symb # 0) & (hashTab [k].id = name) THEN
- sym := hashTab [k].symb;
- ELSE
- k := hashTab [i].alt2;
- IF (hashTab [k].symb # 0) & (hashTab [k].id = name) THEN
- sym := hashTab [k].symb;
- END
- END
- END;
- RETURN sym
- END Search;
-
- (*------------------------------------*)
- PROCEDURE WriteStr (s : ARRAY OF CHAR);
-
- <*$CopyArrays-*>
- BEGIN (* WriteStr *)
- Files.WriteBytes (W, s, SYS.STRLEN (s));
- END WriteStr;
-
- (*------------------------------------*)
- PROCEDURE WriteInt (i : LONGINT);
-
- (*------------------------------------*)
- PROCEDURE WriteDigit (i : LONGINT);
-
- BEGIN (* WriteDigit *)
- IF i > 0 THEN
- WriteDigit (i DIV 10);
- Files.Write (W, Digit [i MOD 10]);
- END; (* IF *)
- END WriteDigit;
-
- BEGIN (* WriteInt *)
- IF i = 0 THEN
- Files.Write (W, "0");
- ELSE
- IF i < 0 THEN
- Files.Write (W, "-");
- END; (* IF *)
- WriteDigit (ABS (i));
- END; (* ELSE *)
- END WriteInt;
-
- (*------------------------------------*)
- PROCEDURE WriteErr (error : BOOLEAN; n : INTEGER);
-
- VAR pos : LONGINT; string : ARRAY 256 OF CHAR;
-
- BEGIN (* WriteErr *)
- pos := Files.Pos (R);
- IF (pos > (lastpos + 10)) THEN
- IF errorFile # NIL THEN
- Files.WriteBytes (W, line, 2);
- Files.WriteBytes (W, col, 2);
- Files.WriteBytes (W, n, 2);
- ELSE
- IF error THEN OCOut.Int3 (s.OCS2, n, line, col)
- ELSE OCOut.Int3 (s.OCS3, n, line, col)
- END
- END;
- lastpos := pos
- END
- END WriteErr;
-
- (*------------------------------------*)
- PROCEDURE Mark * (n : INTEGER);
-
- BEGIN (* Mark *)
- IF scan THEN scanerr := TRUE; WriteErr (TRUE, n) END
- END Mark;
-
- (*------------------------------------*)
- PROCEDURE Warn * (n : INTEGER);
-
- BEGIN (* Warn *)
- IF scan & option [warnings] THEN warned := TRUE; WriteErr (FALSE, n) END
- END Warn;
-
- (*------------------------------------*)
- PROCEDURE GetCh ();
-
- BEGIN (* GetCh *)
- IF bumpLine THEN
- INC (line); col := 0; bumpLine := FALSE;
- IF OCM.Verbose & ((line MOD 10) = 0) THEN
- OCOut.Int (line); OCOut.Char (0DX)
- END
- END;
-
- Files.Read (R, ch);
-
- IF ch = 0AX THEN bumpLine := TRUE
- ELSIF ch = 09X THEN INC (col, 8)
- ELSE INC (col)
- END
- END GetCh;
-
- (*------------------------------------*)
- PROCEDURE Hval (ch : CHAR) : INTEGER;
-
- VAR d : INTEGER;
-
- BEGIN (* Hval *)
- d := ORD (ch) - 30H; (* d >= 0 *)
- IF d >= 10 THEN
- IF (d >= 17) & (d < 23) THEN DEC (d, 7);
- ELSE d := 0; Mark (2)
- END
- END;
- RETURN d
- END Hval;
-
- (*------------------------------------*)
- PROCEDURE String (VAR sym : INTEGER; startCh : CHAR);
-
- VAR i, j, val : INTEGER;
-
- BEGIN (* String *)
- i := 0;
- LOOP
- GetCh ();
- IF ch = startCh THEN EXIT
- ELSIF ch < " " THEN Mark (3); EXIT
- END;
-
- IF ~option [standard] THEN (* process escaped chars in string or char *)
- IF ch = 5CX THEN
- GetCh (); IF ch < " " THEN Mark (3); EXIT END;
- CASE ch OF
- "b" : ch := 08X | (* BS *)
- "e" : ch := 1BX | (* ESC *)
- "f" : ch := 0CX | (* FF *)
- "n" : ch := 0AX | (* LF *)
- "0", "o" : ch := 00X | (* NUL*)
- "r" : ch := 0DX | (* CR *)
- "t" : ch := 09X | (* HT *)
- "v" : ch := 0BX | (* VT *)
- "x" : (* hexadecimal value *)
- GetCh (); IF ch < " " THEN Mark (3); EXIT END;
- val := Hval (ch) * 16;
- GetCh (); IF ch < " " THEN Mark (3); EXIT END;
- val := val + Hval (ch);
- ch := CHR (val);
- |
- ELSE (* insert following character = do nothing *)
- END;
- END;
- END; (* IF *)
-
- IF i < maxStrLen - 1 THEN
- name [i] := ch;
- INC (i)
- ELSE
- Mark (212); i := 0
- END;
- END; (* LOOP *)
- GetCh ();
- sym := string;
- name [i] := 0X;
- intval := i
- END String;
-
- (*------------------------------------*)
- PROCEDURE Identifier (VAR sym : INTEGER);
-
- VAR i : INTEGER; underscore : BOOLEAN;
-
- BEGIN (* Identifier *)
- underscore := FALSE; i := 0;
- REPEAT
- underscore := underscore OR (ch = "_");
- IF i < (maxStrLen - 1) THEN name [i] := ch; INC (i) END;
- GetCh ();
- UNTIL
- (ch < "0") OR (ch > "9")
- & (CAP (ch) < "A") OR (CAP (ch) > "Z")
- & (ch # "_");
-
- IF underscore & option [standard] THEN Mark (924) END;
-
- name [i] := 0X;
- sym := Search (keyTab, name);
- IF sym < 0 THEN sym := ident END
- END Identifier;
-
- (*------------------------------------*)
- PROCEDURE TenL (e : INTEGER) : LONGREAL;
-
- VAR result : LONGREAL;
-
- BEGIN (* TenL *)
- result := 1;
- WHILE e > 0 DO result := result * 10; DEC (e) END;
- RETURN result
- END TenL;
-
- (*------------------------------------*)
- PROCEDURE Ten (e : INTEGER) : REAL;
-
- VAR result : REAL;
-
- BEGIN (* Ten *)
- result := 1;
- WHILE e > 0 DO result := result * 10; DEC (e) END;
- RETURN result
- END Ten;
-
- (*------------------------------------*)
- PROCEDURE Number;
-
- CONST MaxExp = 38; MaxLExp = 38;
-
- VAR
- i, j, h, d, e, n : INTEGER;
- x, f : REAL;
- y, g : LONGREAL;
- lastCh : CHAR;
- neg : BOOLEAN;
- dig : ARRAY maxDig OF CHAR;
-
- (*------------------------------------*)
- PROCEDURE ReadScaleFactor ();
-
- BEGIN (* ReadScaleFactor *)
- GetCh ();
- IF ch = "-" THEN neg := TRUE; GetCh ()
- ELSE neg := FALSE; IF ch = "+" THEN GetCh () END
- END;
- IF ("0" <= ch) & (ch <= "9") THEN
- REPEAT e := e * 10 + ORD (ch) - 30H; GetCh ()
- UNTIL (ch < "0") OR ("9" < ch);
- ELSE Mark (2);
- END
- END ReadScaleFactor;
-
- BEGIN (* 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 - 1) & (dig [j] = "0") DO INC (j) END;
- IF ch = "." THEN
- GetCh ();
- IF ch = "." THEN lastCh := 0X; ch := 7FX; END;
- END; (* IF *)
- IF lastCh = "." THEN (* decimal point *)
- h := i;
- WHILE ("0" <= ch) & (ch <= "9") DO (* read fraction *)
- IF i < maxDig THEN dig [i] := ch; INC (i) END;
- GetCh ();
- END; (* WHILE *)
- IF ch = "D" THEN (* LONGREAL *)
- y := 0; g := 1; e := 0;
- WHILE j < h DO y := y * 10 + (ORD (dig [j]) - 30H); INC (j) END;
- WHILE j < i DO
- g := g / 10; y := (ORD (dig [j]) - 30H) * g + y; INC (j)
- END;
- ReadScaleFactor ();
- IF neg THEN
- IF e <= MaxLExp THEN y := y / TenL (e) ELSE y := 0 END;
- ELSIF e > 0 THEN
- IF e <= MaxLExp THEN y := TenL (e) * y
- ELSE y := 0; Mark (203)
- END
- END; (* ELSE *)
- numtyp := 4; lrlval := y;
- ELSE
- x := 0; f := 1; e := 0;
- WHILE j < h DO x := x * 10 + (ORD (dig [j]) - 30H); INC (j) END;
- WHILE j < i DO
- f := f / 10; x := (ORD (dig [j]) - 30H) * f + x; INC (j)
- END;
- IF ch = "E" THEN ReadScaleFactor() END;
- IF neg THEN
- IF e <= MaxExp THEN x := x / Ten (e) ELSE x := 0 END;
- ELSE
- IF e <= MaxExp THEN x := Ten (e) * x
- ELSE x := 0; Mark (203)
- END;
- END; (* ELSE *)
- numtyp := 3; realval := x;
- END; (* ELSE *)
- ELSE (* Integer *)
- lastCh := dig [i - 1]; intval := 0;
- IF lastCh = "H" THEN (* hex number *)
- IF j < (i - 1) THEN
- DEC (i); intval := Hval (dig [j]); INC (j);
- IF i - j <= 7 THEN
- IF (i - j = 7) & (intval >= 8) THEN DEC (intval, 16) END;
- WHILE j < i DO
- intval := Hval (dig [j]) + intval * 10H; INC (j)
- END;
- ELSE
- Mark (203)
- END; (* ELSE *)
- END; (* IF *)
- ELSIF lastCh = "X" THEN (* character code in hex *)
- DEC (i);
- WHILE j < i DO
- intval := Hval (dig [j]) + intval * 10H; INC (j);
- IF intval > OCM.MaxChar THEN Mark (203); intval := 0 END;
- END; (* WHILE *)
- ELSE (* decimal *)
- WHILE j < i DO
- d := ORD (dig [j]) - 30H;
- IF d < 10 THEN
- IF intval <= (MAX (LONGINT) - d) DIV 10 THEN
- intval := intval * 10 + d;
- ELSE
- Mark (203); intval := 0;
- END;
- ELSE
- Mark (2); intval := 0;
- END; (* ELSE *)
- INC (j);
- END; (* WHILE *)
- END; (* ELSE *)
- IF lastCh = "X" THEN numtyp := 1 ELSE numtyp := 2 END;
- END; (* ELSE *)
- END Number;
-
- (*------------------------------------*)
- PROCEDURE SkipWhitespace ();
- BEGIN (* SkipWhitespace *)
- LOOP (* ignore control characters (and spaces) *)
- IF ch <= " " THEN IF ch = 0X THEN ch := " "; EXIT ELSE GetCh () END
- ELSIF ch > 7FX THEN GetCh ();
- ELSE EXIT
- END
- END;
- END SkipWhitespace;
-
- (*------------------------------------*)
- PROCEDURE InlineCommand ();
-
- VAR sym, cline, ccol : INTEGER;
-
- (*------------------------------------*)
- PROCEDURE GetSym ();
-
- VAR s : INTEGER;
-
- (*------------------------------------*)
- PROCEDURE Identifier;
-
- VAR i : INTEGER;
-
- BEGIN (* Identifier *)
- i := 0;
- REPEAT
- IF i < (maxStrLen - 1) THEN name [i] := ch; INC (i) END;
- GetCh ();
- UNTIL (ch < "0") OR (ch > "9") & (CAP (ch) < "A") OR (CAP (ch) > "Z");
-
- name [i] := 0X;
- s := Search (cmdTab, name);
- IF s < 0 THEN s := ident END
- END Identifier;
-
- BEGIN (* GetSym *)
- SkipWhitespace ();
- CASE ch OF (* " " <= ch <= 7FX *)
- " " : s := eof
- |
- "A" .. "Z", "a" .. "z", "_" : Identifier ()
- |
- "+" : s := plus; GetCh ()
- |
- "-" : s := minus; GetCh ()
- |
- "&" : s := and; GetCh ()
- |
- "(" : s := lparen; GetCh ()
- |
- ")" : s := rparen; GetCh ()
- |
- "<" : s := stack; GetCh ()
- |
- ">" : s := unstack; GetCh ()
- |
- "!" : s := revert; GetCh ()
- |
- "*" :
- GetCh ();
- IF ch = ">" THEN GetCh (); s := endCmd ELSE s := null END
- |
- "~" : s := not; GetCh ()
- |
- ELSE s := null; GetCh ()
- END; (* CASE ch *)
- sym := s;
- END GetSym;
-
- (*------------------------------------*)
- PROCEDURE Pragma ();
-
- VAR i : INTEGER;
-
- (*------------------------------------*)
- PROCEDURE StackPragmas ();
-
- VAR p : PragmaPtr; i : INTEGER;
-
- BEGIN (* StackPragmas *)
- IF scan THEN
- NEW (p);
- p.next := pragmaStk; pragmaStk := p;
- FOR i := 0 TO lastStacked DO
- p.pragma [i] := pragma [i]
- END
- END
- END StackPragmas;
-
- (*------------------------------------*)
- PROCEDURE UnstackPragmas ();
-
- VAR i : INTEGER;
-
- BEGIN (* UnstackPragmas *)
- IF scan THEN
- IF pragmaStk # NIL THEN
- FOR i := 0 TO lastStacked DO
- pragma [i] := pragmaStk.pragma [i]
- END;
- pragmaStk := pragmaStk.next
- ELSE Mark (349)
- END
- END
- END UnstackPragmas;
-
- BEGIN (* Pragma *)
- LOOP
- GetSym ();
- CASE sym OF
- pragmaCode .. (pragmaCode + numPragmas - 1) :
- i := sym - pragmaCode; GetSym();
- IF sym = plus THEN IF scan THEN pragma [i] := TRUE END
- ELSIF sym = minus THEN IF scan THEN pragma [i] := FALSE END
- ELSE Mark (348); EXIT
- END;
- |
- optionCode .. (optionCode + numOptions - 1) :
- Warn (351); GetSym();
- IF (sym # plus) & (sym # minus) THEN Mark (348); EXIT END
- |
- ident : Warn (0); EXIT
- |
- stack : StackPragmas ()
- |
- unstack : UnstackPragmas ()
- |
- revert : IF scan THEN pragma := defaultPragma END
- |
- endCmd : EXIT
- |
- ELSE Mark (359); EXIT
- END
- END;
- END Pragma;
-
- (*------------------------------------*)
- PROCEDURE Control ();
-
- VAR i : INTEGER; x : BOOLEAN; sel : Selector;
-
- (*------------------------------------*)
- PROCEDURE Lookup () : Selector;
- VAR sel : Selector;
- BEGIN (* Lookup *)
- sel := selectors;
- WHILE (sel # NIL) & (sel.name # name) DO sel := sel.next END;
- RETURN sel
- END Lookup;
-
- (*------------------------------------*)
- PROCEDURE Expression () : BOOLEAN;
-
- VAR e, rhs : BOOLEAN;
-
- (*------------------------------------*)
- PROCEDURE Factor () : BOOLEAN;
-
- VAR f : BOOLEAN; sel : Selector;
-
- BEGIN (* Factor *)
- IF sym < lparen THEN
- Mark (13);
- REPEAT GetSym() UNTIL sym >= lparen
- END;
- IF (sym >= optionCode) & (sym < optionCode + numOptions) THEN
- f := option [sym - optionCode]; GetSym()
- ELSIF (sym >= pragmaCode) & (sym < pragmaCode + numPragmas) THEN
- Warn (351); GetSym(); f := FALSE
- ELSIF sym = ident THEN
- sel := Lookup();
- IF sel # NIL THEN f := sel.value
- ELSE Warn (0); f := FALSE
- END;
- GetSym()
- ELSIF sym = lparen THEN
- GetSym(); f := Expression();
- IF sym = rparen THEN GetSym() ELSE Mark (rparen) END;
- ELSIF sym = not THEN
- GetSym(); f := ~Factor()
- ELSE
- Mark (13); GetSym(); f := FALSE
- END;
- RETURN f
- END Factor;
-
- (*------------------------------------*)
- PROCEDURE Term () : BOOLEAN;
-
- VAR t, rhs : BOOLEAN;
-
- BEGIN (* Term *)
- t := Factor ();
- WHILE sym = and DO GetSym(); rhs := Factor(); t := t & rhs END;
- RETURN t
- END Term;
-
- BEGIN (* Expression *)
- e := Term ();
- WHILE sym = or DO GetSym(); rhs := Term(); e := e OR rhs END;
- RETURN e
- END Expression;
-
- (*------------------------------------*)
- PROCEDURE StackSelection ();
- VAR s : SelectionPtr;
- BEGIN (* StackSelection *)
- NEW (s); s.next := selectionStk; selectionStk := s;
- s.scan := scan; s.inSelection := inSelection;
- s.selected := selected;
- scan := FALSE; selected := FALSE; inSelection := TRUE
- END StackSelection;
-
- (*------------------------------------*)
- PROCEDURE UnstackSelection ();
- BEGIN (* UnstackSelection *)
- scan := selectionStk.scan; inSelection := selectionStk.inSelection;
- selected := selectionStk.selected; selectionStk := selectionStk.next
- END UnstackSelection;
-
- BEGIN (* Control *)
- GetSym ();
- CASE sym OF
- optionCode .. (optionCode + numOptions - 1) :
- IF ~allowOptions THEN Mark (357) END;
- i := sym - optionCode; GetSym();
- IF sym = plus THEN
- IF i < rdOnlyOptions THEN IF scan THEN option [i] := TRUE END
- ELSE Warn (325)
- END;
- GetSym()
- ELSIF sym = minus THEN
- IF i < rdOnlyOptions THEN IF scan THEN option [i] := FALSE END
- ELSE Warn (325)
- END;
- GetSym()
- ELSE Mark (348)
- END
- |
- pragmaCode .. (pragmaCode + numPragmas - 1) :
- Warn (351); GetSym();
- IF (sym = plus) OR (sym = minus) THEN GetSym() END
- |
- ident :
- sel := Lookup();
- IF sel # NIL THEN
- GetSym();
- IF sym = plus THEN
- IF scan THEN sel.value := TRUE END; GetSym()
- ELSIF sym = minus THEN
- IF scan THEN sel.value := FALSE END; GetSym()
- ELSE Mark (348)
- END
- ELSE
- Warn (0); GetSym();
- IF (sym = plus) OR (sym = minus) THEN GetSym() END
- END
- |
- if :
- StackSelection ();
- GetSym(); x := Expression ();
- scan := selectionStk.scan & x; selected := x;
- IF sym = then THEN GetSym() ELSE Mark (then) END;
- |
- elsif :
- IF ~inSelection THEN Mark (350); StackSelection () END;
- GetSym(); x := Expression ();
- scan := x & ~selected & selectionStk.scan;
- selected := selected OR x;
- IF sym = then THEN GetSym() ELSE Mark (then) END;
- |
- else :
- IF ~inSelection THEN Mark (350); StackSelection () END;
- scan := selectionStk.scan & ~selected; selected := scan;
- GetSym()
- |
- end :
- IF selectionStk = NIL THEN Mark (350)
- ELSE UnstackSelection ()
- END;
- GetSym()
- |
- new :
- GetSym();
- IF sym = ident THEN
- IF Lookup() = NIL THEN
- IF scan THEN
- NEW (sel); sel.next := selectors; selectors := sel;
- COPY (name, sel.name); sel.value := FALSE
- END
- ELSE Warn (1)
- END;
- GetSym()
- ELSIF sym >= pragmaCode THEN Warn (1)
- END
- |
- endCmd : (* Do nothing *)
- |
- ELSE Mark (359)
- END
- END Control;
-
- BEGIN (* InlineCommand *)
- (* ch = "*" *)
- cline := line; ccol := col - 1; (* Remember start of comment *)
- GetCh ();
- IF ch = "$" THEN GetCh(); Pragma ()
- ELSE
- SkipWhitespace();
- IF ch = "$" THEN Mark (358); GetCh(); Pragma ()
- ELSE Control ()
- END
- END;
- IF (sym # endCmd) & (sym # eof) THEN
- Mark (347); WHILE (sym # eof) & (sym # endCmd) DO GetSym() END
- END;
- IF sym = eof THEN line := cline; col := ccol; Mark (5) END
- END InlineCommand;
-
- (*------------------------------------*)
- PROCEDURE Get * (VAR sym : INTEGER);
-
- VAR
- s : INTEGER;
-
- (*------------------------------------*)
- PROCEDURE Comment (); (* do not read after end of file *)
-
- VAR swCh : CHAR; sw : BOOLEAN; cline, ccol : INTEGER;
-
- BEGIN (* Comment *)
- cline := line; ccol := col - 1; (* Remember start of comment *)
- GetCh ();
- LOOP
- LOOP
- WHILE ch = "(" DO
- GetCh ();
- IF ch = "*" THEN Comment () END
- END;
- WHILE ch = "<" DO
- GetCh ();
- IF ch = "*" THEN InlineCommand () END
- END;
- IF ch = "*" THEN GetCh (); EXIT END;
- IF ch = 0X THEN EXIT END;
- GetCh ()
- END;
- IF ch = ")" THEN GetCh (); EXIT END;
- IF ch = 0X THEN line := cline; col := ccol; Mark (5); EXIT END
- END
- END Comment;
-
- BEGIN (* Get *)
- REPEAT
- SkipWhitespace ();
- CASE ch OF (* " " <= ch <= 7FX *)
- " " : s := eof; ch := 0X;
- |
- 5CX, "!", "$", "%", "?", "@", "`" : s := null; GetCh ();
- |
- 22X, "'" : String (s, ch);
- |
- "#" : s := neq; GetCh ();
- |
- "&" : s := and; GetCh ();
- |
- "(" :
- GetCh ();
- IF ch = "*" THEN Comment (); Get (s) ELSE s := lparen; END;
- |
- ")" : s := rparen; GetCh ();
- |
- "*" : s := times; GetCh ();
- |
- "+" : s := plus; GetCh ();
- |
- "," : s := comma; GetCh ();
- |
- "-" : s := minus; GetCh ();
- |
- "." :
- GetCh ();
- IF ch = "." THEN GetCh (); s := upto; ELSE s := period; END;
- |
- "/" : s := slash; GetCh ();
- |
- "0" .. "9" : Number (); s := number;
- |
- ":" :
- GetCh ();
- IF ch = "=" THEN GetCh (); s := becomes ELSE s := colon END;
- |
- ";" : s := semicolon; GetCh ();
- |
- "<" :
- GetCh ();
- IF ch = "=" THEN GetCh (); s := leq
- ELSIF ch = "*" THEN InlineCommand (); Get (s)
- ELSE s := lss
- END;
- |
- "=" : s := eql; GetCh ();
- |
- ">" :
- GetCh ();
- IF ch = "=" THEN GetCh (); s := geq; ELSE s := gtr; END;
- |
- "A" .. "Z", "a" .. "z", "_" : Identifier (s);
- |
- |
- "[" : s := lbrak; GetCh ();
- |
- "]" : s := rbrak; GetCh ();
- |
- "^" : s := arrow; GetCh ();
- |
- "{" : s := lbrace; GetCh ();
- |
- "}" : s := rbrace; GetCh ();
- |
- "|" : s := bar; GetCh ();
- |
- "~" : s := not; GetCh ();
- |
- 7FX : s := upto; GetCh ();
- |
- ELSE
- Mark (1001); Mark (ORD (ch)); s := null
- END; (* CASE ch *)
- UNTIL scan OR (s = eof);
- sym := s;
- END Get;
-
- (*------------------------------------*)
- PROCEDURE New ( name : ARRAY OF CHAR ) : Selector;
-
- VAR sel : Selector;
-
- <*$ CopyArrays- *>
- BEGIN (* New *)
- NEW (sel); sel.next := OberonA.next; OberonA.next := sel;
- COPY (name, sel.name); sel.value := FALSE;
- RETURN sel
- END New;
-
- (*------------------------------------*)
- PROCEDURE Set* ( name : ARRAY OF CHAR );
-
- VAR sel : Selector; sym : INTEGER;
-
- <*$ CopyArrays- *>
- BEGIN (* Set *)
- sym := Search (cmdTab, name);
- IF sym < 0 THEN
- sel := OberonA;
- WHILE (sel # NIL) & (sel.name # name) DO sel := sel.next END;
- IF sel = NIL THEN sel := New (name) END;
- sel.value := TRUE
- ELSE
- OCOut.Str1 (s.OCS6, name);
- HALT (5)
- END
- END Set;
-
- (*------------------------------------*)
- PROCEDURE Clear* ( name : ARRAY OF CHAR );
-
- VAR sel : Selector; sym : INTEGER;
-
- <*$ CopyArrays- *>
- BEGIN (* Clear *)
- sym := Search (cmdTab, name);
- IF sym < 0 THEN
- sel := OberonA;
- WHILE (sel # NIL) & (sel.name # name) DO sel := sel.next END;
- IF sel = NIL THEN sel := New (name) END;
- sel.value := FALSE
- ELSE
- OCOut.Str1 (s.OCS7, name);
- HALT (5)
- END
- END Clear;
-
- (*------------------------------------*)
- PROCEDURE Init * (source : Files.File);
-
- BEGIN (* Init *)
- ch := " "; scanerr := FALSE; warned := FALSE; lastpos := -1;
- Files.Set (R, source, 0);
- line := 1; col := 0; bumpLine := FALSE;
-
- defaultOption [standard] := OCM.Standard;
- defaultOption [initialise] := OCM.Initialise;
- defaultOption [main] := OCM.Main;
- defaultOption [warnings] := OCM.Warnings;
- defaultOption [debug] := OCM.Debug;
- defaultOption [smallcode] := OCM.SmallCode;
- defaultOption [smalldata] := OCM.SmallData;
- defaultOption [register] := OCM.Register;
- defaultOption [resident] := OCM.Resident;
-
- defaultPragma [typeChk] := OCM.TypeChk;
- defaultPragma [ovflChk] := OCM.OvflChk;
- defaultPragma [indexChk] := OCM.IndexChk;
- defaultPragma [rangeChk] := OCM.RangeChk;
- defaultPragma [caseChk] := OCM.CaseChk;
- defaultPragma [nilChk] := OCM.NilChk;
- defaultPragma [returnChk] := OCM.ReturnChk;
- defaultPragma [stackChk] := OCM.StackChk;
- defaultPragma [longVars] := OCM.LongVars;
- defaultPragma [clearVars] := OCM.ClearVars;
- defaultPragma [assertChk] := OCM.AssertChk;
- defaultPragma [copyArrays] := TRUE;
- defaultPragma [saveRegs] := FALSE;
- defaultPragma [saveAllRegs] := FALSE;
- defaultPragma [entryExitCode] := TRUE;
- defaultPragma [deallocPars] := TRUE;
-
- pragma := defaultPragma;
- option := defaultOption; allowOptions := TRUE;
- scan := TRUE; inSelection := FALSE; selected := FALSE;
- END Init;
-
- (*------------------------------------*)
- PROCEDURE StartModule * (name : ARRAY OF CHAR);
-
- VAR
- res : INTEGER; tag : ARRAY 5 OF CHAR;
- errorFileIcon : ARRAY 256 OF CHAR;
-
- <*$CopyArrays-*>
- BEGIN (* StartModule *)
- OCM.ErrorFileName (name, errorFileName);
- Files.Delete (errorFileName, res);
- COPY (errorFileName, errorFileIcon); Str.Append (".info", errorFileIcon);
- Files.Delete (errorFileIcon, res);
- errorFile := Files.New (errorFileName);
- IF errorFile = NIL THEN
- OCOut.Str1 (s.OCS8, errorFileName);
- HALT (20)
- END;
- Files.Set (W, errorFile, 0);
- (* Output error file tag 'OAER' *)
- tag := "OAER"; Files.WriteBytes (W, tag, 4)
- END StartModule;
-
- (*------------------------------------*)
- PROCEDURE ResetProcSwitches * ();
-
- BEGIN (* ResetProcSwitches *)
- pragma [copyArrays] := TRUE; pragma [saveRegs] := FALSE;
- pragma [saveAllRegs] := FALSE; pragma [entryExitCode] := TRUE;
- pragma [deallocPars] := TRUE;
- END ResetProcSwitches;
-
- (*------------------------------------*)
- PROCEDURE EndModule * ();
-
- BEGIN (* EndModule *)
- Files.Set (R, NIL, 0); Files.Set (W, NIL, 0);
- IF scanerr THEN
- OCOut.Str1 (s.OCS11, errorFileName);
- Files.Register (errorFile);
- OCM.MakeIcon (errorFileName, OCM.iconErr)
- ELSIF warned THEN
- OCOut.Str1 (s.OCS12, errorFileName);
- Files.Register (errorFile);
- OCM.MakeIcon (errorFileName, OCM.iconErr)
- ELSE Files.Purge (errorFile)
- END;
- errorFile := NIL; errorFileName := "";
-
- pragmaStk := NIL; selectionStk := NIL; selectors := OberonA
- END EndModule;
-
- (*------------------------------------*)
- PROCEDURE Enter
- ( VAR hashTab : HashTab;
- sym : INTEGER;
- name : ARRAY OF CHAR );
-
- VAR j, k : INTEGER;
-
- <*$CopyArrays-*>
- BEGIN (* Enter *)
- j := 0; k := 0;
-
- <*$ < OvflChk- *>
- REPEAT INC (k, ORD (name [j])); INC (j)
- UNTIL name [j] = 0X;
- k := (k + j) MOD hashSize; (* hash function *)
- <*$ > *>
-
- IF hashTab [k].symb # 0 THEN
- j := k; k := -1;
- REPEAT INC (k) UNTIL hashTab [k].symb = 0;
- IF hashTab [j].alt = 0 THEN
- hashTab [j].alt := k
- ELSIF hashTab [j].alt2 = 0 THEN
- hashTab [j].alt2 := k
- ELSE
- OCOut.Str0 (s.OCS13);
- HALT (20)
- END
- END;
-
- hashTab [k].symb := sym; COPY (name, hashTab [k].id)
- END Enter;
-
- (*------------------------------------*)
- PROCEDURE* CloseErrorFile (VAR rc : LONGINT);
-
- BEGIN (* CloseErrorFile *)
- IF errorFile # NIL THEN
- Files.Set (W, NIL, 0); Files.Purge (errorFile); errorFile := NIL
- END;
- END CloseErrorFile;
-
- BEGIN (* OCS *)
- Digit := DigitString; errorFile := NIL; errorFileName := "";
- Kernel.SetCleanup (CloseErrorFile);
-
- FOR i := 0 TO hashSize - 1 DO
- keyTab [i].symb := 0; keyTab [i].alt := 0; keyTab [i].alt2 := 0;
- cmdTab [i].symb := 0; cmdTab [i].alt := 0; cmdTab [i].alt2 := 0
- END;
-
- Enter (keyTab, do, "DO"); Enter (keyTab, if, "IF");
- Enter (keyTab, in, "IN"); Enter (keyTab, is, "IS");
- Enter (keyTab, of, "OF"); Enter (keyTab, or, "OR");
- Enter (keyTab, end, "END"); Enter (keyTab, mod, "MOD");
- Enter (keyTab, nil, "NIL"); Enter (keyTab, var, "VAR");
- Enter (keyTab, else, "ELSE"); Enter (keyTab, exit, "EXIT");
- Enter (keyTab, then, "THEN"); Enter (keyTab, with, "WITH");
- Enter (keyTab, array, "ARRAY"); Enter (keyTab, begin, "BEGIN");
- Enter (keyTab, const, "CONST"); Enter (keyTab, elsif, "ELSIF");
- Enter (keyTab, until, "UNTIL"); Enter (keyTab, while, "WHILE");
- Enter (keyTab, record, "RECORD"); Enter (keyTab, repeat, "REPEAT");
- Enter (keyTab, return, "RETURN"); Enter (keyTab, procedure, "PROCEDURE");
- Enter (keyTab, to, "TO"); Enter (keyTab, div, "DIV");
- Enter (keyTab, loop, "LOOP"); Enter (keyTab, type, "TYPE");
- Enter (keyTab, import, "IMPORT"); Enter (keyTab, module, "MODULE");
- Enter (keyTab, pointer, "POINTER"); Enter (keyTab, case, "CASE");
- Enter (keyTab, by, "BY"); Enter (keyTab, for, "FOR");
-
- Enter (cmdTab, if, "IF");
- Enter (cmdTab, then, "THEN");
- Enter (cmdTab, elsif, "ELSIF");
- Enter (cmdTab, else, "ELSE");
- Enter (cmdTab, end, "END");
- Enter (cmdTab, new, "NEW");
- Enter (cmdTab, or, "OR");
- Enter (cmdTab, pragmaCode + copyArrays, "CopyArrays");
- Enter (cmdTab, pragmaCode + typeChk, "TypeChk");
- Enter (cmdTab, pragmaCode + ovflChk, "OvflChk");
- Enter (cmdTab, pragmaCode + indexChk, "IndexChk");
- Enter (cmdTab, pragmaCode + rangeChk, "RangeChk");
- Enter (cmdTab, pragmaCode + caseChk, "CaseChk");
- Enter (cmdTab, pragmaCode + nilChk, "NilChk");
- Enter (cmdTab, pragmaCode + returnChk, "ReturnChk");
- Enter (cmdTab, pragmaCode + stackChk, "StackChk");
- Enter (cmdTab, pragmaCode + longVars, "LongVars");
- Enter (cmdTab, pragmaCode + clearVars, "ClearVars");
- Enter (cmdTab, pragmaCode + saveRegs, "SaveRegs");
- Enter (cmdTab, pragmaCode + saveAllRegs, "SaveAllRegs");
- Enter (cmdTab, pragmaCode + entryExitCode, "EntryExitCode");
- Enter (cmdTab, pragmaCode + deallocPars, "DeallocPars");
- Enter (cmdTab, pragmaCode + assertChk, "AssertChk");
- Enter (cmdTab, optionCode + standard, "STANDARD");
- Enter (cmdTab, optionCode + initialise, "INITIALISE");
- Enter (cmdTab, optionCode + main, "MAIN");
- Enter (cmdTab, optionCode + warnings, "WARNINGS");
- Enter (cmdTab, optionCode + debug, "DEBUG");
- Enter (cmdTab, optionCode + smallcode, "SMALLCODE");
- Enter (cmdTab, optionCode + smalldata, "SMALLDATA");
- Enter (cmdTab, optionCode + register, "REGISTER");
- Enter (cmdTab, optionCode + resident, "RESIDENT");
-
- pragmaStk := NIL;
- NEW (OberonA);
- OberonA.next := NIL; OberonA.name := "OberonA"; OberonA.value := TRUE;
- selectionStk := NIL; selectors := OberonA;
-
- END OCS.
-
- (***************************************************************************
-
- $Log: OCS.mod $
- Revision 5.16 1995/06/15 18:10:46 fjc
- - Added RESIDENT to inline command identifier table.
-
- Revision 5.15 1995/06/02 18:32:25 fjc
- - Added AssertChk macro.
- - defaultOption and defaultPragma are now initialised from
- the settings exported by OCM.
- - Fixed some problems with parsing inline commands.
- - Removed option to generate text error files.
-
- Revision 5.15 1995/05/29 21:15:49 fjc
- - Added AssertChk pragma.
- - Minor fixes in parsing of inline commands and pragmas.
-
- Revision 5.14 1995/05/19 16:00:11 fjc
- - Uses OCOut for console IO.
-
- Revision 5.13 1995/03/23 17:58:17 fjc
- - Fixed pragma.
-
- Revision 5.12 1995/02/27 16:50:50 fjc
- - Removed trace code.
- - Implemented DEBUG, SMALLCODE, SMALLDATA and REGISTER as
- read-only options.
-
- Revision 5.11 1995/01/26 00:17:17 fjc
- - Release 1.5
-
- Revision 5.10 1995/01/09 13:47:10 fjc
- - Added calls to OCM.MakeIcon.
- - Changed output depending on OCM.Verbose.
-
- Revision 5.9 1995/01/03 21:04:01 fjc
- - Changed OCG to OCM.
- - Changed to use catalogs:
- - Uses OCM for console I/O instead of Out.
- - Gets text from OCStrings instead of hard-coding it.
-
- Revision 5.8 1994/12/16 17:01:51 fjc
- - Changed Identifier() to allow underscores.
- - Uses procedures in OCG to construct error file names.
-
- Revision 5.7 1994/11/13 11:15:29 fjc
- - Consolidated writing to the error file in WriteErr().
-
- Revision 5.6 1994/10/23 15:31:37 fjc
- - Replaced StdIO with Out for console IO.
- - Implemented 'DeallocPars' pragma.
- - Scan() now allows for IEEE REALs.
-
- Revision 5.5 1994/09/25 17:33:31 fjc
- - Deleted CPOINTER, BPOINTER and LIBCALL keywords.
- - Uncommented trace code in Mark() and Warn().
-
- Revision 5.4 1994/09/16 17:31:03 fjc
- - Implemented source control.
- - Added Warn(), Set() and Clear().
-
- Revision 5.3 1994/09/15 10:12:46 fjc
- - Replaced switches with pragmas.
- - Used Kernel instead of SYSTEM.
-
- Revision 5.2 1994/09/08 10:43:54 fjc
- - Actually got pragmas and options to work.
-
- Revision 5.1 1994/09/03 20:20:12 fjc
- - Bumped version number
-
- ***************************************************************************)
-