package nl.uva.se.ql.typechecking; import nl.uva.se.ql.ast.expression.variable.Reference; import nl.uva.se.ql.ast.form.Form; import nl.uva.se.ql.ast.statement.CalculatedQuestion; import nl.uva.se.ql.ast.statement.Question; import nl.uva.se.ql.ast.type.Type; import nl.uva.se.ql.typechecking.error.DuplicateLabels; import nl.uva.se.ql.typechecking.error.ErrorList; import nl.uva.se.ql.typechecking.error.IncompatibleTypeDeclaration; import nl.uva.se.ql.typechecking.error.UndefinedReference; public class SymbolResolver extends AbstractResolver { private SymbolTable symbols; private ErrorList errors; private SymbolResolver() { symbols = new SymbolTable(); errors = new ErrorList(); } public static SymbolResult resolve(Form form) { SymbolResolver visitor = new SymbolResolver(); visitor.visit(form); return new SymbolResult(visitor.errors, visitor.symbols); } @Override public void visit(Question question) { addSymbol(question); } @Override public void visit(CalculatedQuestion calculatedQuestion) { addSymbol(calculatedQuestion); calculatedQuestion.getExpression().accept(this); } @Override public Void visit(Reference reference) { if (!symbols.containsSymbol(reference.getName())) { errors.addError(new UndefinedReference(reference.getLineNumber(), reference.getOffset(), reference.getName())); } return null; } private void addSymbol(Question question) { if (symbols.containsSymbol(question.getId())) { Type existingType = symbols.getTypeForSymbol(question.getId()); if (existingType.equals(question.getType())) { errors.addWarning(new DuplicateLabels(question.getLineNumber(), question.getOffset(), question.getId())); } else { errors.addError(new IncompatibleTypeDeclaration(symbols .getQuestionForSymbol(question.getId()), question)); } } else { symbols.addSymbol(question.getId(), question); } } }