Project #4
(Cross Reference Listing)
(Due 23 March 2007)
A utility feature that many compilers provide is the cross reference listing. Such a listing shows every user-defined identifier in a program and the line numbers within the program where those identifiers are used. In fact, good cross reference listings distinguish between instances of where the identifier is defined, used, and changed. Your task is to write a Java program that can analyze C++ programs and produce simplified cross reference listings for those programs.
We will assume that user-defined identifiers all begin with a letter (either uppercase or lowercase) and contain only letters, digits, underscores or periods (member operators). Identifiers may appear in a program immediately next to various other characters that are not part of the identifier's name. Your program should treat these other characters as identifier delimiters as it reads a C++ program file.
There are two special situations that your program must handle: comments and C-string constants. You may assume that all comments are line comments, i.e., begin with // and whatever follows on that line is a comment and must be ignored. Comments may start at any place on a line. There are no block comments (beginning with /*). (To be able to detect comments, you should NOT use / as a delimiter.) C-string constants begin and end with a double quote ("). Your program must ignore anything between the double quotes; but it must analyze all that comes before and all that comes after the C-string constant on the line. You may assume that there is no situation in which a double quote is part of a C-string. Similarly, character constants must be ignored; whatever appears between the single quotes should be skipped. You may assume that there is no situation in which a single quote is in a character constant or a C-string constant.
In every C++ program there are strings of characters which meet the specification of being identifiers; however, they are not. Instead, they are reserved or key words - elements of the language which are standard. You are being provided with a file reserved.txt which contains the words that you should consider reserved for this project (it is NOT the true set of reserved words for C++, but it will suffice). The words in reserved.txt are in alphabetical order. You can get a copy of the file from the I: drive, at I:\jlwolfe\310\s07
Cross reference listings always show the identifiers found in case-insensitive alphabetical order. Each line of the listing should have the following form:
identifier: line#, line#, . . .
where "identifier" is the identifier's name and each line number indicates a line on which the identifier appears. There should be no comma after the last line number in the list. Also, no line number should be duplicated; that is, if an identifier appears more than once on a line, that line number is to be listed only once. In addition, the line numbers must be in ascending order so that the first occurrence of the identifier is indicated by the first line number and the last is shown by the last line number. Following is a sample of the sort of output that is required for the program on the last page.
Cross Reference Listing for squareroot.cpp
19 identifiers found.
cin: 20, 23
cmath: 4
count: 16, 28, 31, 36, 38
cout: 19, 21, 26, 27, 31, 38
diff: 15, 28, 30
endl: 21, 26, 32, 39
EPSILON: 8, 28
fabs: 28
iomanip: 3
iostream: 2
main: 10
MAXTIMES: 7, 28
nextTrial: 13, 24, 30, 34, 35
number: 14, 20, 24, 26, 35
scientific: 27
setprecision: 31, 38
setw: 31, 38
showpoint: 27
trialx: 12, 23, 24, 30, 32, 34, 35, 39
You are being given three C++ programs to analyze with your Java program. All can be found on the I: drive in I:\jlwolfe\310\s07 The files are named: curling.cpp, ftree.h, and parser3.cpp
Requirements:
You must use a LinkedList to keep track
of the identifiers.
You must use LinkedLists to keep track
of the line numbers where the identifiers appear.
You must use iterators at least twice
in doing this program.
You should hand in a printout of your well-documented program and a printout of the program's output of a cross reference listing for curling.cpp, ftree.h and parser3.cpp In addition, you should create a folder named p4 in the folder on the P: drive that is named for you in association with this course. Into the p4 folder, you should put all .java files that you created for this project.
For extra credit: Create a numeric reference listing for the C++ program at the same time as you make the cross reference listing. A numeric reference listing has every unnamed numeric constant that appears in the program and the lines on which they appear. Obviously, numeric references begin with a digit; the listing should be in lexicographic order and have the same format as the cross reference listing. As with the cross reference listing, if a number appears twice on a line, that line should be listed only once. Note: floating point numbers in scientific notation may be reported in two parts.
Following is a square root program, a sample C++ program whose style matches the specification given. The line numbers along the side of the program statements are for your reference. Because the reserved.txt file does not include every C++ identifier that is a standard feature, some of them appear in the cross reference listing. These are regarded as beneficial to help keep track of feature usage in the program. This program is also available on the I: drive as squareroot.txt
1 // Program to find the square root of a number
2 #include <iostream>
3 #include <iomanip>
4 #include <cmath>
5
6 using namespace std;
7 const int MAXTIMES = 50;
8 const double EPSILON = 1.0e-012;
9
10 int main ()
11 {
12 double trialx;
// Trial square root
13 double nextTrial;
// Next trial root
14 double number;
// Number to take sq root of
15 double diff = 1.0;
// Change in root value
16 int count =
1; // Loop count
17
18 // Get
starting values
19 cout << "Number to take square
root of: ";
20 cin >> number;
21 cout << endl << "Using Newton's
Method" << endl
22 <<
"Initial" << " trial for root: ";
23 cin >> trialx;
24 nextTrial = 0.5 * (trialx + number /
trialx);
25 // Start
table for output
26 cout << "Count
Trial root of " << number << endl;
27 cout << scientific << showpoint;
28 while (count < MAXTIMES &&
fabs(diff) > EPSILON)
29 {
30 diff =
trialx - nextTrial;
31 cout <<
setw(5) << count << setprecision(12) << setw(22)
32
<< trialx << endl;
33
// Get next estimate
34 trialx
= nextTrial;
35 nextTrial
= 0.5*(trialx+number / trialx);
36 count++;
37 }
38 cout << setw(5) << count
<<setprecision(12) << setw(22)
39 <<
trialx << endl;
40 return 0;
41 }