package chocopy.pa2; import chocopy.common.analysis.AbstractNodeAnalyzer; import chocopy.common.analysis.SymbolTable; import chocopy.common.analysis.types.*; import chocopy.common.astnodes.*; /** Analyzes declarations to create a top-level symbol table. */ public class DeclarationAnalyzer extends AbstractNodeAnalyzer { /** Current symbol table. Changes with new declarative region. */ private SymbolTable sym = new SymbolTable<>(); /** Global symbol table. */ private final SymbolTable globals = sym; /** Receiver for semantic error messages. */ private final Errors errors; /** A new declaration analyzer sending errors to ERRORS0. */ public DeclarationAnalyzer(Errors errors0) { errors = errors0; } public SymbolTable getGlobals() { return globals; } @Override public Type analyze(Program program) { for (Declaration decl : program.declarations) { Identifier id = decl.getIdentifier(); String name = id.name; Type type = decl.dispatch(this); if (type == null) { continue; } if (sym.declares(name)) { errors.semError( id, "Duplicate declaration of identifier in same " + "scope: %s", name); } else { sym.put(name, type); } } return null; } @Override public Type analyze(VarDef varDef) { return ValueType.annotationToValueType(varDef.var.type); } @Override public Type analyze(FuncDef node) { FuncType current_func=new FuncType((ValueType) node.returnType.dispatch(this)); SymbolTable current_scope=new SymbolTable<>(sym); sym=current_scope; for (TypedVar param : node.params) { if (sym.declares(param.identifier.name)) { errors.semError( node.name, "Duplicate declaration of identifier in same " + "scope: %s", param.identifier.name); continue; } /* else if (sym.get(param.identifier.name)!= null) { System.out.println("Error:"+sym.get(param.identifier.name)); errors.semError( node.name, "Parameter shadows class name: %s", param.identifier.name); continue; }*/ Type p = param.dispatch(this); current_func.parameters.add((ValueType)p); sym.put(param.identifier.name, p); } for (Declaration decl : node.declarations) { Identifier id = decl.getIdentifier(); String name = id.name; Type type = decl.dispatch(this); if (type == null) { continue; } if (sym.declares(name)) { errors.semError( id, "Duplicate declaration of identifier in same " + "scope: %s", name); } else { sym.put(name, type); } } sym = sym.getParent(); return current_func; } @Override public Type analyze(GlobalDecl node) { if (globals.declares(node.variable.name)==false) { errors.semError( node.variable, "Not a global variable: %s", node.variable.name); return null; } return globals.get(node.variable.name); } }