CPSC 411 - Lab Notes - 03-24 (Semantic checking)

We discussed checking the semantics of your abstract sytnax tree. The method for this in Python is to create a check method for each class of your ast. Each of these methods takes one argument, the symbol table. The return value is either a pair of the ir and type in the expression class checks, or an ir for all other classes.

In the code we assumed the symbol table has a standard interface that gives us a few required functions. Assuming our symbol table instance is st, they are:

st.newscope()
Prepares the symbol table to accept new entries at a new scope level.
st.removescope()
Removes the latest scope and all definitions made at that scope level
st.insert(dec)
Inserts the information from a declaration into the symbol table.
st.lookup(id)
Finds an identifier in the symbol table and returns it's information.

We first reviewed checking a program. It begins with inserting all the programs declarations into the symbol table.

def check(self,symbol_table):
    for declaration in self.declaration_list:
        symbol_table.insert(declaration)

We then prepare two empty lists to hold the IR of arrays and functions that are declared in the program.

    ir_of_array_list=[]
    ir_of_function_body_list=[]

Looping through the declarations, we check each of them. We either ignore them when they are for a simple var (no ir) or append them to the appropriate list.

    for declaration in self.declaration_list:
        ir_of_declaration= declaration.check(symbol_table)
        if ir_of_declaration != None :
            if ir_of_declaration.iAmAFunction():
                ir_of_function_body.append(ir_of_declaration)
            else:
                ir_of_array_list.append(ir_of_declaration)

Next, we loop through the statements, appending them to a statement ir list.

     ir_of_statement_list=[]
     for statement in self.statement_list:
         ir_of_statement_list.append(s.check(symbol_table))

Finally, we return the ir of the program.

    return iProgram(ir_of_function_body_list,
                    symbol_table.storage(),
                    ir_of_array_list,
                    ir_of_statement_list)

We continued with the check of the while and condition statements. Here, we see that we need to check for proper types in the expressions. Each of the expressions must be of type 'bool'

# while class
def check(self,symbol_table):
    (ir_of_expression,expression_type)=self.exp.check(symbol_table)
    if expression_type != 'bool' :
        raise semanticError("While expression not of type bool")
    ir_of_statement=self.stmt.check(symbol_table)
    return iWhile(ir_of_expression, ir_of_statement)

#if class
def check(self,symbol_table):
    (ir_of_expression,expression_type)=self.exp.check(symbol_table)
    if expression_type != 'bool' :
        raise semanticError("If expression not of type bool")
    ir_of_true_statement=self.true_statement.check(symbol_table)
    ir_of_false_statement=self.false_statement.check(symbol_table)
    return iCond(ir_of_expression,ir_of_true_statement,ir_of_false_statement)
Last modified by Brett Giles

Last modified: Mon Mar 31 11:40:44 MST 2003 Valid XHTML 1.0!