// Path: src/java/minijava/ast/Program.java
// public class Program extends AST {
// 	
// 	public final MainClass mainClass;
// 	public final NodeList<ClassDecl> classes;
// 
// 	public Program(MainClass mainClass, NodeList<ClassDecl> otherClasses) {
// 		this.mainClass=mainClass;
// 		this.classes=otherClasses; 
// 	}
// 
// 	public Program(MainClass m, List<ClassDecl> cs) {
// 		this(m, new NodeList<ClassDecl>(cs));
// 	}
// 	
// 	public <R> R accept(Visitor<R> v) {
// 		return v.visit(this);
// 	}
// 
// }
// 
// Path: src/java/minijava/parser/MiniJavaParser.java
// public class MiniJavaParser {
// 
// 	/**
// 	 * Read input from a File and parse it into an AST representation.
// 	 */
// 	public static Program parse(File file) throws IOException, ParseException {
// 		FileReader input = new FileReader(file);
// 		try {
// 			return parse(input);
// 		}
// 		finally { //No matter what happens, always close the file!
// 			input.close();
// 		}
// 	}
// 
// 	/**
// 	 * Read input from a java.io.Reader and parse it into an AST. It is the
// 	 * caller's responsibility to close the Reader.
// 	 */
// 	private static Program parse(Reader input) throws ParseException {
// 		JCCMiniJavaParser parser = new JCCMiniJavaParser(input);
// 		return parser.Program();
// 	}
// 
// 	/**
// 	 * Read input directly from a String and parse it into an AST.
// 	 */
// 	public static Program parse(String inputText) throws ParseException {
// 		return parse(new StringReader(inputText));
// 	}
// 
// 	/**
// 	 * Normally we don't need to parse just expressions by themselves. But this
// 	 * is a convenience method, used by the unit tests for creating error messages.
// 	 * @throws ParseException 
// 	 */
// 	public static Expression parseExp(String exp) throws ParseException {
// 		JCCMiniJavaParser parser = new JCCMiniJavaParser(new StringReader(exp));
// 		return parser.Expression();
// 	}
// 	/**
// 	 * Pretty print an AST node and return the result as a String.
// 	 */
// 	public static String unparse(AST node) {
// 		return node.toString(); 
// 		// This assumes that toString on AST nodes is appropriately implemented.
// 		// If you decided to generate/implement your own AST classes rather than use 
// 		// the ones we provided for you, you may need to implement this unparse method 
// 		// differently.
// 	}
// 
// }
// 
// Path: src/java/minijava/typechecker/implementation/TypeCheckerImplementation.java
// public class TypeCheckerImplementation {
// 	
// 	Program program;
// 	ImpTable<ClassEntry> classTable;
// 	ErrorReport reporter;
// 	public TypeCheckerImplementation(Program program) {
// 		this.program = program;
// 	}
// 
// 
// 	public TypeChecked typeCheck() throws TypeCheckerException{
// 		reporter = new ErrorReport();
// 		buildClassTable();
// 		
// 		TypeCheckerVisitor checker = new TypeCheckerVisitor(classTable, reporter);
// 		checker.visit(program);
// 		
// 		reporter.close();//this will throw the first exception that was reported, if it exists.
//                 return new TypeChecked(program, classTable);
// 	}
// 
// 	public Object buildClassTable(){
// 		ClassBuilderVisitor builder = new ClassBuilderVisitor(reporter);
// 		classTable = builder.visit(program);
// 		
// 		// Resolve class inheritance
// 		Iterator<Entry<String, ClassEntry>> itr = classTable.iterator();
// 		while (itr.hasNext()) {
// 			Entry<String, ClassEntry> entry;
// 			entry = (Entry<String, ClassEntry>) itr.next();
// 			String parentClassName = entry.getValue().getParentName(); 
// 			
// 			if (parentClassName != null) {
// 				ClassEntry parentClass = classTable.lookup(parentClassName);
// 				entry.getValue().setParentClass(parentClass);
// 			}
// 		}
// 		
// 		return classTable;
// 	}
// 
// }


import java.io.File;
import minijava.ast.Program;
import minijava.parser.MiniJavaParser;
import minijava.typechecker.implementation.TypeCheckerImplementation;
package minijava.typechecker;



/**
 * This file constitutes the "interface" with the MiniJavaTypeChecker. 
 * It provides a few static methods that allow the MiniJava checker to be
 * invoked on a given input program.
 * <p>
 * You may change the implementations of these methods, or any other methods
 * and classes in this project, as long as your changes are compatible with
 * the unit tests provided in the test packages.
 * 
 * @author kdvolder
 */
public class MiniJavaTypeChecker {
	
	/**
	 * Parse the contents of a given file and typecheck it. If type checking succeeds
	 * the method returns normally. 
	 * <p>
	 * If the program has a type error or undeclared identifier error then an appropriate 
	 * TypeCheckerException must be raised. The type checker may try to continue checking
	 * after the first error is encountered, but should nevertheless still raise a 
	 * TypeCheckerException (this can be done by postponing the raising of the Exception
	 * until all of the input has been processed). See the class {@link ErrorReport}
	 * <p>
	 * Other Exceptions may be raised if the parsing or reading of the file fails.
	 * <p>
	 * The TypeChecker may return some representation of the TypeChecked program along with
	 * useful information derived by the checker.
	 * <p>
	 * This information will be passed along to the next phase of the compiler. 
	 * <p>
	 * Right now what information goes in TypeChecked is irrelevant. All that matters is
	 * that errors get discovered. In later stages of the compiler however, you may find
	 * that your type checker computed valuable information (such as the symbol table from
	 * phase 1, which you may want to use again). At this point you will be able to
	 * add information into the TypeChecked object without breaking the type checker
	 * tests.
	 */
	public static TypeChecked parseAndCheck(File file) throws TypeCheckerException, Exception {
// Path: src/java/minijava/ast/Program.java
// public class Program extends AST {
// 	
// 	public final MainClass mainClass;
// 	public final NodeList<ClassDecl> classes;
// 
// 	public Program(MainClass mainClass, NodeList<ClassDecl> otherClasses) {
// 		this.mainClass=mainClass;
// 		this.classes=otherClasses; 
// 	}
// 
// 	public Program(MainClass m, List<ClassDecl> cs) {
// 		this(m, new NodeList<ClassDecl>(cs));
// 	}
// 	
// 	public <R> R accept(Visitor<R> v) {
// 		return v.visit(this);
// 	}
// 
// }
// 
// Path: src/java/minijava/parser/MiniJavaParser.java
// public class MiniJavaParser {
// 
// 	/**
// 	 * Read input from a File and parse it into an AST representation.
// 	 */
// 	public static Program parse(File file) throws IOException, ParseException {
// 		FileReader input = new FileReader(file);
// 		try {
// 			return parse(input);
// 		}
// 		finally { //No matter what happens, always close the file!
// 			input.close();
// 		}
// 	}
// 
// 	/**
// 	 * Read input from a java.io.Reader and parse it into an AST. It is the
// 	 * caller's responsibility to close the Reader.
// 	 */
// 	private static Program parse(Reader input) throws ParseException {
// 		JCCMiniJavaParser parser = new JCCMiniJavaParser(input);
// 		return parser.Program();
// 	}
// 
// 	/**
// 	 * Read input directly from a String and parse it into an AST.
// 	 */
// 	public static Program parse(String inputText) throws ParseException {
// 		return parse(new StringReader(inputText));
// 	}
// 
// 	/**
// 	 * Normally we don't need to parse just expressions by themselves. But this
// 	 * is a convenience method, used by the unit tests for creating error messages.
// 	 * @throws ParseException 
// 	 */
// 	public static Expression parseExp(String exp) throws ParseException {
// 		JCCMiniJavaParser parser = new JCCMiniJavaParser(new StringReader(exp));
// 		return parser.Expression();
// 	}
// 	/**
// 	 * Pretty print an AST node and return the result as a String.
// 	 */
// 	public static String unparse(AST node) {
// 		return node.toString(); 
// 		// This assumes that toString on AST nodes is appropriately implemented.
// 		// If you decided to generate/implement your own AST classes rather than use 
// 		// the ones we provided for you, you may need to implement this unparse method 
// 		// differently.
// 	}
// 
// }
// 
// Path: src/java/minijava/typechecker/implementation/TypeCheckerImplementation.java
// public class TypeCheckerImplementation {
// 	
// 	Program program;
// 	ImpTable<ClassEntry> classTable;
// 	ErrorReport reporter;
// 	public TypeCheckerImplementation(Program program) {
// 		this.program = program;
// 	}
// 
// 
// 	public TypeChecked typeCheck() throws TypeCheckerException{
// 		reporter = new ErrorReport();
// 		buildClassTable();
// 		
// 		TypeCheckerVisitor checker = new TypeCheckerVisitor(classTable, reporter);
// 		checker.visit(program);
// 		
// 		reporter.close();//this will throw the first exception that was reported, if it exists.
//                 return new TypeChecked(program, classTable);
// 	}
// 
// 	public Object buildClassTable(){
// 		ClassBuilderVisitor builder = new ClassBuilderVisitor(reporter);
// 		classTable = builder.visit(program);
// 		
// 		// Resolve class inheritance
// 		Iterator<Entry<String, ClassEntry>> itr = classTable.iterator();
// 		while (itr.hasNext()) {
// 			Entry<String, ClassEntry> entry;
// 			entry = (Entry<String, ClassEntry>) itr.next();
// 			String parentClassName = entry.getValue().getParentName(); 
// 			
// 			if (parentClassName != null) {
// 				ClassEntry parentClass = classTable.lookup(parentClassName);
// 				entry.getValue().setParentClass(parentClass);
// 			}
// 		}
// 		
// 		return classTable;
// 	}
// 
// }


// Path: src/java/minijava/typechecker/MiniJavaTypeChecker.java
import java.io.File;
import minijava.ast.Program;
import minijava.parser.MiniJavaParser;
import minijava.typechecker.implementation.TypeCheckerImplementation;

package minijava.typechecker;



/**
 * This file constitutes the "interface" with the MiniJavaTypeChecker. 
 * It provides a few static methods that allow the MiniJava checker to be
 * invoked on a given input program.
 * <p>
 * You may change the implementations of these methods, or any other methods
 * and classes in this project, as long as your changes are compatible with
 * the unit tests provided in the test packages.
 * 
 * @author kdvolder
 */
public class MiniJavaTypeChecker {
	
	/**
	 * Parse the contents of a given file and typecheck it. If type checking succeeds
	 * the method returns normally. 
	 * <p>
	 * If the program has a type error or undeclared identifier error then an appropriate 
	 * TypeCheckerException must be raised. The type checker may try to continue checking
	 * after the first error is encountered, but should nevertheless still raise a 
	 * TypeCheckerException (this can be done by postponing the raising of the Exception
	 * until all of the input has been processed). See the class {@link ErrorReport}
	 * <p>
	 * Other Exceptions may be raised if the parsing or reading of the file fails.
	 * <p>
	 * The TypeChecker may return some representation of the TypeChecked program along with
	 * useful information derived by the checker.
	 * <p>
	 * This information will be passed along to the next phase of the compiler. 
	 * <p>
	 * Right now what information goes in TypeChecked is irrelevant. All that matters is
	 * that errors get discovered. In later stages of the compiler however, you may find
	 * that your type checker computed valuable information (such as the symbol table from
	 * phase 1, which you may want to use again). At this point you will be able to
	 * add information into the TypeChecked object without breaking the type checker
	 * tests.
	 */
	public static TypeChecked parseAndCheck(File file) throws TypeCheckerException, Exception {
		Program program = MiniJavaParser.parse(file);