Due on March 8th 11:59 PM (Accepted with no penalty). |
Accepted late by March 9th 11:59 PM for 1 penalty |
Accepted late by March 10th 11:59 PM for 2 penalties |
Not accepted on or after March 11th 12:00 AM |
Due on March 8th 11:59 PM (Accepted with no penalty). |
Accepted late by March 9th 11:59 PM for 1 penalty |
Accepted late by March 10th 11:59 PM for 2 penalties |
Not accepted on or after March 11th 12:00 AM |
None yet!
For this assignment, you'll enhance the Jeff compiler by implementing name analysis, which collects each semantic symbol (e.g. variable or function) of the input program and builds a correspondance between identifiers and their symbol.
From a black-box view of jeffc, the changes needed are fairly straightforward: Implement a new command-line option for jeffc that augments unparsing so that every use or definition of an identifier has its type, in curly brackets, after its name. You'll also write error checking code which reports name analysis issues (these errors are described below). Make any changes in the code necessary to support the above tasks.
We will run the new -n <output_file>
option for
jeffc with various test-case input files, then
diff the expected results from the output of your code. We'll
use test files that we expect to unparse correctly, and
test files that have type errors that we expect to
report type errors.
You should submit a single tarred-and-zipped directory containing source code and a makefile such that the following invocations build and execute your code:
make
./jeffc <infile.jeff> -n <namedunparse.txt> 2> <errors.txt>
Where
You may work in pairs on this assignment. If you do work
in a pair, please include a file named TEAM.txt in your tarball with each
partner's name, each on their own line, in the format:
(lastname1,firstname1)
(lastname2,firstname2)
Since we'll be grading with diff, we'll require a very specific format for the unparsed data. The following format should be used for the type data in curly brackets after the identifier:
(param1Type,param2Type,...,paramNType) -> returnType
For names of global variables, parameters, and local variables output the type.
Your name analysis should find all of the errors described in the table given below; it should report the specified position of the error, and it should give exactly the specified error message (each message should appear on a single line, even if your browser adds a line break in the following table). Error messages should have the same format as in the scanner and parser.
Type of Error | Error Message Description |
---|---|
More than one declaration of an identifier in a given scope | <p>: Multiply declared identifier |
Use of an undeclared identifier | <p>: Undeclared identifier |
Bad declaration type (variable or parameter of void type) | <p>: Invalid type in declaration |
Where <p> is the position of the IDNode for each error.
Note that the ID names should not be printed as part of the error messages.
During name analysis, if a function name is multiply declared you should still process the formals and the body of the function; don't add a new entry to the symbol table for the function, but do create a new scope for the function's body, and add any formals to that new scope.
If you find a bad variable declaration (a variable of type void or of a bad aggregate type), give an error message and add nothing to the symbol table.
If a declaration is both "bad" (e.g., a non-function declared void) and is a declaration of a name that has already been declared in the same scope, you should give two error messages (first the "bad" declaration error, then the "multiply declared" error).
For this assignment, you'll enhance the jeffc compiler by implementing name analysis by traversing the AST. You'll also need to modify the AST nodes to assist in the collection of symbol table entries.
While there are a variety of ways to implement name analysis, the basic workflow should take the form of a traversal over the AST, doing the following: