package de.fuberlin.projecta;
import org.junit.Test;
import de.fuberlin.commons.parser.ISyntaxTree;
import de.fuberlin.projecta.analysis.SemanticAnalyzer;
import de.fuberlin.projecta.analysis.SemanticException;
/**
* This tests the following parts:
* Lexer -> Parser -> Semantic Analysis
*
* The focus here lies on semantic analysis failures
*/
public class SemanticAnalysisTest {
// "forward declare"
static String mainC(String block) {
return ParserTest.mainC(block);
}
@Test(expected = IllegalStateException.class)
public void testDuplicateIds() {
final String code = mainC("int a; int a;");
analyze(code);
}
@Test
public void testValidFunctionDef() {
final String code = mainC("") +
"def void foo(int a){int b;}" +
"def void foo(real a){int b;}";
analyze(code);
}
@Test(expected = IllegalStateException.class)
public void testInvalidFunctionDef() {
final String code = mainC("") + "def int foo() {} def real foo() {}";
analyze(code);
}
@Test
public void testDeclarationScope() {
final String code = mainC("int a; { int a; }");
analyze(code);
}
@Test(expected = SemanticException.class)
public void testInvalidArtihmeticsOnStrings(){
final String code = mainC("\"foo\" + \"foo\";");
analyze(code);
}
@Test(expected = SemanticException.class)
public void testInvalidArtihmeticsOnRecords(){
final String code = mainC("record {int a; int b; } r; r + r;");
analyze(code);
}
@Test(expected = SemanticException.class)
public void testInvalidAssignOperand1() {
final String code = mainC("bool a; a = !42;");
analyze(code);
}
@Test(expected = SemanticException.class)
public void testInvalidAssignOperand2() {
final String code = mainC("bool b; int i; i = b;");
analyze(code);
}
@Test(expected = SemanticException.class)
public void testInvalidAssignOperand3() {
final String code = mainC("int a; a = 0.0;");
analyze(code);
}
@Test
public void testRecordAsReturnType(){
final String code = mainC("") +
"def record {int real; int imag;} foo() {" +
"record {int real; int imag;} myRecord; return myRecord;" +
"}";
analyze(code);
}
@Test
public void testMultiExpression() {
String code = mainC("int a; a = 1 + 2 + 3;");
analyze(code);
}
@Test
public void testRecordBehaviour(){
final String code = mainC("") +
"def int foobar(record {int r; int i;} t) {" +
"t.r = 1; t.i = 0;" +
"}";
analyze(code);
}
@Test
public void testReturnRecordElement() {
String code = mainC("record {int r; int i;} r; r.r = 0; return r.r;");
analyze(code);
}
@Test(expected = SemanticException.class)
public void testMissingMain(){
final String code = "def int foobar(){return 0;}";
analyze(code);
}
@Test(expected = SemanticException.class)
public void testReturnVoidInNonVoidFunction() {
final String code = "def int main() { return; }";
analyze(code);
}
@Test(expected = SemanticException.class)
public void testReturnValueInVoidFunction() {
final String code = mainC("") + "def void foo() { return 1; }";
analyze(code);
}
@Test(expected = SemanticException.class)
public void testInvalidPrintArgument() {
final String code = mainC("record { int a; int b; } r; print r;");
analyze(code);
}
@Test
public void testFunctionCallAsOperand() {
String code = "def int foo() { return 1; }" + mainC("int i; i = foo();");
analyze(code);
}
@Test(expected = SemanticException.class)
public void testVariableDeclaredVoid() {
final String code = mainC("void v;");
analyze(code);
}
@Test(expected = SemanticException.class)
public void testUndefinedVariable(){
final String code = mainC("v = 1;");
analyze(code);
}
static void analyze(String code) {
ISyntaxTree parseTree = ParserTest.parse(code);
SemanticAnalyzer analyzer = new SemanticAnalyzer(parseTree);
analyzer.analyze();
}
}