Lecture 17

Context-Sensitive Analysis

also called semantic analysis

What properties of valid programs cannot be enforced by Context-Free Grammars?

To solve these, need more complex programs.

Next language class is context-sensitive languages (specified by context-sensitive grammars)

Ad hoc approach actually more useful.

e.g. Parse Tree

class Tree {
    public:
        string rule;                //grammar rule e.g. "term id"
        vector <Tree*> children;
};

Traversal example: print the tree

void print(Tree &t) {
    //print t.rule
    for (vector <Tree*>::iterator i = t.begin(); i != t.end(); i ++)
        print(**i);
}

What semantic analysis is needed for WLP4? What error need to be caught?

For now, assume wain is the only procedure.

Declaration errors

multiple/missing declaration.

Construct a symbol table.

These two passes could be merged.

Symbol table implementation

global variable

map<string, string> symbol_table; (name and type)

But

Issue:

int f() {
    int x = 0;
    return 1;
}
int wain(int a, int b) {
    int x = 0;
    return 1;
}

According to the algorithm, \(x\) is declared twice. But this should be OK.

Must forbid duplicated definition in the procedure, but allow them in different procedures.

Also forbid this:

int f() {}
int f() {}

Solution: * have a separate symbol table for each procedure * have one top level symbol table that collects all procedure names.

map <string, map <string, string> > top_symbol_table; //(procedure name, procedure's symbol table)

When traversing:

For variables, we store the declared type in the symbol table.

Is there type into for procedures? Yes, signature.

Note:

map <string, pair <vector <string>, map <string, string> > > top_symbol_table; //(procedure name, (signature, local symbol table))

Top compute the signature:

All of this can be done in one pass.

Types

Why do programming languages have types?

e.g.

int *a = NULL;  //denotes a pointer
a = 7;          //error, attempt store an int where a pointer is needed.

To check type correctness

Tree traversal

string typeof(Tree &t) {
    for each c in t.children
        compute typeof(c)
    determine typeof(t) from types of children, based on t.rule

e.g. ID - get its type from symbol table

\[\frac{<id.name,\tau>\in declaration}{id:\tau}\]

string typeof(Tree &t) {
    if (t.rule == "ID name"
        return symbol_table.lookup(name);
    ...
}