package compiler.semanal;
import compiler.abstree.AbsArrTyp;
import compiler.abstree.AbsAtomExpr;
import compiler.abstree.AbsAtomTyp;
import compiler.abstree.AbsBinExpr;
import compiler.abstree.AbsDecl;
import compiler.abstree.AbsDecls;
import compiler.abstree.AbsForStmt;
import compiler.abstree.AbsFunDecl;
import compiler.abstree.AbsFunName;
import compiler.abstree.AbsIfStmt;
import compiler.abstree.AbsLetExpr;
import compiler.abstree.AbsPtrTyp;
import compiler.abstree.AbsRecTyp;
import compiler.abstree.AbsStmt;
import compiler.abstree.AbsStmts;
import compiler.abstree.AbsTypDecl;
import compiler.abstree.AbsTypName;
import compiler.abstree.AbsUnExpr;
import compiler.abstree.AbsValExpr;
import compiler.abstree.AbsValStmt;
import compiler.abstree.AbsVarDecl;
import compiler.abstree.AbsVarName;
import compiler.abstree.AbsWhileStmt;
import compiler.abstree.Visitor;
import compiler.report.Report;
import compiler.symtable.SymDefinedAtThisScope;
import compiler.symtable.SymTable;
import compiler.symtable.SymUndefinedAtThisScope;
public class NameResolver implements Visitor
{
private int declCount = 0;
@Override
public Object visit(AbsArrTyp node)
{
node.base.accept(this);
return null;
}
@Override
public Object visit(AbsAtomExpr node)
{
return null;
}
@Override
public Object visit(AbsAtomTyp node)
{
return null;
}
@Override
public Object visit(AbsBinExpr node)
{
node.lsub.accept(this);
if (node.op != AbsBinExpr.DOT)
{
node.rsub.accept(this);
}
return null;
}
@Override
public Object visit(AbsDecls node)
{
for (AbsDecl decl : node.decls)
{
if (decl instanceof AbsVarDecl)
continue;
try
{
SymTable.names.put(decl.name, decl);
}
catch (SymDefinedAtThisScope e)
{
Report.error("Duplicate declaration of " + decl.name, decl.begLine, decl.begColumn, -3);
}
}
for (AbsDecl decl : node.decls)
{
decl.accept(this);
}
return null;
}
@Override
public Object visit(AbsForStmt node)
{
node.expr.accept(this);
node.hi.accept(this);
node.lo.accept(this);
node.stmts.accept(this);
return null;
}
@Override
public Object visit(AbsFunDecl node)
{
node.declId = declCount++;
node.typ.accept(this);
SymTable.names.newScope();
if (node.args != null)
{
node.args.accept(this);
}
node.val.accept(this);
SymTable.names.oldScope();
return null;
}
@Override
public Object visit(AbsFunName node)
{
AbsFunDecl decl = null;
try
{
decl = (AbsFunDecl) SymTable.names.get(node.name);
}
catch (SymUndefinedAtThisScope e)
{
Report.error("Undefined function " + node.name, node.begLine, node.begColumn, -4);
}
node.decl = decl;
if (node.args != null)
{
for (AbsValExpr ex : node.args)
{
ex.accept(this);
}
}
return null;
}
@Override
public Object visit(AbsIfStmt node)
{
node.cond.accept(this);
node.then_stmts.accept(this);
if (node.else_stmts != null)
{
node.else_stmts.accept(this);
}
return null;
}
@Override
public Object visit(AbsLetExpr node)
{
SymTable.names.newScope();
if (node.defs != null)
{
node.defs.accept(this);
}
if (node.stmts != null)
{
node.stmts.accept(this);
}
node.expr.accept(this);
SymTable.names.oldScope();
return null;
}
@Override
public Object visit(AbsPtrTyp node)
{
node.base.accept(this);
return null;
}
@Override
public Object visit(AbsRecTyp node)
{
SymTable.names.newScope();
for (AbsVarDecl comp : node.comps)
{
comp.accept(this);
}
SymTable.names.oldScope();
return null;
}
@Override
public Object visit(AbsStmts node)
{
for (AbsStmt stmt : node.stmts)
{
stmt.accept(this);
}
return null;
}
@Override
public Object visit(AbsTypDecl node)
{
node.declId = declCount++;
node.typ.accept(this);
return null;
}
@Override
public Object visit(AbsTypName node)
{
AbsTypDecl decl = null;
try
{
decl = (AbsTypDecl) SymTable.names.get(node.name);
}
catch (SymUndefinedAtThisScope e)
{
Report.error("Undeclared type " + node.name, node.begLine, node.begColumn, -5);
}
node.decl = decl;
return null;
}
@Override
public Object visit(AbsUnExpr node)
{
node.sub.accept(this);
return null;
}
@Override
public Object visit(AbsValStmt node)
{
node.expr.accept(this);
return null;
}
@Override
public Object visit(AbsVarDecl node)
{
node.declId = declCount++;
try
{
SymTable.names.put(node.name, node);
}
catch (SymDefinedAtThisScope e)
{
Report.error("Double declaration of " + node.name, node.begLine, node.begColumn, -5);
}
node.typ.accept(this);
return null;
}
@Override
public Object visit(AbsVarName node)
{
AbsVarDecl varDecl = null;
try
{
varDecl = (AbsVarDecl) SymTable.names.get(node.name);
}
catch (SymUndefinedAtThisScope e)
{
Report.error("Undeclared variable " + node.name, node.begLine, node.begColumn, -6);
}
node.decl = varDecl;
return null;
}
@Override
public Object visit(AbsWhileStmt node)
{
node.cond.accept(this);
node.stmts.accept(this);
return null;
}
}