CMPU 331:   Compiler Design (Spring 2016)
1 Overview
2 Phases of semantic action implementation
2.1 Phase 1:   Declarations
2.2 Phase 2:   Simple expressions
2.3 Phase 3:   Subscripts, Relational and Boolean operations
2.4 Phase 4:   The Complete Compiler
3 Resources
4 Submission

CMPU 331: Compiler Design (Spring 2016)

Semantic Actions

1 Overview

With the integration of semantic routines into the project as it exists so far, the project will be complete, and you should have a working generator for an Intermediate Code representation of any valid program written in the subset of Pascal described by the grammar.

To implement the semantic actions, you will use the augmented version of the original grammar that includes semantic actions in the right hand sides of most productions. The parser must be modified to recognize the presence of a semantic action on the stack top and call the appropriate routine when it does.

In addition to writing the routines, you should provide for error handling in the following ways:

2 Phases of semantic action implementation

The semantic actions are the biggest part of the compiler, in part because this is where all the pieces you have developed finally start working together. Therefore, this part of the project is itself divided into four phases, each due on a given date between now and the time the entire project is due. The due dates are listed on the main course page.

2.1 Phase 1: Declarations

In this phase of the project, you will implement actions 1, 2, 3, 4, 6, 7, 9, 13. These actions and approriate intializations are summarized here.

To lay the groundwork for this, do the following, in this order:

2.2 Phase 2: Simple expressions

In this phase of the project, you will implement actions 55, 56, 30, 31, 40, 41, 42, 43, 44, 45, 46, and 48. These actions and appropriate intializations are summarized on the phase 2 semantic actions page.

The next part of the semantic actions implementation involves generating intermediate code.

This is the general outline of tasks:

The next set of actions involve simple expressions, which can appear on the right side of an assignment operator. You will need to implement two more functions:

  • CREATE, which creates new variables (typically, temporary variables used in expression evaluation); and

  • TYPECHECK, which determines the types of operands in an expression.

Both of these routines are described in the phase 2 semantic actions page.

Once these routines are set up, implement actions 30, 31, 40, 41, 42, 43, 44, 45, 46, and 48.

Test your code on these files, using only the ones labeled "(no-subscripts)". Each file includes the expected output (in a comment at the end of the file). Note that the address numbers might be slightly different in your code, depending on the order in which you generate them.

Enhancements (not required): Provide for each user-defined variable to be initialized automatically to 0. Or, implement means to flag and issue an error for use of an undefined variable anywhere but on the left of an assignment operator.

2.3 Phase 3: Subscripts, Relational and Boolean operations

Implement actions 53, 54, 32, 33, 34, which handle subscripted array variables on the left and right hand sides of an assignment operator. You will also have to update action 48 to handle array references.

The next set of actions involve relational and boolean operators. You need to implement the following functions:

These routines are described on the semantic actions page.

Next, implement actions handling relational expressions (actions 38 and 39) and the parts of actions 42, 43, 44, 45 that deal with boolean operators (AND, OR), as well as action 47, which deals with NOT.

Once these actions are implemented, implement actions handling flow of control: actions 22, 27, 28, 29, 24, 25, 26.

Test your code on these files. Each file includes the expected output (in a comment at the end of the file).

2.4 Phase 4: The Complete Compiler

In the final phase, you will implement semantic actions that handle procedure and function declarations, setting up the function result variable, formal parameter declarations, and calling procedures and functions. This will involve checking that the number and types of parameters are correct, allocating local storage within a procedure or function, and freeing it at the end.

You should implement and test the semantic actions listed below, in this order:
  • Actions 5 and 11 (11 generates code that ends a procedure or function by freeing storage);

  • Actions 15, 16, and 17, which insert procedure and function names in the symbol table and handle the function result variable;

  • Actions 19, 20, and 21, which handle formal parameters;

  • Actions 35, 51, 54, 36, and 37, which handle procedure calls;

  • Actions 49, 50, and 52, which handle function calls;

  • Actions 51WRITE and 51READ, which handle calls to the built-in procedures READ and WRITE.

The output of your compiler should be two-fold:

Test files, together with their most up-to-date compiled forms, are available here.

3 Resources