Computer Science 4627
Table Manager

Read this entire assignment before you begin on it.

Modify your compiler as follows.

  1. Create a type of types. The possible types in C- are int, void, int array and function. Each function has a codomain (a return type) and a domain (a list of types). Use a linked list to store the domain. You will need a tag in the type to tell what kind of type it is.

    Create some type constants (for int, void and int array) and a function that builds a function type, given a domain list and a codomain type. You will want some support for linked lists as well. Keep it simple.

  2. Add a table manager that stores integer keys and values that are types. Just use an array of structures, and use linear search to look up a name in the table.

    Write a function to look up a name in the table, and to return its type (or to say, somehow, that the name is not in the table.) You will need to know how many entries are in the table, and you will need to be able to back up the table to a particular size.

    You can allocate a table array of a fixed size (say, 200), and not make it grow. But be sure to make it very easy to change the fixed size. Use a named constant for the size.

  3. Testing software is not an afterthought. Software should be written for testing from the outset. One way to do that is to write instrumented programs. An instrumented program contains prints that can be turned on and off. Normally they are off, but at any time you can turn them back on, to see what is happening.

    Do not remove your prints of the productions being used. Instead, surround them by switches. Where you used to have something like

      printf("program -> declaration_list\n");
    
    write instead
      #ifdef SHOWPARSE
        printf("program -> declaration_list\n");
      #endif
    
    Now, if you do not define SHOWPARSE, then this will not be compiled when the program is compiled, so the print is not done. To switch on these prints, add line
      #define SHOWPARSE
    
    to the top of your parser.

  4. Modify your parser to make entries in the table. When the parser sees

        int x;
    
    it should put (x, int) into the table. That is, it remembers that x has type int. When the parser sees
        int x[10];
    
    it should put (x, int array) into the table. At a function, it should add the name of the function to the table, along with its type.

    You will want to make your params function give you a linked list of the types of the parameters, so that you can build the type of a function.

    When the compiler enters a compound statement, it should remember how many entries there are in the table. At the end of the compound statement, just restore the size to what it was at the beginning. That will remove all table entries that were made inside the compound statement.

  5. Now make the parser print the type of each identifier, whether a variable or a function, when it sees the identifier. Put these prints in a switch, such as

      #ifdef SHOWTYPES
        printf(...);
      #endif
    
    Turn this switch on in the program that you turn in.


Remark about instrumentation

It is convenient to be able to switch prints on or off both at compile time and at run time. So a debug print might look like this.

  #ifdef SHOWPARSE
    if(showparse) {
      printf(...);
    }
  #endif
Now you define SHOWPARSE to get this compiled into the program, and make showparse nonzero if you want the print done. You can turn on printing during just part of a run this way.

It is also convenient to have all of the switch definitions in one place, to make them easy to change. For example, you might create a file debug.h that you include in each file. Put your definitions in that file. Comment them out if you do not want them.

To keep things managable for this course, you are not required to have both compile-time and run-time switches. Just use compile-time switches.


What to turn in

Turn in all of your source files, including any that you have turned in earlier.