home *** CD-ROM | disk | FTP | other *** search
- %{
- (* CREF.L: simple Turbo Pascal cross reference utility
- USAGE: cref <input-file >output-file
- DESCRIPTION: Produces a cross reference listing from the input-file
- (.pas suffix must be specified), written to the output-file (if source
- and target file redirection is ommitted, input comes from stdin, and
- output goes to stdout)
- EXAMPLE: cref <myprog.pas >prn *)
-
- program cref;
- uses LexLib;
- type Ident = string[80];
- function upper(id : Ident) : Ident; forward;
- (* converts id to uppercase *)
- function is_keyword(id : Ident) : boolean; forward;
- (* checks whether id is a Turbo Pascal keyword *)
- procedure enter(id : Ident; lineno : integer); forward;
- (* enter id and lineno into binary tree, sorted in lexical order of
- identifiers *)
- procedure print; forward;
- (* prints out the binary tree in inorder *)
- %}
-
- %start code str comment1 comment2
-
- letter [A-Za-z_]
- digit [0-9]
-
- %%
-
- { print line numbers: }
-
- \n begin
- echo;
- write(yyout, yylineno:4, ': ')
- end;
-
- { echo keywords and enter identifier occurrences into binary tree
- (converted to uppercase): }
-
- <code>{letter}({letter}|{digit})*
- begin
- echo;
- if not is_keyword(yytext) then
- enter(upper(yytext), yylineno)
- end;
-
- { rules to handle strings, comments, and hexadecimals: }
-
- <code>' begin echo; begin_(str) end;
- <str>'' echo;
- <str>' begin echo; begin_(code) end;
- <code>"(*" begin echo; begin_(comment1) end;
- <code>"{" begin echo; begin_(comment2) end;
- <comment1>"*)" begin echo; begin_(code) end;
- <comment2>"}" begin echo; begin_(code) end;
- <code>"$"({digit}|[A-Fa-f])+ echo;
-
- %%
-
- function upper(id : Ident) : Ident;
- var i : integer;
- begin
- for i := 1 to length(id) do
- id[i] := upCase(id[i]);
- upper := id
- end(*upper*);
- function is_keyword(id : Ident) : boolean;
- (* table of Turbo Pascal keywords: *)
- const
- no_of_keywords = 48;
- keyword : array [1..no_of_keywords] of Ident = (
- 'ABSOLUTE', 'AND', 'ARRAY', 'BEGIN', 'CASE',
- 'CONST', 'DIV', 'DO', 'DOWNTO', 'ELSE',
- 'END', 'EXTERNAL', 'FILE', 'FOR', 'FORWARD',
- 'FUNCTION', 'GOTO', 'IF', 'IMPLEMENTATION', 'IN',
- 'INLINE', 'INTERFACE', 'INTERRUPT', 'LABEL', 'MOD',
- 'NIL', 'NOT', 'OF', 'OR', 'PACKED',
- 'PROCEDURE', 'PROGRAM', 'RECORD', 'REPEAT', 'SET',
- 'SHL', 'SHR', 'STRING', 'THEN', 'TO',
- 'TYPE', 'UNIT', 'UNTIL', 'USES', 'VAR',
- 'WHILE', 'WITH', 'XOR');
- var m, n, k : integer;
- begin
- id := upper(id);
- m := 1; n := no_of_keywords;
- is_keyword := true;
- while m<=n do
- begin
- k := m+(n-m) div 2;
- if id=keyword[k] then
- exit
- else if id>keyword[k] then
- m := k+1
- else
- n := k-1
- end;
- is_keyword := false
- end(*is_keyword*);
- type
- (* binary tree for identifiers, sorted in lexical order of idents,
- and linked list of integers (line numbers) *)
- BinTree = ^TreeNode;
- IntList = ^ListNode;
- TreeNode = record
- id : Ident;
- linenos : IntList;
- left, right : BinTree;
- end;
- ListNode = record
- lineno : integer;
- next : IntList
- end;
- var
- tree : BinTree;
- (* binary tree to store identifier occurrences *)
- procedure enter(id : Ident; lineno : integer);
- procedure enter_id(var tree : BinTree; id : Ident; lineno : integer);
- (* enter id, lineno into tree *)
- procedure enter_lineno(var linenos : IntList; lineno : integer);
- (* append lineno to linenos *)
- begin
- if linenos=nil then
- begin
- new(linenos);
- linenos^.lineno := lineno;
- linenos^.next := nil
- end
- else
- enter_lineno(linenos^.next, lineno)
- end(*enter_lineno*);
- begin
- if tree=nil then
- (* add new leave *)
- begin
- new(tree);
- tree^.id := id;
- tree^.linenos := nil;
- tree^.left := nil; tree^.right := nil;
- enter_lineno(tree^.linenos, lineno)
- end
- else if tree^.id=id then
- (* add lineno to the linenos list of this node *)
- enter_lineno(tree^.linenos, lineno)
- else if tree^.id>id then
- (* enter into left subtree *)
- enter_id(tree^.left, id, lineno)
- else
- (* enter into right subtree *)
- enter_id(tree^.right, id, lineno)
- end(*enter_id*);
- begin
- enter_id(tree, id, lineno)
- end(*enter*);
- procedure print;
- procedure print_ids(tree : BinTree);
- (* print out tree (inorder) *)
- procedure print_linenos(linenos : IntList);
- (* print linenos list *)
- begin
- if linenos<>nil then with linenos^ do
- begin
- write(yyout, lineno, ' ');
- print_linenos(next)
- end
- end(*print_linenos*);
- begin
- if tree<>nil then with tree^ do
- begin
- print_ids(left);
- write(yyout, ' ', id, ' ');
- print_linenos(linenos);
- writeln(yyout);
- print_ids(right)
- end
- end(*print_ids*);
- begin
- writeln(yyout);
- writeln(yyout);
- print_ids(tree);
- end(*print*);
- begin
- (* initialize binary tree, print line counter: *)
- tree := nil;
- write(yyout, yylineno:4, ': ');
- (* process file with yylex and print out cref list contained in binary
- tree *)
- begin_(code);
- if yylex=0 then ;
- print
- end.