Programming Assigment 8
Course Project: Phase 4 -- Semantic Analysis/AST Gen
Background:
- Due Date:
Overview:
As the fourth step in the compiler project, you are to perform semantic actions as syntactic constructs are recognized by the parser. This is done by writing semantic routines that construct and then use the symbol table, manipulate the semantic stack and generate intermediate code, and by calling the semantic routines in appropriate places in the parsing. The parser you developed in Phase 3 will be used. Each program in the test set will be translated into an intermediate code program. The form of the intermediate code is an Abstract Syntax Tree. A detailed specification of this intermediate language is something you will develop
Program Structure:
Your parser/code-generator and scanner, along with a small driver, constitute the ``front-end'' of your compiler. This front-end should be linked into one program, which must accept at least the following arguments:
- -c Compile and assemble the input
- -d[lps]* Produce debugging output (see below)
- -o
Your front-end driver should accept and process these arguments. This driver should handle producing four different kinds of useful output, plus three additional types of debugging output. Which type of useful output to be produced (intermediate code, assembly language code, object code, or executable code) is determined by which of the -q, -S, -c options are given, respectively.
Giving none of these options shall be considered a request for executable code output. Regardless of what type of output is selected, if a -o argument is given, that output shall be placed in the named file. If no -o argument is given, output may be placed in a consistent location of your choosing.
The -d option, if one is given, may be followed by 0-3 of the letters l, p, and s, corresponding to the Lexer, Parser, and Symbol table. For each letter given, a corresponding debugging output file shall be generated. Each type of debugging information should be placed in a separate file. The lexer debugging output should consist of a list of tokens and their values as returned by the scanner (lexer). The parser debugging output should consist of a list of reductions performed by the parser. The symbol table debugging output should consist of symbol table dumps at key times during execution (for example, at the beginning and end of blocks). You may, of course, elect to produce additional debugging output for each phase, or to accept additional arguments to the -d option. You may also, if you wish, accept additional arguments for whatever uses you like, provided that these are appropriately documented.
Driver Responsibilities:
The driver should do all of the following:
- Parse all command-line arguments
- Open all files needed by the front-end
- Contain any necessary global variables used by the front-end.
- Create an initial symbol table
- Invoke the parser yyparse() and verify that it completes successfully
- Invoke the back-end, normally in a separate program, after parsing and intermediate code generation are complete.
Intermediate Code/AST Overview:
Your Abstract Syntax Tree should include everything necessary to generate any run time checks that are needed for error detection, such as bounds-checking. Your semantic analyzer should include tests on the correctness of the declarations, checking for use-before-declaration, type mismatches, and other semantic errors. If such an error is detected, compilation should cease and a descriptive error message should be printed to standard error, indicating if possible the location at which the error occurred. Your compiled program should halt when a run time error is encountered. Do not forget that some of the language constructs can be nested, and your semantic analysis routines should handle this. Building of the semantic analysis phase should be performed in the following steps:
- declaring constants/types and variables, including arrays
- generating code for simple assignments
- generating code for the conditional (IF) statement
- generating code for the WHILE loop
- generating code for the array accesses and operations
- handling declarations, generating code for procedures with single nesting levels and value/reference parameters
- handling declarations, generating code to process the FOR statement and the DO/WHILE statement
- handling declarations and generation of code for structs
- handling declarations, generating code for procedures with nested scope, and value/reference parameters
- Finishing other sections of the grammar.
Materials to be Submitted:
On the interim due date, submit the results of running your program with test cases demonstrating that you can handle (1), (2), (3), and (4) above.
Run your program with the -ds switch so that the symbol table is printed. Submit a script showing the execution of the program, the files containing the output and debugging information, and your yacc/bison definition file. On the project due date, submit your completed semantic analyzer. The format of the submission should be similar to that of the previous assignment. For both of the due dates, some test cases will be supplied. However, it is your responsibility to demonstrate the power of your semantic analyzer. The features that it handles should be discussed in the description in the heading and you should develop, and indicate which, test cases illustrate each feature. At a minimum, all graduate students are required to complete steps (1) - (6), and undergraduate students are required to complete (1) - (5). Additional items may be completed for extra credit, under the following restrictions:
- No extra credit will be given if all required items are not completed and working properly.
- The extra credit items must be done in order.