You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ChocoPy/src/main/java/chocopy/pa2/DeclarationAnalyzer.java

187 lines
6.0 KiB

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<Type>
{
/** Current symbol table. Changes with new declarative region. */
private SymbolTable<Type> sym = new SymbolTable<>();
/** Global symbol table. */
private final SymbolTable<Type> 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;
ClassVType cvt = new ClassVType("object");
FuncValueType init = new FuncValueType(Type.OBJECT_TYPE);
init.parameters.add(Type.OBJECT_TYPE);
sym.put("object", cvt);
cvt = new ClassVType("int");
init = new FuncValueType(Type.INT_TYPE);
init.parameters.add(Type.INT_TYPE);
sym.put("int", cvt);
cvt = new ClassVType("str");
init = new FuncValueType(Type.STR_TYPE);
init.parameters.add(Type.STR_TYPE);
sym.put("str", cvt);
cvt = new ClassVType("bool");
init = new FuncValueType(Type.BOOL_TYPE);
init.parameters.add(Type.BOOL_TYPE);
sym.put("bool", cvt);
}
public SymbolTable<Type> 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);
}
}
// Check for return statements at top
for (Stmt stmt : program.statements)
{
if (stmt instanceof ReturnStmt)
errors.semError(
stmt, "Return statement cannot appear at the top level");
}
return null;
}
@Override
public Type analyze(VarDef varDef) {
return ValueType.annotationToValueType(varDef.var.type);
}
@Override
public Type analyze(FuncDef node) {
FuncValueType current_func=new FuncValueType((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 && sym.get(param.identifier.name) instanceof ClassVType)
{
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);
}
@Override
public Type analyze(ClassDef node)
{
ClassVType cvt=new ClassVType(node.name.name);
SymbolTable current_scope=new SymbolTable<>(sym);
sym=current_scope;
Type super_class = sym.get(node.superClass.name);
cvt.super_class = node.superClass;
if (super_class == null)
{
errors.semError(
node.name, "Super-class not defined: %s", node.superClass.name);
}
else if ((super_class instanceof ClassVType)==false)
{
errors.semError(
node.name, "Super-class must be a class: %s", node.superClass.name);
}
else if (node.superClass.name.equals("int") || node.superClass.name.equals("bool") || node.superClass.name.equals("str"))
{
errors.semError(
node.name, "Cannot extend special class: %s", node.superClass.name);
}
else
{
for (Declaration decl : node.declarations)
{
Identifier id = decl.getIdentifier();
String name = id.name;
Type type = decl.dispatch(this);
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 cvt;
}
}