package de.fuberlin.projectci.test.parser;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.junit.Before;
import org.junit.Test;
import de.fuberlin.bii.lexergen.BuilderType;
import de.fuberlin.bii.lexergen.Lexergen;
import de.fuberlin.bii.tokenmatcher.errorhandler.ErrorCorrector.CorrectionMode;
import de.fuberlin.commons.lexer.ILexer;
import de.fuberlin.commons.parser.IParser;
import de.fuberlin.commons.parser.ISyntaxTree;
import de.fuberlin.commons.util.LogFactory;
import de.fuberlin.optimierung.LLVM_Optimization;
import de.fuberlin.projecta.analysis.SemanticAnalyzer;
import de.fuberlin.projecta.analysis.SemanticException;
import de.fuberlin.projectci.lrparser.LRParser;
import de.fuberlin.projectci.lrparser.LRParserException;
/**
* Testet alle Beispiel-Quellprogramme in einem Verzeichnis.
*/
public class LRParserTest {
private static Logger logger = LogFactory.getLogger(LRParserTest.class);
private static final String testSourceFilesDirPath="input/de/fuberlin/projectci/quellprogrammdateien";
private static final String DEFAULT_GRAMMAR_FILE = "input/de/fuberlin/projectci/non-ambigous.txt";
private static final String DEFAULT_TOKEN_DEFINITION_FILE = "input/de/fuberlin/bii/def/tokendefinition.rd";
@Before
public void setUp() throws Exception {
// Disable System.out to avoid spamming the console output
//PrintStream printStreamOriginal=System.out;
System.setOut(new PrintStream(new OutputStream(){
public void write(int b) {
}
}));
LogFactory.init(Level.INFO, null, null);
}
@Test
public void testParse() {
boolean rebuildDFA=false;
File[] sourceFiles = null;
try {
File testSourceFilesDir = new File(testSourceFilesDirPath);
sourceFiles = testSourceFilesDir.listFiles();
} catch (Exception e) {
logger.log(Level.SEVERE, "Failed to access example source files from "+testSourceFilesDirPath, e);
fail("Failed to access example source files from "+testSourceFilesDirPath);
}
if (sourceFiles==null){
logger.log(Level.SEVERE, "Failed to access any example source files from "+testSourceFilesDirPath);
fail("Failed to access any example source files from "+testSourceFilesDirPath);
}
if (sourceFiles.length==0){
logger.info("No source file found in "+testSourceFilesDirPath);
return;
}
IParser parser=new LRParser();
int numberOfTests=0;
int numberOfPassedTests=0;
for (int i = 0; i < sourceFiles.length; i++) {
File aSourceFile = sourceFiles[i];
List<ILexer> lexers=new ArrayList<ILexer>();
try {
lexers.add(new Lexergen(new File(DEFAULT_TOKEN_DEFINITION_FILE), aSourceFile, BuilderType.directBuilder, CorrectionMode.PANIC_MODE, rebuildDFA));
} catch (Exception e) {
logger.log(Level.SEVERE, "Failed to create Lexer "+BuilderType.directBuilder+" for tokendefinition="+DEFAULT_TOKEN_DEFINITION_FILE+" and sourceFile="+aSourceFile.getAbsolutePath(), e);
}
try {
lexers.add(new Lexergen(new File(DEFAULT_TOKEN_DEFINITION_FILE), aSourceFile, BuilderType.indirectBuilder, CorrectionMode.PANIC_MODE, rebuildDFA));
} catch (Exception e) {
logger.log(Level.SEVERE, "Failed to create Lexer "+BuilderType.indirectBuilder+" for tokendefinition="+DEFAULT_TOKEN_DEFINITION_FILE+" and sourceFile="+aSourceFile.getAbsolutePath(), e);
}
for (ILexer aLexer : lexers) {
numberOfTests++;
try {
logger.info("Testing sourceFile: "+aSourceFile.getAbsolutePath()+" with lexer="+((Lexergen)aLexer).getBuilderType()+", tokenDefintion="+DEFAULT_TOKEN_DEFINITION_FILE+" and grammar="+DEFAULT_GRAMMAR_FILE);
ISyntaxTree syntaxTree = null;
try {
syntaxTree = parser.parse(aLexer, DEFAULT_GRAMMAR_FILE);
if (syntaxTree==null){
logger.log(Level.SEVERE, "Parser failed to create SyntaxTree.");
continue;
}
} catch (RuntimeException e) {
logger.log(Level.SEVERE, "Parser failed to create SyntaxTree.", e);
continue;
}
SemanticAnalyzer semanticAnalyzer= new SemanticAnalyzer(syntaxTree);
try {
// analyze() now internally calls checkSemantics, etd.
semanticAnalyzer.analyze();
try {
try {
String generatedLLVMCode = semanticAnalyzer.getAST().genCode();
@SuppressWarnings("unused")
String optimized_llvm_code = null;
try {
LLVM_Optimization llvm_optimizer = new LLVM_Optimization();
optimized_llvm_code = llvm_optimizer.optimizeCodeFromString(generatedLLVMCode);
} catch (Exception e) {
logger.log(Level.WARNING,"LLVM Optimization failed. Use unoptimized code!",e);
// Nutze nicht optimierten Code
optimized_llvm_code = generatedLLVMCode;
}
try {
// TODO CodeGenerator kann nicht getestet werden, da Exception in CodeGenerator.generateCode2 gefangen und nicht wieder geworfen wird.
// boolean debug = false;
// boolean guiFlag = false;
// boolean exec = false;
// String asmType = "gnu";
//
// String machineCode = CodeGenerator.generateCode(optimized_llvm_code, asmType, debug, guiFlag);
// // TODO Gibt es eine einfache Möglichkeit die Güte des LLVM Codes zu beurteilen?
// if (machineCode==null){
// logger.log(Level.SEVERE, "CodeGenerator failed to generate Machine code.");
// continue;
// }
//
//
//// if (outputFile != null) {
//// CodeGenerator.writeFile(exec, outputFile, machineCode);
//// }
////
//// if (exec) {
//// CodeGenerator.exec(outputFile);
//// }
numberOfPassedTests++;
logger.info("Succeed to generate LLVM code.");
// logger.info("Succeed to generate Machine code.");
} catch (RuntimeException e) {
logger.log(Level.WARNING,"Machine Code Generation failed.",e);
}
} catch (Exception e) {
logger.log(Level.SEVERE, "SemanticAnalyzer failed to generate LLVM code on SyntaxTree.", e);
}
} catch (RuntimeException e) {
logger.log(Level.WARNING, "SemanticAnalyzer failed to check semantics on SyntaxTree.", e);
}
} catch (SemanticException e) {
logger.log(Level.SEVERE, "SemanticAnalyzer failed to analyze SyntaxTree.", e);
}
} catch (LRParserException e) {
logger.log(Level.SEVERE, "LRParser failed to create SyntaxTree", e);
}
}
}
int numberOfFaildTests=numberOfTests-numberOfPassedTests;
assertEquals(numberOfFaildTests+" out of "+numberOfTests+" tests failed", numberOfTests,numberOfPassedTests);
}
}