A Semantic Checker for Klein
Translation of Programming Languages
Stage 4 of the
Klein compiler project
OUT: Friday, October 13
DUE: Friday, October 27
STATUS CHECK DUE: Friday, October 20
A Semantic Analyzer
This stage consists of the third component of your Klein compiler,
and three auxiliary programs.
- Your primary task is:
Write a semantic analyzer that ensures a parsed Klein program
satisfies the entire language specification.
The semantic analyzer is a function or object that takes as
input the abstract syntax tree of a candidate Klein program and
produces as output:
- an abstract syntax tree verified as legal, annotated with
type information at every node, and
- a symbol table that records all of the identifiers defined
and used in the program.
Implement your semantic analyzer by walking the nodes of the
abstract syntax tree. To assign type information, you will
want to do a pre-order traversal of the tree.
See below for
for the code that verifies semantic correctness and produces
the symbol table.
Be sure that your semantic analyzer reports any semantic errors
that it finds. Your semantic analyzer should produced an error
listing which includes enough detail that the programmer can
match the error with the offending code.
- Once your parser is able to generate an abstract syntax tree:
Write a program that uses your parser to produce a formatted
listing of the symbol table.
This listing is like a dictionary of the symbols used in the
program. For each function in the table, list its type, its
parameters, and the name of every function that calls it
(including itself, if it does).
This listing will give the programmer more information about
the structure of the program and maybe even about error
messages printed by the analyzer. Entries for functions that
are never called will help the programmer find "dead code" in
Extra Credit: The code that walks the AST to produce
this listing can find functions that are never called. Use
similar code in your semantic analyzer to print warning
messages about unused functions and parameters along
with the required error messages.
- In order to test your parser,
Create one new Klein program, named
semantic-errors.kln, that contains all of the
semantics errors found by your semantic analyzer.
Include in your repository a text file showing a run of your
analyzer against this program, with all of the error messages
it produces. Then debug this program so that it is legal
Klein and passes through the semantic analyzer with no errors
or warnings. (If you do the extra credit described above,
include code that generates warnings to this program, too.)
You should, of course, produce as many tests as necessary in
order to ensure that your parser works correctly. You are
also encouraged to use the test programs available on the
project home page.
- Finally, in order to use your client program as a tool,
Create an executable or a Unix command-line script named
that takes the name of a Klein source file as an argument
and runs your "dictionary" program on the resulting symbol
This program will, of course, have to scan, parse, semantically
check the Klein program first.
This is the fourth in a series of tools that makes up the
command-line suite of your Klein compiler.
- Status check
- You will need to create concrete examples to test each
element of your semantic analyzer early on. Create the
semantic-errors.kln program as a part of this
planning. Email your program to
by 5:00 PM on the due date.
- Final deliverable
- By 5:00 PM on the due date, submit
your project directory
Make your electronic submission using
the on-line submission system.
- (electronically) a zipped file named
project04.zip or project04.tar.gz
- (hardcopy) a print-out of the README
As before, submit only one copy of each assignment per team,
both electronically and on paper. The team captain or a
designated team member can be responsible for the submission.
Here are some thoughts on implementing the two components of
your semantic analyzer.
- Verifying Semantic Correctness. The first
part of verifying the program's semantic correctness is to
show that all expressions have valid data types. This
- ensuring that primitive operators are applied to
expressions of the correct type
- ensuring that each function call passes the correct
number of arguments, and that the arguments are of the
- ensuring that each function call returns a value of the
The second part of verifying the program's semantic
correctness is to show that the program satisfies all other
non-grammatical requirements of
the language spec,
including at least:
- there is a single user-defined function named
- there is not a user-defined function named
- every other function name is defined exactly once
- each function refers only to its formal parameters
and other functions
Extra credit is available for identifying unused functions
and unused formal parameters.
- Producing the Symbol Table. Your symbol
table should contain an entry for every function defined
in the program. With each, record:
- its data type
- a symbol table containing an entry for each of its
- the name of every function that calls the function,
including recursive calls
- any other information you think useful
You may want to extend, modify, or even replace the
implementation of your symbol table in the next project
task, when you build the compiler's run-time system. For
example, you may want to add entries for the number of
temporary objects needed at run-time or its line number
in the generated TM code. Therefore, devote some thought
to designing a reasonable interface to the table.
You may choose to implement a single module to verify the
program's correctness and produce the symbol table, or you may
choose to implement separate modules for the two tasks. This
design decision may affect the top-level structure of the
compiler you produce at the end of the semester, as well as
the structure of other programs that use the semantic analyzer
and symbol table. Either approach will work fine.
Eugene Wallingford .....
October 31, 2017