"ALIAS" TYPES AND THE SAME-TYPE CHECk When trying to make your code look like the spec, a key observation is that types are different than symbols. A symbol is a name that refers to something (a variable, type, procdedure, etc.). Type "aliases" are particularly troubling this way, because multiple symbols may refer to the same thing: TYPE t1 = INTEGER; TYPE t2 = t1; TYPE t3 = INTEGER; VAR x : t1; y : t2; z : t3; All of these refer to the same type, and so all are "same type". So the question arises, how should we check these during type checking? The commonly proposed solution is to chase down the chain of references back to the base type: t2 --> t1 --> INTEGER. However, this is misleading. The first two are symbols, the last is a type. t2 doesn't really refer to t2, rather, it is a name for INTEGER. Of course, when discussing these problems, it is important to have: (1) an example (above) (2) the relevant pieces of grammar (with simplifications): TypeDecl ::= T_TYPE ID:id T_EQ Type:t VarDecl ::= T_VAR ID:id T_COLON Type:t Type ::= TypeDecl | QualIdent TypeDecl ::= T_INTEGER | T_REAL | ... QualIdent ::= ID Starting from here, we can see that there are two kinds of entities here symbols (ID's) and types. Every time we see an ID that refers to a type, we should retrieve its type (just like when we see a VAR ID we retrieve the STO: TypeDecl ::= T_TYPE ID:id T_EQ Type:t {: symTab.insert(new TypeSTO(id, t)); :} VarDecl ::= T_VAR ID:id T_COLON Type:t {: symTab.insert(VarSTO(id, symTab.lookup(qid).type())); :} Type ::= TypeDecl:t {: RESULT = t; :} | QualIdent {: RESULT = symTab.lookup(qid).type(); :} This results in a symbol table that looks like this: +-------+ | | | Glob | --> t1 --> t2 --> t3--> x --> y --> z | | / / / / / / +-------+ / / / / / / / / / / / / +--------+ < / / / / / | INTE- | <--+ / / / / | GER | <------------+-----+-----+-----+ +--------+ In other words, all the symbols end up pointing the the INTEGER type object. Once you've done this, the sameType method is a cinch: boolean VarSTO::sameType(STO b) { return this.m_type.sameType(b); // delegate } boolean Type::sameType(Type b) { return this == b; // simple! } Of course, it's not that simple for all checks. The POINTER check for same type uses structural equivalence, so the structure of the types must be checked.