{.pa} {**************************** procedure BuildTree ***************************} procedure BuildTree(var Tree :TreePointer; Key :IdentType; LengthWord, LNumber :Index; var Status :Info ); { This driver procedure will determine if a word is a reserved word by running a BinarySearch. If not reserved, then it will be inserted into the tree by running InsertTree. During insertion, if the word is new to the tree it will be put on to a node, otherwise it will run EnQueue to put the line number into a queue. The variables Reserved, Key, LengthWord, LNumber, & Status are used as globals within this procedure. } var TestKey :RWord; { test key for binary search. } UpKey :IdentType; { upper case version of identifier. } J :Index; { loop index. } Found :boolean; { has a reserved word been found. } {************************* function BinarySearch *************************} function BinarySearch (TestKey :RWord):boolean; { This function will check if a word is a reserved or a semi-reserved word. A true boolean flag (BinarySearch) will be returned if there is an occurance, otherwise false. } var Found :boolean; { found match } Mid, { median of list } Low, { lower bound of list } High :Index; { upper bound of list } begin Low := 1; { set lower bound } High := MaxReservedWords; { set upper bound } Found := false; while (Low <= High) and (not Found) do { binary search loop } begin Mid := (Low + High) div 2; if TestKey = Reserved[Mid] then begin Found := true; Status.UsedReserved[Mid] := Status.UsedReserved[Mid] + 1; end else if TestKey < Reserved[Mid] then High := Mid - 1 else Low := Mid + 1 end; { while } BinarySearch := Found { return result of search } end; { function BinarySearch } {**************************** procedure EnQueue ***************************} procedure EnQueue(var Entry :EntryType); { This procedure will add a line number to the queue. } var NewPointer :QueuePointer; { new node of queue } begin new(NewPointer); { allocate space in queue } NewPointer^.LineNumber := LNumber; NewPointer^.Next := nil; if Entry.Head = nil then begin { queue is empty } Entry.Head := NewPointer; Entry.Tail := NewPointer end else begin { store line number in } Entry.Tail^.Next := NewPointer; { queue } Entry.Tail := NewPointer end end; { procedure EnQueue } {************************** procedure InsertTree **************************} procedure InsertTree (var Tree :TreePointer); { This procedure will insert an identifier into the tree. If the identifier already exists, then the its line number will be enqueued. } begin if Tree = nil then begin new(Tree); { start new node of tree } with Tree^ do begin Status.DifferentIdents := Status.DifferentIdents + 1; Left := nil; { initialize sub-node } Right := nil; { initialize sub-node } Entry.Ident := Key; { unchanged identifier } Entry.UpIdent := UpKey; { upper case Ident } Entry.Head := nil; { initialize queue head } Entry.Tail := nil; { initialize queue tail } EnQueue (Entry); end; end { if Tree = nil } else with Tree^ do if UpKey < Entry.UpIdent then InsertTree (Left) { go to left node of tree } else if UpKey > Entry.UpIdent then InsertTree (Right) { go to right node of tree } else EnQueue (Entry) { duplicate Key } end; { procedure InsertTree } {****************************** procedure EnterTree **************************} begin for J := 1 to MaxIdentLength do { convert to upper case } UpKey[J] := upcase(Key[J]); if LengthWord <= MaxReservedLength then { word can't be reserved if it } { is longer than max. reserved } begin for J := 1 to MaxReservedLength do TestKey[J] := UpKey[J]; Found:=BinarySearch (TestKey); { determine if reserved } end else Found := false; if not Found then begin Status.TotalIdents := Status.TotalIdents + 1; { total idents } InsertTree (Tree) { insert ident into tree } end else Status.TotalReserved := Status.TotalReserved + 1 end; { procedure EnterTree } {.pa} {************************* procedure FindWord *******************************} procedure FindWord( LText :LineType; Number :Index; var State :Condition; var Tree :TreePointer; var Status :Info ); { This procedure will pick out words from a line of text. Only words containing alphabet, numbers or underscore characters will be taken; then call a function SearchLine to see if it already occurs on the current line.} var I,J,K :Index; { array index's. } Word :IdentType; { word built by program. } Ch :char; { character of LINETEXT. } Comment, { the start of a comment? } FoundWord :boolean; { has a word been created? } Line :WordType; { line of input file. } begin for K := 1 to MaxIdentLength do Word[K] := ' '; { init. WORD array to blanks } J := 1; { index of WORD array. } I := 0; { index of LINE array. } FoundWord := false; Line := LText.Line; { line of input file. } while I < LText.Len do { scan through line of text } begin I := I + 1; { increment index of LINE array } Ch := Line[I]; { assign one char } if (State = CCopy) and (J = 1) and (Ch in Alpha) then { char is valid } begin Word[1] := Ch; K := I; { start index of word } I := I + 1; while (I <= LText.Len) and { build word to MaxIdentLength } (Line[I] in AlphaNumeric) and (J < MaxIdentLength) do begin J := J + 1; Word[J] := Line[I]; I := I + 1; end; while (I < LText.Len) and { get rid of excess word } (Line[I] in AlphaNumeric) do I := I + 1; Status.AvgIdentLength := Status.AvgIdentLength + (I-K); FoundWord := true; { word has been found } BuildTree(Tree,Word,J,Number,Status); for K := 1 to J do Word[K] := ' '; J := 1 { start next word. } end { if -- then } else begin Comment := (Ch = '{') or ((Ch = '(') and (Line[I+1] = '*')); if (State = SkipComment) or Comment then begin if Comment then begin Status.Comments := Status.Comments + 1; State := SkipComment; end; while (State = SkipComment) and { get rid of comments } (I < LText.Len) do begin I := I + 1; if Line[I] = '}' then State := CCopy; if I+1 <= LText.Len then if (Line[I] = '*') and (Line[I+1] = ')') then State := CCopy; end; { while } end; if (State = SkipString) or (Ch = '''') then repeat { get rid of strings } I := I + 1; if Line[I] = '''' then State := CCopy else State := SkipString until (State = CCopy) or (I = LText.Len) end; { else } end; { while } if not FoundWord then Status.CommentLines := Status.CommentLines + 1 { count comment lines } end; { procedure FindWord }