IMPLEMENTATION MODULE -->modulename; (* Scanner generated by Coco/R - using the FileIO library supplied with this project. *) (* allows extraction of comments *) IMPORT FileIO, Storage, SYSTEM (* TSIZE only *); CONST noSYMB = -->unknownsym; (*error token code*) (* not only for errors but also for not finished states of scanner analysis *) eof = 32C (* MS-DOS Keyboard eof char *); EOF = 0C; EOL = 15C; CR = 15C; LF = 12C; Long0 = 0; Long1 = 1; BlkSize = 16384; TYPE BufBlock = ARRAY [0 .. BlkSize-1] OF CHAR; Buffer = ARRAY [0 .. 31] OF POINTER TO BufBlock; StartTable = ARRAY [0 .. 255] OF INTEGER; GetCH = PROCEDURE (INT32): CHAR; CommentPtr = POINTER TO CommentRec; CommentRec = RECORD begCom, endCom: INT32; next: CommentPtr; END; VAR lastCh, ch: CHAR; (*current input character*) curLine: INTEGER; (*current input line (may be higher than line)*) lineStart: INT32; (*start position of current line*) apx: INT32; (*length of appendix (CONTEXT phrase)*) oldEols: INTEGER; (*number of EOLs in a comment*) bp, bp0: INT32; (*current position in buf (bp0: position of current token)*) inputLen: INT32; (*source file size*) buf: Buffer; (*source buffer for low-level access*) start: StartTable; (*start state for every character*) CurrentCh: GetCH; firstComment, lastComment: CommentPtr; PROCEDURE Err (nr, line, col: INTEGER; pos: INT32); BEGIN INC(errors) END Err; PROCEDURE NextCh; (* Return global variable ch *) BEGIN lastCh := ch; INC(bp); ch := CurrentCh(bp); IF (ch = EOL) OR (ch = LF) AND (lastCh # EOL) THEN INC(curLine); lineStart := bp END END NextCh; PROCEDURE HaveComment (): BOOLEAN; VAR level, startLine: INTEGER; oldLineStart: INT32; BEGIN level := 1; startLine := curLine; oldLineStart := lineStart; -->commentRETURN FALSE; END HaveComment; PROCEDURE Comment (): BOOLEAN; VAR SeenComment: BOOLEAN; beginC, endC: INT32; nextComment: CommentPtr; BEGIN beginC := bp; SeenComment := HaveComment(); endC := bp; DEC(endC); IF endC > beginC THEN seenComment := TRUE; Storage.ALLOCATE(nextComment, SYSTEM.TSIZE(CommentRec)); nextComment^.begCom := beginC; nextComment^.endCom := endC; nextComment^.next := NIL; IF firstComment = NIL THEN firstComment := nextComment ELSE lastComment^.next := nextComment END; lastComment := nextComment; END; RETURN SeenComment; END Comment; PROCEDURE GetComment (VAR comment: ARRAY OF CHAR; pos: CARDINAL; VAR length: CARDINAL); VAR this: CommentPtr; BEGIN length := 0; WHILE firstComment # NIL DO this := firstComment; WHILE (pos + length <= HIGH(comment)) AND (this^.begCom <= this^.endCom) DO comment[pos + length] := CharAt(this^.begCom); INC(length); INC(this^.begCom); END; firstComment := firstComment^.next; Storage.DEALLOCATE(this, SYSTEM.TSIZE(CommentRec)) END; seenComment := FALSE; END GetComment; PROCEDURE Get (VAR sym: CARDINAL); VAR state: CARDINAL; PROCEDURE Equal (s: ARRAY OF CHAR): BOOLEAN; VAR i: CARDINAL; q: INT32; BEGIN IF nextLen # LENGTH(s) THEN RETURN FALSE END; i := 1; q := bp0; INC(q); WHILE i < nextLen DO IF CurrentCh(q) # s[i] THEN RETURN FALSE END; INC(i); INC(q) END; RETURN TRUE END Equal; PROCEDURE CheckLiteral; BEGIN -->literals END CheckLiteral; BEGIN (*Get*) -->GetSy1 pos := nextPos; nextPos := bp; col := nextCol; nextCol := VAL(INTEGER, bp - lineStart); line := nextLine; nextLine := curLine; len := nextLen; nextLen := 0; apx := 0; state := start[ORD(ch)]; bp0 := bp; LOOP NextCh; INC(nextLen); CASE state OF -->GetSy2 ELSE sym := noSYMB; RETURN (*NextCh already done*) END END END Get; PROCEDURE GetString (pos: INT32; len: CARDINAL; VAR s: ARRAY OF CHAR); VAR i: CARDINAL; p: INT32; BEGIN IF len > HIGH(s) THEN len := HIGH(s) END; p := pos; i := 0; WHILE i < len DO s[i] := CharAt(p); INC(i); INC(p) END; s[len] := 0C; END GetString; PROCEDURE GetName (pos: INT32; len: CARDINAL; VAR s: ARRAY OF CHAR); VAR i: CARDINAL; p: INT32; BEGIN IF len > HIGH(s) THEN len := HIGH(s) END; p := pos; i := 0; WHILE i < len DO s[i] := CurrentCh(p); INC(i); INC(p) END; s[len] := 0C; END GetName; PROCEDURE CharAt (pos: INT32): CHAR; VAR ch: CHAR; BEGIN IF pos >= inputLen THEN RETURN EOF END; ch := buf[ORD(pos DIV BlkSize)]^[ORD(pos MOD BlkSize)]; IF ch # eof THEN RETURN ch ELSE RETURN EOF END END CharAt; PROCEDURE CapChAt (pos: INT32): CHAR; VAR ch: CHAR; BEGIN IF pos >= inputLen THEN RETURN EOF END; ch := CAP(buf[ORD(pos DIV BlkSize)]^[ORD(pos MOD BlkSize)]); IF ch # eof THEN RETURN ch ELSE RETURN EOF END END CapChAt; PROCEDURE Reset; VAR i, read: CARDINAL; BEGIN (*assert: src has been opened*) i := 0; inputLen := 0; REPEAT Storage.ALLOCATE(buf[i], BlkSize); read := BlkSize; FileIO.ReadBytes(src, buf[i]^, read); INC(i); INC(inputLen, VAL(INT32, read)) UNTIL read # BlkSize; buf[i-1]^[read] := EOF; curLine := 1; lineStart := -2; bp := -1; oldEols := 0; apx := 0; errors := 0; NextCh; END Reset; BEGIN -->initializations Error := Err; lastCh := EOF; firstComment := NIL; seenComment := FALSE; END -->modulename. -->definitionDEFINITION MODULE -->modulename; (* Scanner generated by Coco/R - using the FileIO library supplied with this project. *) IMPORT FileIO; TYPE INT32 = FileIO.INT32 (* need 32 bit integers *); VAR src, lst: FileIO.File;(*source/list files. To be opened by the main pgm*) directory: ARRAY [0 .. 255] OF CHAR (*of source file*); line, col: INTEGER; (*line and column of current symbol*) len: CARDINAL; (*length of current symbol*) pos: INT32; (*file position of current symbol*) nextLine: INTEGER; (*line of lookahead symbol*) nextCol: INTEGER; (*column of lookahead symbol*) nextLen: CARDINAL; (*length of lookahead symbol*) nextPos: INT32; (*file position of lookahead symbol*) errors: INTEGER; (*number of detected errors*) seenComment: BOOLEAN; (*TRUE if comments have been registered*) Error: PROCEDURE ((*nr*)INTEGER, (*line*)INTEGER, (*col*)INTEGER, (*pos*)INT32); PROCEDURE Get (VAR sym: CARDINAL); (* Gets next symbol from source file *) PROCEDURE GetString (pos: INT32; len: CARDINAL; VAR name: ARRAY OF CHAR); (* Retrieves exact string of max length len from position pos in source file *) PROCEDURE GetName (pos: INT32; len: CARDINAL; VAR name: ARRAY OF CHAR); (* Retrieves name of symbol of length len at position pos in source file *) PROCEDURE CharAt (pos: INT32): CHAR; (* Returns exact character at position pos in source file *) PROCEDURE GetComment (VAR comment: ARRAY OF CHAR; pos: CARDINAL; VAR length: CARDINAL); (* IF seenComment THEN concatenates and extracts previously scanned comments into comment, starting at comment[pos], and computes length; seenComment := FALSE ELSE returns length := 0 *) PROCEDURE Reset; (* Reads and stores source file internally *) END -->modulename.