package de.dhbwstuttgart.core; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import de.dhbwstuttgart.typeinference.Menge; import de.dhbwstuttgart.logger.Logger; import de.dhbwstuttgart.logger.LoggerConfiguration; import de.dhbwstuttgart.logger.Section; import de.dhbwstuttgart.myexception.CTypeReconstructionException; import de.dhbwstuttgart.myexception.JVMCodeException; import de.dhbwstuttgart.parser.JavaParser; import de.dhbwstuttgart.parser.Scanner; import de.dhbwstuttgart.parser.JavaParser.yyException; import de.dhbwstuttgart.syntaxtree.Class; import de.dhbwstuttgart.syntaxtree.ClassBody; import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.ImportDeclarations; import de.dhbwstuttgart.syntaxtree.Method; import de.dhbwstuttgart.syntaxtree.ParameterList; import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.misc.DeclId; import de.dhbwstuttgart.syntaxtree.misc.UsedId; import de.dhbwstuttgart.syntaxtree.type.GenericTypeVar; import de.dhbwstuttgart.syntaxtree.type.IMatchable; import de.dhbwstuttgart.syntaxtree.type.ITypeContainer; import de.dhbwstuttgart.syntaxtree.type.RefType; import de.dhbwstuttgart.syntaxtree.type.Type; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; import de.dhbwstuttgart.typeinference.ByteCodeResult; import de.dhbwstuttgart.typeinference.FunNInterface; import de.dhbwstuttgart.typeinference.FunVoidNInterface; import de.dhbwstuttgart.typeinference.Pair; import de.dhbwstuttgart.typeinference.ResultSet; import de.dhbwstuttgart.typeinference.TypeinferenceResultSet; import de.dhbwstuttgart.typeinference.assumptions.TypeAssumptions; import de.dhbwstuttgart.typeinference.exceptions.DebugException; import de.dhbwstuttgart.typeinference.exceptions.ParserError; import de.dhbwstuttgart.typeinference.exceptions.TypeinferenceException; public class MyCompiler implements MyCompilerAPI{ // PL: Der Zusammenhang zwischen paralist und vParaOrg muesste // noch geklaert werden 05-01-07 public static final int NO_LINENUMBER = -1; protected static Logger inferencelog = Logger.getLogger(MyCompiler.class.getName()); protected String OutputDir = ""; public Menge testPair = null; /** * Author: J�rg B�uerle
* Der private Konstruktor. Es soll von au�en kein Compiler angelegt werden * k�nnen, sondern nur eine API zur Verf�gung gestellt werden. * @param logger Konfiguration für Debug Ausgabe TODO */ private MyCompiler(){ this.init(); } /** * Author: Jörg Bäuerle
* Stellt eine neue Instanz der CompilerAPI zur Verf�gung. * Diese Methode sollte von der IDE aus aufgerufen werden, * um eine Quellcode-Datei zu kompilieren. * @return Die Compiler-API */ public static MyCompilerAPI getAPI(LoggerConfiguration loggerConfig){ Logger.setStandardConfiguration(loggerConfig); return new MyCompiler(); } /** * Parst den Quellcode und baut den abstrakten Syntaxbaum auf. Danach wird * automatisch der von Thomas Ott implementierte Algorithmus * NewTVar(jclass) (siehe Algorithmus 5.17 TRProg, Martin Pl�micke) * aufgerufen. *
Author: J�rg B�uerle * @param reader * @throws IOException * @throws JavaParser.yyException */ private void parse_backup(Reader reader) throws IOException, JavaParser.yyException{ } ///////////////////////////////////////////////////////////////////////////////////////////////// // Implementierte API-Methoden: ///////////////////////////////////////////////////////////////////////////////////////////////// /** * Author: J�rg B�uerle
* Initialisiert den Compiler */ public void init(){ TypePlaceholder.deleteRegistry(); } /** * Author: J�rg B�uerle
* Ruft die Parse-Methode. * @param file Die Quellcode-Datei * @throws FileNotFoundException Wenn die Quellcode-Datei nicht existiert. * @throws IOException Wenn was schief l�uft. * @throws JavaParser.yyException Wenn ein Fehler beim Parsen auftritt. */ public SourceFile parse(File file) throws FileNotFoundException, IOException, JavaParser.yyException{ FileReader fr = new FileReader(file); SourceFile ret = this.parse2SyntaxTree(fr); fr.close(); return ret; } /** * Author: J�rg B�uerle
* Ruft den Typrekonstruktionsalgorithmus auf. * @return Die Menge aller m�glichen Typkombinationen * @throws NullPointerException Wenn noch kein abstrakter Syntaxbaum vorhanden * ist. @throws CTypeReconstructionException Wenn ein Fehler bei der * Typrekonstruktion auftritt. */ public Menge typeReconstruction(Menge m_AbstractSyntaxTree) throws NullPointerException, CTypeReconstructionException{ inferencelog.info("##########################################", Section.TYPEINFERENCE); inferencelog.info("# TypeReconstruction-Algorithmus - START #", Section.TYPEINFERENCE); inferencelog.info("##########################################\n", Section.TYPEINFERENCE); TypeAssumptions globalAssumptions = makeFunNAssumptions(); Menge result = new Menge(); for(SourceFile srcFile : m_AbstractSyntaxTree){ result.addAll(srcFile.typeReconstruction(globalAssumptions)); } inferencelog.info("#########################################", Section.TYPEINFERENCE); inferencelog.info("# TypeReconstruction-Algorithmus - ENDE #", Section.TYPEINFERENCE); inferencelog.info("#########################################\n", Section.TYPEINFERENCE); return result; } /** * Erstellt die FunN-Assumptions * Fun0-FunN (momentan für N = 6) * @return */ private TypeAssumptions makeFunNAssumptions(){ TypeAssumptions ret = new TypeAssumptions(); //Basic Assumptions für die FunN Interfaces: //TODO: Hier mehr als Fun1-Fun5 implementieren for(int i = 0; i<6; i++){ FunNInterface funN = new FunNInterface(i); ret.add(funN.getPublicFieldAssumptions()); } for(int i = 0; i<6; i++){ FunVoidNInterface funN = new FunVoidNInterface(i); ret.add(funN.getPublicFieldAssumptions()); } return ret; } /** * Die Main-Funktion, �ber die der Compiler auch per Konsole gestartet * werden kann. * @param args Klassendatei */ public static void main(String[] args){ MyCompilerAPI compiler = MyCompiler.getAPI(new LoggerConfiguration()); // Hier koennten ggf. Aenderungen der Ausgabeeinstellungen // (Debuginfos) vorgenommen werden -> LOG4J try { compiler.parse(new File(args[0])); } catch (FileNotFoundException e) { System.err.println("Die Datei \""+args[0]+"\" konnte nicht gefunden werden."); System.exit(0); } catch (IOException e) { System.err.println("Fehler beim Parsen:"); System.err.println(e); System.exit(0); } catch (yyException e) { System.err.println("Fehler beim Parsen:"); System.err.println(e); System.exit(0); } } public void setOutputDir(String dir){ char c = dir.charAt(dir.length()-1); if (c != '/' & c != '\\') dir = dir + "/"; OutputDir = dir; // Verzeichnis(se) ggf. anlegen File f = new File(dir); f.mkdirs(); } public String getOutputDir(){ return OutputDir; } /** * @author Arne Lüdtke * Ersetzt alle GTVs durch TPHs mit gleichem Namen. Arbeitet Rekursiv. * ACHTUNG: BACKDOOR CREATE!!! Nur für Testzwecke verwenden. * @param T - Typ, bei welchem die GTVs ersetzt werden sollen. */ public static Type makeGenericTypeVars2TypePlaceHolders(Type T) { if(T instanceof RefType) { RefType refT = (RefType)T; if(refT.get_ParaList() != null) { Menge paras = refT.get_ParaList(); for(int i = 0; i Ergebnis: srcFile ////////////////////////////////////// SourceFile srcFile = null; try { srcFile = (SourceFile) parser.yyparse( scanner ); } catch (IOException | yyException e) { e.printStackTrace(); if(e instanceof yyException)throw new ParserError((yyException)e); } ////////////////////////////////////// // Postprocessing: ////////////////////////////////////// srcFile.parserPostProcessing(null); //Muss mit null aufgerufen werden. //Fertig: return srcFile; } /** * Diese Funktion nimmt einen Menge von Dateinamen. Alle diese Dateien werden zu einem SyntaxBaum geparst. * @return */ public Menge parse(Menge filenames) throws ParserError { Menge m_AbstractSyntaxTree = new Menge(); for(String filename : filenames){ StringBuffer fileData = new StringBuffer(); BufferedReader reader; try { reader = new BufferedReader( new FileReader(filename)); } catch (FileNotFoundException e) { throw new DebugException("Die Datei "+ filename+" konnte nicht gelesen werden."); } char[] buf = new char[1024]; int numRead=0; try { while((numRead=reader.read(buf)) != -1){ String readData = String.valueOf(buf, 0, numRead); fileData.append(readData); } reader.close(); } catch (IOException e) { e.printStackTrace(); } StringReader srcreader = new StringReader(fileData.toString()); //Den aus der Datei ausgelesenen Quellcode zu einem Syntaxbaum parsen: m_AbstractSyntaxTree.add(parse2SyntaxTree(srcreader)); // Alle Dateien nacheinander hintereinander anhängen... } return m_AbstractSyntaxTree; } @Override public SourceFile parse(String sourceCode) { return parse2SyntaxTree(new StringReader(sourceCode)); } @Override public Menge generateBytecode(Menge m_AbstractSyntaxTree, TypeinferenceResultSet typeinferenceResult) { //SourceFile parsedFile = this.m_AbstractSyntaxTree.firstElement(); //Class parsedClass = parsedFile.KlassenVektor.firstElement(); Menge ret = new Menge<>(); for(SourceFile sf : m_AbstractSyntaxTree){ ret.addAll(sf.generateBytecode(typeinferenceResult)); } return ret; } }