Compare commits
6 Commits
084808c3ab
...
fb5372bc8f
Author | SHA1 | Date | |
---|---|---|---|
|
fb5372bc8f | ||
|
f29be4fd8c | ||
|
34bb86c7f4 | ||
|
c0e197e2d0 | ||
|
ae872ed906 | ||
91552ad147 |
35
pom.xml
35
pom.xml
@ -23,6 +23,24 @@
|
||||
<version>5.11.0-M2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-suite-engine</artifactId>
|
||||
<version>1.11.0-M2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.11.0-M2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.antlr</groupId>
|
||||
<artifactId>antlr4-runtime</artifactId>
|
||||
@ -44,18 +62,6 @@
|
||||
<version>3.26.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.11.0-M2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>5.11.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@ -65,6 +71,11 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M5</version> <!-- Change the version as needed -->
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*Test.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
|
68
readme.md
Normal file
68
readme.md
Normal file
@ -0,0 +1,68 @@
|
||||
# "Nicht Haskel 2.0" Java Compiler
|
||||
|
||||
Realisation of a subset of the Java Standard Compiler in the course Compiler Construction of the 4th semester Computer Science at the Duale Hochschule Suttgart (Horb).
|
||||
|
||||
This project aims to provide a simplified version of the Java compiler, focusing on key language features and demonstrating the principles of compiler construction.
|
||||
|
||||
## Realised Java syntax
|
||||
|
||||
- **Data types**: `int`, `boolean`, `char`
|
||||
- **Access modifier**: `public`, `protected`, `private`
|
||||
- **Operators**: `=` `+` `-` `*` `%` `/` `>` `<` `>=` `<=` `==` `!=` `!` `&&` `||` `++` `--`
|
||||
- **Keywords**: `class`, `this`, `while`, `do`, `if`, `else`, `for`, `return`, `new`, `switch`, `case`, `break`, `default`, `:`
|
||||
- **Statements**:
|
||||
- `if` ... `if else` ... `else`;
|
||||
- `while` ... ;
|
||||
- `do` ... `while`;
|
||||
- `for`;
|
||||
- `switch` ... `case` ... ;
|
||||
- **Comments**:
|
||||
- Single line: `// comment`
|
||||
- Multi-line: `/* comment */`
|
||||
- **Further functions**:
|
||||
- All methods are overloadable
|
||||
- High maintainability and expandability through implementation of the visitor pattern
|
||||
- Logging Input and Outputs
|
||||
- Error Handling in the Semantic Check
|
||||
|
||||
## Project Structure
|
||||
|
||||
```plain
|
||||
src/
|
||||
└── main/
|
||||
├── java/
|
||||
│ ├── ast/ -> Defining the structure of the AST
|
||||
│ ├── bytecode/ -> Generate Java bytecode
|
||||
│ ├── main/ -> Running the compiler
|
||||
│ ├── parser/
|
||||
│ │ ├── astBuilder/ -> Builder creating the AST
|
||||
│ │ ├── generated/ -> Antlr generated grammar
|
||||
│ │ └── grammar/ -> Antlr grammar
|
||||
│ ├── semantic/ -> Running the semantic check
|
||||
│ └── visitor/ -> Visitor interface
|
||||
└── resources/
|
||||
test/
|
||||
└── java/
|
||||
│ ├── main/ -> MainTest, E2ETests, UtilityTests
|
||||
│ ├── parser/ -> Performs tests on the parser
|
||||
│ └── semantic/ -> Performs tests on the semantic check
|
||||
└── resources/ -> Ressources for running the Tests
|
||||
```
|
||||
|
||||
## Class-Diagramm AST
|
||||
|
||||
![AST Diagramm](ast.png)
|
||||
|
||||
## Used Tools
|
||||
|
||||
- [Maven 4.0](https://maven.apache.org/index.html)
|
||||
- Used for automating the build process and managing dependencies.
|
||||
- [ANTLR4 v.13.1](https://www.antlr.org/)
|
||||
- Used to parse the input Java code into the Abstract Syntax Tree.
|
||||
|
||||
|
||||
## How to run the compiler
|
||||
|
||||
## Download
|
||||
|
||||
```bash
|
@ -9,7 +9,6 @@ public class CalculationNode extends BinaryNode {
|
||||
public CalculationNode calculationExpression;
|
||||
public EnumLineOperator operator;
|
||||
public DotNode dotExpression;
|
||||
private ITypeNode typeNode;
|
||||
|
||||
public CalculationNode(CalculationNode calculationExpression, String operator, DotNode dotExpression) {
|
||||
this.calculationExpression = calculationExpression;
|
||||
|
@ -316,9 +316,13 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
||||
@Override
|
||||
public TypeCheckResult analyze(IfElseNode toCheck) {
|
||||
var resultIf = toCheck.ifStatement.accept(this);
|
||||
var resultElse = toCheck.elseStatement.accept(this);
|
||||
if(toCheck.elseStatement != null){
|
||||
var resultElse = toCheck.elseStatement.accept(this);
|
||||
return new TypeCheckResult(resultIf.isValid() && resultElse.isValid(), new BaseType(TypeEnum.VOID));
|
||||
}
|
||||
|
||||
return new TypeCheckResult(resultIf.isValid() && resultElse.isValid(), new BaseType(TypeEnum.VOID));
|
||||
|
||||
return new TypeCheckResult(resultIf.isValid(), new BaseType(TypeEnum.VOID));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -454,6 +458,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
||||
case PLUS, MINUS:
|
||||
if (calcRes.getType() instanceof BaseType calcType && dotRes.getType() instanceof BaseType dotType &&
|
||||
calcType.getTypeEnum().equals(TypeEnum.INT) && dotType.getTypeEnum().equals(TypeEnum.INT)) {
|
||||
calcNode.setType(new BaseType(TypeEnum.INT));
|
||||
return new TypeCheckResult(true, new BaseType(TypeEnum.INT));
|
||||
}
|
||||
break;
|
||||
@ -461,10 +466,12 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
||||
}
|
||||
|
||||
} else {
|
||||
calcNode.setType(calcNode.getType());
|
||||
return new TypeCheckResult(calcRes.isValid(), calcRes.getType());
|
||||
}
|
||||
} else if (calcNode.dotExpression != null) {
|
||||
var dotRes = calcNode.dotExpression.accept(this);
|
||||
calcNode.setType(dotRes.getType());
|
||||
return new TypeCheckResult(dotRes.isValid(), dotRes.getType());
|
||||
}
|
||||
return new TypeCheckResult(false, null);
|
||||
@ -473,7 +480,9 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
||||
@Override
|
||||
public TypeCheckResult analyze(DotNode toCheck) {
|
||||
if (toCheck.dotSubstractionExpression != null) {
|
||||
return toCheck.dotSubstractionExpression.accept(this);
|
||||
var result = toCheck.dotSubstractionExpression.accept(this);
|
||||
toCheck.setType(result.getType());
|
||||
return result;
|
||||
}
|
||||
return new TypeCheckResult(false, null);
|
||||
}
|
||||
@ -481,19 +490,35 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
||||
@Override
|
||||
public TypeCheckResult analyze(DotSubstractionNode toCheck) {
|
||||
if (toCheck.value != null) {
|
||||
return toCheck.value.accept(this);
|
||||
var result = toCheck.value.accept(this);
|
||||
toCheck.setType(result.getType());
|
||||
return result;
|
||||
} else if (toCheck.memberAccess != null) {
|
||||
return toCheck.memberAccess.accept(this);
|
||||
var result = toCheck.memberAccess.accept(this);
|
||||
toCheck.setType(result.getType());
|
||||
return result;
|
||||
} else if (toCheck.methodCall != null) {
|
||||
return toCheck.methodCall.accept(this);
|
||||
var result = toCheck.methodCall.accept(this);
|
||||
toCheck.setType(result.getType());
|
||||
return result;
|
||||
} else if (toCheck.identifier != null) {
|
||||
if (currentScope.contains(toCheck.identifier)) {
|
||||
return new TypeCheckResult(true, currentScope.getLocalVar(toCheck.identifier));
|
||||
var type = currentScope.getLocalVar(toCheck.identifier);
|
||||
toCheck.setType(type);
|
||||
return new TypeCheckResult(true, type);
|
||||
} else if (currentFields.get(toCheck.identifier) != null) {
|
||||
return new TypeCheckResult(true, currentFields.get(toCheck.identifier));
|
||||
var type = currentFields.get(toCheck.identifier);
|
||||
toCheck.setType(type);
|
||||
MemberAccessNode memberAccessNode = new MemberAccessNode(false);
|
||||
memberAccessNode.identifiers.add(currentClass.identifier);
|
||||
memberAccessNode.identifiers.add(toCheck.identifier);
|
||||
toCheck.memberAccess = memberAccessNode;
|
||||
return new TypeCheckResult(true, type);
|
||||
}
|
||||
} else if (toCheck.calculationExpression != null) {
|
||||
return toCheck.calculationExpression.accept(this);
|
||||
var result = toCheck.calculationExpression.accept(this);
|
||||
toCheck.setType(result.getType());
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -513,8 +538,8 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
||||
}
|
||||
break;
|
||||
case OR, AND:
|
||||
if (expResult.getType() instanceof BaseType expResultType && expResultType.getTypeEnum().equals(TypeEnum.INT) &&
|
||||
unaryResult.getType() instanceof BaseType unaryResultType && unaryResultType.getTypeEnum().equals(TypeEnum.INT)) {
|
||||
if (expResult.getType() instanceof BaseType expResultType && expResultType.getTypeEnum().equals(TypeEnum.BOOL) &&
|
||||
unaryResult.getType() instanceof BaseType unaryResultType && unaryResultType.getTypeEnum().equals(TypeEnum.BOOL)) {
|
||||
return new TypeCheckResult(true, new BaseType(TypeEnum.BOOL));
|
||||
} else {
|
||||
errors.add(new TypeMismatchException("Both types must be Boolean"));
|
||||
@ -538,13 +563,17 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
||||
|
||||
if (unary.identifier != null) {
|
||||
if (currentScope.contains(unary.identifier)) {
|
||||
return new TypeCheckResult(valid, currentScope.getLocalVar(unary.identifier));
|
||||
var type = currentScope.getLocalVar(unary.identifier);
|
||||
unary.setType(type);
|
||||
return new TypeCheckResult(valid, type);
|
||||
} else if (currentFields.get(unary.identifier) != null) {
|
||||
MemberAccessNode memberAccessNode = new MemberAccessNode(false);
|
||||
memberAccessNode.identifiers.add(currentClass.identifier);
|
||||
memberAccessNode.identifiers.add(unary.identifier);
|
||||
unary.memberAccess = memberAccessNode;
|
||||
return new TypeCheckResult(valid, currentFields.get(unary.identifier));
|
||||
var type = currentFields.get(unary.identifier);
|
||||
unary.setType(type);
|
||||
return new TypeCheckResult(valid,type );
|
||||
} else if (unary.statement != null) {
|
||||
var result = unary.statement.accept(this);
|
||||
unary.setType(result.getType());
|
||||
@ -554,15 +583,19 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
||||
}
|
||||
} else if (unary.statement != null) {
|
||||
var result = unary.statement.accept(this);
|
||||
unary.setType(result.getType());
|
||||
return new TypeCheckResult(result.isValid(), result.getType());
|
||||
} else if (unary.value != null) {
|
||||
var result = unary.value.accept(this);
|
||||
unary.setType(result.getType());
|
||||
return new TypeCheckResult(result.isValid(), result.getType());
|
||||
} else if (unary.memberAccess != null) {
|
||||
var result = unary.memberAccess.accept(this);
|
||||
unary.setType(result.getType());
|
||||
return new TypeCheckResult(result.isValid(), result.getType());
|
||||
} else if (unary.expression != null) {
|
||||
var result = unary.expression.accept(this);
|
||||
unary.setType(result.getType());
|
||||
return new TypeCheckResult(result.isValid(), result.getType());
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,6 @@ public class Node {
|
||||
public void main() {
|
||||
Compiler compiler = new Compiler();
|
||||
int i = compiler.add(5, 8);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,13 +10,7 @@ compile-javac:
|
||||
compile-raupenpiler:
|
||||
cd ../.. ; mvn -DskipTests install
|
||||
cd ../.. ; mvn exec:java -DgenJar=true -DgenClass=true -Dexec.mainClass="main.Main" -Dexec.args="'src/main/resources/input/CompilerInput.java' 'src/main/resources/output'"
|
||||
cp ../main/resources/output/CompilerInput.class .java/resources/output/raupenpiler
|
||||
|
||||
test: compile-javac compile-raupenpiler test-javac test-raupenpiler
|
||||
|
||||
test-javac:
|
||||
# gleich wie bei raupenpiler, kann ich ohne funktionierenden Compiler nicht testen
|
||||
|
||||
# cp ../main/resources/output/CompilerInput.class .java/resources/output/raupenpiler
|
||||
|
||||
test-raupenpiler:
|
||||
# move the compiled class to the test/main folder
|
||||
@ -29,17 +23,19 @@ test-raupenpiler:
|
||||
|
||||
|
||||
clean:
|
||||
# clean output folders
|
||||
# clean main output folders
|
||||
rm -f ../main/resources/output/*.class
|
||||
rm -f ../main/resources/output/*.jar
|
||||
# clean resources output folders
|
||||
rm -f ./resources/output/javac/*.class
|
||||
rm -f ./resources/output/raupenpiler/*.class
|
||||
rm -f ./resources/output/raupenpiler/*.jar
|
||||
# clean logs
|
||||
rm -f ../main/resources/logs/*.log
|
||||
rm -f ../main/resources/logs/*
|
||||
# clean test/java/main folders from .class files for End-to-End tests
|
||||
rm -f ./java/main/*.class
|
||||
# clean javac output from combinedFeatureTests
|
||||
rm -f ./resources/input/combinedFeatureTests/*.class
|
||||
rm -f ./resources/input/singleFeatureTests/*.class
|
||||
rm -f ./resources/input/typedAstFeatureTests/*.class
|
||||
# clean javac output from every folder
|
||||
rm -f ./resources/input/*/*.class
|
||||
# clean test results from maven surefire plugin
|
||||
rm -f ../../target/surefire-reports/*.txt
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
||||
package main;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.tools.JavaCompiler;
|
||||
@ -26,13 +27,17 @@ public class InputFilesTest {
|
||||
// Assert that the compiler is available
|
||||
assertNotNull(javac, "Java Compiler is not available");
|
||||
|
||||
File folder1 = new File("src/test/resources/input/combinedFeatureTests");
|
||||
File folder2 = new File("src/test/resources/input/singleFeatureTests");
|
||||
File folder3 = new File("src/test/resources/input/typedAstFeatureTests");
|
||||
File combinedFeatureTests = new File("src/test/resources/input/combinedFeatureTests");
|
||||
File endabgabeTests = new File("src/test/resources/input/endabgabeTests");
|
||||
File singleFeatureSemanticTests = new File("src/test/resources/input/singleFeatureSemanticTests");
|
||||
File singleFeatureTests = new File("src/test/resources/input/singleFeatureTests");
|
||||
File typedAstFeatureTests = new File("src/test/resources/input/typedAstFeatureTests");
|
||||
|
||||
List<File> files = getJavaFilesFromDirectory(folder1);
|
||||
files.addAll(getJavaFilesFromDirectory(folder2));
|
||||
files.addAll(getJavaFilesFromDirectory(folder3));
|
||||
List<File> files = getJavaFilesFromDirectory(combinedFeatureTests);
|
||||
// files.addAll(getJavaFilesFromDirectory(endabgabeTests));
|
||||
// files.addAll(getJavaFilesFromDirectory(singleFeatureSemanticTests));
|
||||
files.addAll(getJavaFilesFromDirectory(singleFeatureTests));
|
||||
// files.addAll(getJavaFilesFromDirectory(typedAstFeatureTests));
|
||||
|
||||
if (!files.isEmpty()) {
|
||||
for (File file : files) {
|
||||
@ -47,6 +52,133 @@ public class InputFilesTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void areCombinedFeatureTestsValid() throws IOException {
|
||||
// Get the system Java compiler
|
||||
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
|
||||
// Assert that the compiler is available
|
||||
assertNotNull(javac, "Java Compiler is not available");
|
||||
|
||||
File combinedFeatureTests = new File("src/test/resources/input/combinedFeatureTests");
|
||||
|
||||
List<File> files = getJavaFilesFromDirectory(combinedFeatureTests);
|
||||
|
||||
if (!files.isEmpty()) {
|
||||
for (File file : files) {
|
||||
// Try to compile the file and get the result
|
||||
int result = javac.run(null, null, null, file.getPath());
|
||||
|
||||
// Assert that the compilation succeeded (i.e., the result is zero)
|
||||
assertEquals(0, result, "Expected compilation success for " + file.getName());
|
||||
}
|
||||
} else {
|
||||
System.out.println("No files found in the directories.");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void areEndabgabeTestsActuallyValid() throws IOException {
|
||||
// Get the system Java compiler
|
||||
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
|
||||
// Assert that the compiler is available
|
||||
assertNotNull(javac, "Java Compiler is not available");
|
||||
|
||||
File endabgabeTests = new File("src/test/resources/input/endabgabeTests");
|
||||
|
||||
List<File> files = getJavaFilesFromDirectory(endabgabeTests);
|
||||
|
||||
if (!files.isEmpty()) {
|
||||
for (File file : files) {
|
||||
// Try to compile the file and get the result
|
||||
int result = javac.run(null, null, null, file.getPath());
|
||||
|
||||
// Assert that the compilation succeeded (i.e., the result is zero)
|
||||
assertEquals(0, result, "Expected compilation success for " + file.getName());
|
||||
}
|
||||
} else {
|
||||
System.out.println("No files found in the directories.");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void areSingleFeatureSemanticTestsActuallyValid() throws IOException {
|
||||
// Get the system Java compiler
|
||||
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
|
||||
// Assert that the compiler is available
|
||||
assertNotNull(javac, "Java Compiler is not available");
|
||||
|
||||
File singleFeatureSemanticTests = new File("src/test/resources/input/singleFeatureSemanticTests");
|
||||
|
||||
List<File> files = getJavaFilesFromDirectory(singleFeatureSemanticTests);
|
||||
|
||||
if (!files.isEmpty()) {
|
||||
for (File file : files) {
|
||||
// Try to compile the file and get the result
|
||||
int result = javac.run(null, null, null, file.getPath());
|
||||
|
||||
// Assert that the compilation succeeded (i.e., the result is zero)
|
||||
assertEquals(0, result, "Expected compilation success for " + file.getName());
|
||||
}
|
||||
} else {
|
||||
System.out.println("No files found in the directories.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void areSingleFeatureTestsActuallyValid() throws IOException {
|
||||
// Get the system Java compiler
|
||||
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
|
||||
// Assert that the compiler is available
|
||||
assertNotNull(javac, "Java Compiler is not available");
|
||||
|
||||
File singleFeatureTests = new File("src/test/resources/input/singleFeatureTests");
|
||||
|
||||
List<File> files = getJavaFilesFromDirectory(singleFeatureTests);
|
||||
|
||||
if (!files.isEmpty()) {
|
||||
for (File file : files) {
|
||||
// Try to compile the file and get the result
|
||||
int result = javac.run(null, null, null, file.getPath());
|
||||
|
||||
// Assert that the compilation succeeded (i.e., the result is zero)
|
||||
assertEquals(0, result, "Expected compilation success for " + file.getName());
|
||||
}
|
||||
} else {
|
||||
System.out.println("No files found in the directories.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
public void areTypedAstFeatureTestsActuallyValid() throws IOException {
|
||||
// Get the system Java compiler
|
||||
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
|
||||
// Assert that the compiler is available
|
||||
assertNotNull(javac, "Java Compiler is not available");
|
||||
|
||||
File typedAstFeatureTests = new File("src/test/resources/input/typedAstFeatureTests");
|
||||
|
||||
List<File> files = getJavaFilesFromDirectory(typedAstFeatureTests);
|
||||
|
||||
if (!files.isEmpty()) {
|
||||
for (File file : files) {
|
||||
// Try to compile the file and get the result
|
||||
int result = javac.run(null, null, null, file.getPath());
|
||||
|
||||
// Assert that the compilation succeeded (i.e., the result is zero)
|
||||
assertEquals(0, result, "Expected compilation success for " + file.getName());
|
||||
}
|
||||
} else {
|
||||
System.out.println("No files found in the directories.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This test method checks if invalid Java files fail to compile as expected.
|
||||
|
@ -1,28 +1,25 @@
|
||||
package main;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
import parser.ParserTest;
|
||||
import parser.ScannerTest;
|
||||
import semantic.EndToTypedAstTest;
|
||||
import semantic.SemanticTest;
|
||||
|
||||
/**
|
||||
* run every test: mvn test
|
||||
* Nutzen dieser Klasse: Eigentlich nicht vorhanden, in der Main gibts nichts zu testen
|
||||
* This class is a test suite that runs all the test classes in the project.
|
||||
* <p> run: <code> mvn test </code>
|
||||
* <p> check results in console or <code> target/surefire-reports </code>
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({
|
||||
InputFilesTest.class,
|
||||
ScannerTest.class,
|
||||
ParserTest.class,
|
||||
SemanticTest.class,
|
||||
EndToTypedAstTest.class
|
||||
})
|
||||
public class MainTest {
|
||||
@Test
|
||||
void test() {
|
||||
CharStream codeCharStream = null;
|
||||
try {
|
||||
codeCharStream = CharStreams.fromPath(Paths.get("src/main/test/resources/CompilerInput.java"));
|
||||
Main.compileFile(codeCharStream, "src/main/test/resources/output");
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error reading the file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
// This class remains empty, it is used only as a holder for the above annotations
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,145 +0,0 @@
|
||||
package main;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
public class ReflectionsTest {
|
||||
|
||||
@Test
|
||||
public void testSimpleJavaLexerClass() throws ClassNotFoundException, NoSuchMethodException {
|
||||
Class<?> clazz = Class.forName("parser.generated.SimpleJavaLexer");
|
||||
|
||||
// Class Name
|
||||
assertEquals("parser.generated.SimpleJavaLexer", clazz.getName());
|
||||
|
||||
// Constructors
|
||||
Constructor<?>[] actualConstructors = clazz.getDeclaredConstructors();
|
||||
assertTrue(actualConstructors.length > 0, "No constructors found");
|
||||
|
||||
Constructor<?> expectedConstructor = clazz.getConstructor(CharStream.class);
|
||||
|
||||
boolean constructorFound = false;
|
||||
for (Constructor<?> constructor : actualConstructors) {
|
||||
if (constructor.equals(expectedConstructor)) {
|
||||
constructorFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertTrue(constructorFound, "Expected constructor not found in actual constructors");
|
||||
|
||||
|
||||
|
||||
// Methods
|
||||
Method[] actualMethodNames = clazz.getDeclaredMethods();
|
||||
assertTrue(actualMethodNames.length > 0);
|
||||
Arrays.stream(actualMethodNames).forEach(method -> System.out.println("Method: " + method.getName()));
|
||||
|
||||
List<String> expectedMethodNames = Arrays.asList(
|
||||
"getTokenNames",
|
||||
"getVocabulary",
|
||||
"getGrammarFileName",
|
||||
"getRuleNames",
|
||||
"getSerializedATN",
|
||||
"getChannelNames",
|
||||
"getModeNames",
|
||||
"getATN",
|
||||
"makeRuleNames",
|
||||
"makeLiteralNames",
|
||||
"makeSymbolicNames"
|
||||
);
|
||||
|
||||
for (Method method : actualMethodNames) {
|
||||
assertTrue(expectedMethodNames.contains(method.getName()));
|
||||
}
|
||||
|
||||
for (String expectedMethodName : expectedMethodNames) {
|
||||
boolean methodFound = false;
|
||||
for (Method method : actualMethodNames) {
|
||||
if (method.getName().equals(expectedMethodName)) {
|
||||
methodFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertTrue(methodFound, "Expected method " + expectedMethodName + " not found in actual methods");
|
||||
}
|
||||
|
||||
|
||||
// Fields
|
||||
Field[] actualFieldNames = clazz.getDeclaredFields();
|
||||
assertTrue(actualFieldNames.length > 0);
|
||||
Arrays.stream(actualFieldNames).forEach(field -> System.out.println("Field: " + field.getName()));
|
||||
|
||||
List<String> expectedFieldNames = Arrays.asList(
|
||||
"_decisionToDFA",
|
||||
"_sharedContextCache",
|
||||
"channelNames",
|
||||
"modeNames",
|
||||
"ruleNames",
|
||||
"_LITERAL_NAMES",
|
||||
"_SYMBOLIC_NAMES",
|
||||
"VOCABULARY",
|
||||
"tokenNames",
|
||||
"_serializedATN",
|
||||
"_ATN"
|
||||
);
|
||||
|
||||
for (Field field : actualFieldNames) {
|
||||
assertTrue(expectedFieldNames.contains(field.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleJavaParserClass() throws ClassNotFoundException {
|
||||
Class<?> clazz = Class.forName("parser.generated.SimpleJavaParser");
|
||||
|
||||
// Class Name
|
||||
assertEquals("parser.generated.SimpleJavaParser", clazz.getName());
|
||||
|
||||
// Constructors
|
||||
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
|
||||
assertTrue(constructors.length > 0);
|
||||
|
||||
// Methods
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
assertTrue(methods.length > 0);
|
||||
Arrays.stream(methods).forEach(method -> System.out.println("Method: " + method.getName()));
|
||||
|
||||
// Fields
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
assertTrue(fields.length > 0);
|
||||
Arrays.stream(fields).forEach(field -> System.out.println("Field: " + field.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testASTBuilderClass() throws ClassNotFoundException {
|
||||
Class<?> clazz = Class.forName("parser.astBuilder.ASTBuilder");
|
||||
|
||||
// Class Name
|
||||
assertEquals("parser.astBuilder.ASTBuilder", clazz.getName());
|
||||
|
||||
// Constructors
|
||||
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
|
||||
assertTrue(constructors.length > 0);
|
||||
|
||||
// Methods
|
||||
Method[] methods = clazz.getDeclaredMethods();
|
||||
assertTrue(methods.length > 0);
|
||||
Arrays.stream(methods).forEach(method -> System.out.println("Method: " + method.getName()));
|
||||
|
||||
// Fields
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
assertTrue(fields.length > 0);
|
||||
Arrays.stream(fields).forEach(field -> System.out.println("Field: " + field.getName()));
|
||||
}
|
||||
|
||||
// Similarly, you can add tests for SemanticAnalyzer and ByteCodeGenerator
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package semantic;
|
||||
|
||||
import ast.ProgramNode;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import parser.astBuilder.ASTBuilder;
|
||||
import parser.generated.SimpleJavaLexer;
|
||||
import parser.generated.SimpleJavaParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class BeginnToTAST {
|
||||
|
||||
@Test
|
||||
public void FieldTests() {
|
||||
SemanticAnalyzer.clearAnalyzer();
|
||||
|
||||
CharStream codeCharStream = null;
|
||||
try {
|
||||
codeCharStream = CharStreams.fromPath(Paths.get("src/test/resources/input/johnsTests/FieldTests.java"));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
|
||||
ParseTree parseTree = parser.program(); // parse the input
|
||||
|
||||
/* ------------------------- AST builder -> AST ------------------------- */
|
||||
ASTBuilder astBuilder = new ASTBuilder();
|
||||
ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
|
||||
|
||||
var result = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
}
|
||||
|
||||
}
|
@ -281,6 +281,74 @@ public class EndToTypedAstTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void VariableCompare(){
|
||||
|
||||
ASTNode tast = SemanticHelper.generateTypedASTFrom("src/test/resources/input/singleFeatureSemanticTests/VariableCompare.java");
|
||||
|
||||
SemanticAnalyzer.generateTast(tast);
|
||||
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void IfExpressionInt(){
|
||||
|
||||
ASTNode tast = SemanticHelper.generateTypedASTFrom("src/test/resources/input/singleFeatureSemanticTests/IfExpressionInt.java");
|
||||
|
||||
SemanticAnalyzer.generateTast(tast);
|
||||
|
||||
assertFalse(SemanticAnalyzer.errors.isEmpty());
|
||||
assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SelectWrongMethodCauseParameter(){
|
||||
|
||||
ASTNode tast = SemanticHelper.generateTypedASTFrom("src/test/resources/input/singleFeatureSemanticTests/SelectWrongMethodCauseParameter.java");
|
||||
|
||||
SemanticAnalyzer.generateTast(tast);
|
||||
|
||||
assertFalse(SemanticAnalyzer.errors.isEmpty());
|
||||
assertInstanceOf(TypeMismatchException.class, SemanticAnalyzer.errors.getFirst());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SelectRightMethodCauseParameter(){
|
||||
|
||||
ASTNode tast = SemanticHelper.generateTypedASTFrom("src/test/resources/input/singleFeatureSemanticTests/SelectRightMethodCauseParameter.java");
|
||||
|
||||
SemanticAnalyzer.generateTast(tast);
|
||||
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void VariableCalculation(){
|
||||
|
||||
ASTNode tast = SemanticHelper.generateTypedASTFrom("src/test/resources/input/singleFeatureSemanticTests/VariableCalculation.java");
|
||||
|
||||
SemanticAnalyzer.generateTast(tast);
|
||||
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Expression(){
|
||||
|
||||
ASTNode tast = SemanticHelper.generateTypedASTFrom("src/test/resources/input/singleFeatureSemanticTests/Expression.java");
|
||||
|
||||
SemanticAnalyzer.generateTast(tast);
|
||||
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
|
||||
}
|
||||
|
||||
// ------------------ Helpers ------------------
|
||||
|
||||
/**
|
||||
|
@ -14,6 +14,9 @@ import java.io.IOException;
|
||||
|
||||
public class SemanticHelper {
|
||||
public static ASTNode generateTypedASTFrom(String filePath) {
|
||||
|
||||
SemanticAnalyzer.clearAnalyzer();
|
||||
|
||||
CharStream testFile = null;
|
||||
try {
|
||||
testFile = CharStreams.fromFileName(filePath);
|
||||
|
@ -1,5 +1,441 @@
|
||||
package semantic;
|
||||
|
||||
import ast.ASTNode;
|
||||
import ast.ClassNode;
|
||||
import ast.ProgramNode;
|
||||
import ast.expressions.IExpressionNode;
|
||||
import ast.expressions.unaryexpressions.MemberAccessNode;
|
||||
import ast.expressions.unaryexpressions.UnaryNode;
|
||||
import ast.members.ConstructorNode;
|
||||
import ast.members.FieldNode;
|
||||
import ast.members.MethodNode;
|
||||
import ast.parameters.ParameterNode;
|
||||
import ast.statementexpressions.AssignNode;
|
||||
import ast.statementexpressions.AssignableNode;
|
||||
import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode;
|
||||
import ast.statements.BlockNode;
|
||||
import ast.statements.ReturnNode;
|
||||
import ast.type.AccessModifierNode;
|
||||
import ast.type.EnumValueNode;
|
||||
import ast.type.ValueNode;
|
||||
import ast.type.type.BaseType;
|
||||
import ast.type.type.TypeEnum;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import parser.Helper;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class SemanticTest {
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
SemanticAnalyzer.clearAnalyzer();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Empty Class Test")
|
||||
public void emptyClassTest() {
|
||||
ClassNode emptyClass = Helper.generateEmptyClass("EmptyClass");
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(emptyClass);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@DisplayName("Multiple Empty Classes Test")
|
||||
public void multipleEmptyClassesTest() {
|
||||
ClassNode class1 = Helper.generateEmptyClass("MultipleClasses");
|
||||
ClassNode class2 = Helper.generateEmptyClass("TestClass2");
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(class1);
|
||||
abstractSyntaxTree.addClass(class2);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@DisplayName("Empty Class Test with Constructor")
|
||||
public void emptyClassWithConstructorTest() {
|
||||
ClassNode class1 = Helper.generateEmptyClass("EmptyClassWithConstructor");
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(class1);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Field Test")
|
||||
public void fieldTest() {
|
||||
ClassNode class1 = Helper.generateEmptyClass("Field");
|
||||
class1.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"));
|
||||
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(class1);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Field Test with Accessmodifier")
|
||||
public void fieldTestWithModifier() {
|
||||
ClassNode class1 = Helper.generateEmptyClass("FieldWithAccessModifier");
|
||||
class1.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"));
|
||||
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(class1);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Comments Ignore Test")
|
||||
public void commentsIgnoreTest() {
|
||||
ClassNode class1 = Helper.generateEmptyClass("Comments");
|
||||
class1.addMember(new FieldNode(new AccessModifierNode("private"), new BaseType(TypeEnum.INT), "a"));
|
||||
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(class1);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Constructor Parameter Test")
|
||||
public void constructorParameterTest() {
|
||||
BlockNode block = new BlockNode();
|
||||
block.addStatement(new ReturnNode(null));
|
||||
ConstructorNode constructor = new ConstructorNode("public", "ConstructorParameter", block);
|
||||
constructor.addParameter(new ParameterNode(new BaseType(TypeEnum.INT), "a"));
|
||||
constructor.addParameter(new ParameterNode(new BaseType(TypeEnum.INT), "b"));
|
||||
|
||||
ClassNode class1 = new ClassNode("public", "ConstructorParameter");
|
||||
class1.addMember(constructor);
|
||||
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(class1);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("This Dot Test")
|
||||
public void thisDotTest() {
|
||||
BlockNode block = new BlockNode();
|
||||
MemberAccessNode memberAccess = new MemberAccessNode(true);
|
||||
memberAccess.addIdentifier("a");
|
||||
|
||||
AssignableNode assignable = new AssignableNode(memberAccess);
|
||||
|
||||
ValueNode value = new ValueNode(EnumValueNode.INT_VALUE, "1");
|
||||
IExpressionNode expression = new UnaryNode(value);
|
||||
|
||||
block.addStatement(new AssignNode(assignable, expression));
|
||||
block.addStatement(new ReturnNode(null));
|
||||
ConstructorNode constructor = new ConstructorNode("public", "ThisDot", block);
|
||||
|
||||
ClassNode class1 = new ClassNode("public", "ThisDot");
|
||||
class1.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"));
|
||||
class1.addMember(constructor);
|
||||
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(class1);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Constructor This Dot Test")
|
||||
public void constructorThisDotTest() {
|
||||
BlockNode block = new BlockNode();
|
||||
MemberAccessNode memberAccess = new MemberAccessNode(true);
|
||||
memberAccess.addIdentifier("a");
|
||||
|
||||
AssignableNode assignable = new AssignableNode(memberAccess);
|
||||
|
||||
IExpressionNode expression = new UnaryNode("a");
|
||||
|
||||
block.addStatement(new AssignNode(assignable, expression));
|
||||
block.addStatement(new ReturnNode(null));
|
||||
ConstructorNode constructor = new ConstructorNode("public", "ConstructorThisDot", block);
|
||||
constructor.addParameter(new ParameterNode(new BaseType(TypeEnum.INT), "a"));
|
||||
|
||||
ClassNode class1 = new ClassNode("public", "ConstructorThisDot");
|
||||
class1.addMember(new FieldNode(new AccessModifierNode("private"), new BaseType(TypeEnum.INT), "a"));
|
||||
class1.addMember(constructor);
|
||||
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(class1);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Void Methoden Test")
|
||||
public void voidMethodenTest() {
|
||||
ClassNode class1 = Helper.generateEmptyClass("VoidMethod");
|
||||
BlockNode block = new BlockNode();
|
||||
block.addStatement(new ReturnNode(null));
|
||||
class1.addMember(new MethodNode("public", null, true, "test", block));
|
||||
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(class1);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Constructor Method call Test")
|
||||
public void constructorMethodCallTest() {
|
||||
BlockNode blockCon = new BlockNode();
|
||||
MemberAccessNode memberAccess = new MemberAccessNode(true);
|
||||
memberAccess.addIdentifier("a");
|
||||
|
||||
AssignableNode assignable = new AssignableNode(memberAccess);
|
||||
|
||||
IExpressionNode expression = new UnaryNode(new MethodCallNode(null, "testMethod"));
|
||||
|
||||
blockCon.addStatement(new AssignNode(assignable, expression));
|
||||
blockCon.addStatement(new ReturnNode(null));
|
||||
ConstructorNode constructor = new ConstructorNode("public", "ConstructorMethodCall", blockCon);
|
||||
|
||||
BlockNode blockMethod = new BlockNode();
|
||||
blockMethod.addStatement(new ReturnNode(new UnaryNode(new ValueNode(EnumValueNode.INT_VALUE, "1"))));
|
||||
MethodNode method = new MethodNode("public", new BaseType(TypeEnum.INT), false, "testMethod", blockMethod);
|
||||
|
||||
ClassNode class1 = new ClassNode("public", "ConstructorMethodCall");
|
||||
class1.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"));
|
||||
class1.addMember(constructor);
|
||||
class1.addMember(method);
|
||||
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(class1);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Constructor Method call Parameters Test")
|
||||
public void constructorMethodCallParametersTest() {
|
||||
BlockNode blockCon = new BlockNode();
|
||||
MemberAccessNode memberAccess = new MemberAccessNode(true);
|
||||
memberAccess.addIdentifier("a");
|
||||
|
||||
AssignableNode assignable = new AssignableNode(memberAccess);
|
||||
|
||||
MethodCallNode methodCall = new MethodCallNode(null, "testMethod");
|
||||
methodCall.addExpression(new UnaryNode("a"));
|
||||
IExpressionNode expression = new UnaryNode(methodCall);
|
||||
|
||||
blockCon.addStatement(new AssignNode(assignable, expression));
|
||||
blockCon.addStatement(new ReturnNode(null));
|
||||
ConstructorNode constructor = new ConstructorNode("public", "ConstructorMethodCallParameters", blockCon);
|
||||
constructor.addParameter(new ParameterNode(new BaseType(TypeEnum.INT), "a"));
|
||||
|
||||
BlockNode blockMethod = new BlockNode();
|
||||
blockMethod.addStatement(new ReturnNode(new UnaryNode("a")));
|
||||
MethodNode method = new MethodNode("public", new BaseType(TypeEnum.INT), false, "testMethod", blockMethod);
|
||||
method.addParameter(new ParameterNode(new BaseType(TypeEnum.INT), "a"));
|
||||
|
||||
ClassNode class1 = new ClassNode("public", "ConstructorMethodCallParameters");
|
||||
class1.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"));
|
||||
class1.addMember(constructor);
|
||||
class1.addMember(method);
|
||||
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(class1);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Char Test")
|
||||
public void charTest() {
|
||||
BlockNode blockCon = new BlockNode();
|
||||
MemberAccessNode memberAccess = new MemberAccessNode(true);
|
||||
memberAccess.addIdentifier("a");
|
||||
|
||||
AssignableNode assignable = new AssignableNode(memberAccess);
|
||||
|
||||
MethodCallNode methodCall = new MethodCallNode(null, "testMethod");
|
||||
methodCall.addExpression(new UnaryNode("a"));
|
||||
IExpressionNode expression = new UnaryNode(methodCall);
|
||||
|
||||
blockCon.addStatement(new AssignNode(assignable, expression));
|
||||
blockCon.addStatement(new ReturnNode(null));
|
||||
ConstructorNode constructor = new ConstructorNode("public", "Char", blockCon);
|
||||
constructor.addParameter(new ParameterNode(new BaseType(TypeEnum.CHAR), "a"));
|
||||
|
||||
BlockNode blockMethod = new BlockNode();
|
||||
blockMethod.addStatement(new ReturnNode(new UnaryNode("a")));
|
||||
MethodNode method = new MethodNode("public", new BaseType(TypeEnum.CHAR), false, "testMethod", blockMethod);
|
||||
method.addParameter(new ParameterNode(new BaseType(TypeEnum.CHAR), "a"));
|
||||
|
||||
ClassNode class1 = new ClassNode("public", "Char");
|
||||
class1.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.CHAR), "a"));
|
||||
class1.addMember(constructor);
|
||||
class1.addMember(method);
|
||||
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(class1);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Null Test")
|
||||
public void nullTest() {
|
||||
BlockNode blockCon = new BlockNode();
|
||||
MemberAccessNode memberAccess = new MemberAccessNode(true);
|
||||
memberAccess.addIdentifier("a");
|
||||
|
||||
AssignableNode assignable = new AssignableNode(memberAccess);
|
||||
|
||||
blockCon.addStatement(new AssignNode(assignable, new UnaryNode(new ValueNode(EnumValueNode.NULL_VALUE, "null"))));
|
||||
blockCon.addStatement(new ReturnNode(null));
|
||||
ConstructorNode constructor = new ConstructorNode("public", "Null", blockCon);
|
||||
|
||||
ClassNode class1 = new ClassNode("public", "Null");
|
||||
class1.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"));
|
||||
class1.addMember(constructor);
|
||||
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(class1);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Self Reference Test")
|
||||
public void selfReferenceTest() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Variable Compare Test")
|
||||
public void variableCompareTest() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Variable Calculation Test")
|
||||
public void variableCalculationTest() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Main Method Test")
|
||||
public void mainMethodTest() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("While Test")
|
||||
public void whileTest() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Do While Test")
|
||||
public void doWhileTest() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("For Test")
|
||||
public void forTest() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Increment Test")
|
||||
public void incrementTest() {
|
||||
ClassNode classNode = Helper.generateEmptyClass("Increment");
|
||||
classNode.addMember(new FieldNode(new AccessModifierNode("public"), new BaseType(TypeEnum.INT), "a"));
|
||||
|
||||
ProgramNode abstractSyntaxTree = new ProgramNode();
|
||||
abstractSyntaxTree.addClass(classNode);
|
||||
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
for (Exception runtimeException : SemanticAnalyzer.errors) {
|
||||
runtimeException.printStackTrace();
|
||||
}
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
assertNotNull(typedAst);
|
||||
}
|
||||
}
|
25
src/test/resources/input/endabgabeTests/Car.java
Normal file
25
src/test/resources/input/endabgabeTests/Car.java
Normal file
@ -0,0 +1,25 @@
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
Car myCar = new Car(2020);
|
||||
int tires = 0;
|
||||
int year = myCar.getYear();
|
||||
|
||||
if (year == 2020) {
|
||||
tires = 4;
|
||||
} else {
|
||||
tires = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Car {
|
||||
private int year;
|
||||
|
||||
public Car(int year) {
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return this.year;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
public class ControlStructures {
|
||||
|
||||
public int sum(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
public cahr checkNumber(int num) {
|
||||
if (num > 0) {
|
||||
return "p";
|
||||
} else if (num < 0) {
|
||||
return "n";
|
||||
} else {
|
||||
return "z";
|
||||
}
|
||||
}
|
||||
|
||||
public void printNumbersUpTo(int limit) {
|
||||
int even = 0;
|
||||
int uneven = 0;
|
||||
int i = 0;
|
||||
while (i < limit) {
|
||||
if (i % 2 == 0) {
|
||||
even++;
|
||||
} else {
|
||||
uneven = uneven + 1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ControlStructures cs = new ControlStructures();
|
||||
cs.printNumbersUpTo(5);
|
||||
int result = cs.sum(5, 5);
|
||||
}
|
||||
}
|
11
src/test/resources/input/endabgabeTests/Person.java
Normal file
11
src/test/resources/input/endabgabeTests/Person.java
Normal file
@ -0,0 +1,11 @@
|
||||
public class Person {
|
||||
private int age;
|
||||
|
||||
public Person(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return this.age;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
class VariableCompare{
|
||||
|
||||
void trueMethod(boolean a, int c) {
|
||||
if(a && c == 10){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
// @expected: TypeMismatchException
|
||||
public class Test{
|
||||
|
||||
public void test(int x){
|
@ -0,0 +1,22 @@
|
||||
// @expected: TypeMismatchException
|
||||
public class Test{
|
||||
|
||||
public int i;
|
||||
public boolean b;
|
||||
|
||||
public int test(){
|
||||
|
||||
return test(b);
|
||||
|
||||
}
|
||||
|
||||
public void test(int a){
|
||||
|
||||
}
|
||||
|
||||
public int test(boolean bool){
|
||||
int ret = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
class VariableCalculation{
|
||||
|
||||
int aPlusB(int a, int b){
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int aMinusB(int a, int b){
|
||||
return a - b;
|
||||
}
|
||||
|
||||
int aTimeB(int a, int b){
|
||||
return a * b;
|
||||
}
|
||||
|
||||
int aDivB(int a, int b){
|
||||
return a / b;
|
||||
}
|
||||
|
||||
int complexCalc (int a, int b){
|
||||
return a * b / 1 * 3;
|
||||
}
|
||||
|
||||
boolean aSmallerB (int a, int b){
|
||||
return a < b;
|
||||
}
|
||||
|
||||
boolean aGreaterB (int a, int b){
|
||||
return a > b;
|
||||
}
|
||||
|
||||
boolean aEqualsB (int a, int b){
|
||||
return a == b;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
class VariableCompare{
|
||||
|
||||
boolean trueMethod() {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean falseMethod(){
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean trueAndTrueMethod(){
|
||||
return true && true;
|
||||
}
|
||||
|
||||
boolean trueAndFalseMethod(){
|
||||
return true && false;
|
||||
}
|
||||
|
||||
boolean falseAndFalseMethod(){
|
||||
return false && false;
|
||||
}
|
||||
|
||||
boolean trueOrTrueMethod(){
|
||||
return true || true;
|
||||
}
|
||||
|
||||
boolean falseOrFalseMethod(){
|
||||
return false || false;
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user