E2E Running
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run
Other tests and make refactored
This commit is contained in:
parent
2934872457
commit
f7a4e65093
18
pom.xml
18
pom.xml
@ -35,6 +35,12 @@
|
|||||||
<version>5.11.0-M2</version>
|
<version>5.11.0-M2</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.13.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.antlr</groupId>
|
<groupId>org.antlr</groupId>
|
||||||
<artifactId>antlr4-runtime</artifactId>
|
<artifactId>antlr4-runtime</artifactId>
|
||||||
@ -56,18 +62,6 @@
|
|||||||
<version>3.26.0</version>
|
<version>3.26.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.mockito</groupId>
|
|
||||||
<artifactId>mockito-core</artifactId>
|
|
||||||
<version>5.11.0</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<version>4.13.1</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
77
readme.md
Normal file
77
readme.md
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# "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/
|
||||||
|
│ ├── parser/ -> Performs tests on the parser
|
||||||
|
│ └── semantic/
|
||||||
|
└── resources/ -> Ressources for running the Tests
|
||||||
|
├──input
|
||||||
|
│ ├── combinedFeatureTests
|
||||||
|
│ ├── endabgabeTests
|
||||||
|
│ ├── failureTests
|
||||||
|
│ ├── singleFeatureSemanticTests
|
||||||
|
│ ├── singleFeatureTests
|
||||||
|
│ ├── typedAstExceptionsTests
|
||||||
|
│ └── typedAstFeatureTests
|
||||||
|
└──output
|
||||||
|
├── javac
|
||||||
|
└── raupenpiler
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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
|
@ -29,11 +29,13 @@ test-raupenpiler:
|
|||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
# clean output folders
|
# clean main output folders
|
||||||
rm -f ../main/resources/output/*.class
|
rm -f ../main/resources/output/*.class
|
||||||
rm -f ../main/resources/output/*.jar
|
rm -f ../main/resources/output/*.jar
|
||||||
|
# clean resources output folders
|
||||||
rm -f ./resources/output/javac/*.class
|
rm -f ./resources/output/javac/*.class
|
||||||
rm -f ./resources/output/raupenpiler/*.class
|
rm -f ./resources/output/raupenpiler/*.class
|
||||||
|
rm -f ./resources/output/raupenpiler/*.jar
|
||||||
# clean logs
|
# clean logs
|
||||||
rm -f ../main/resources/logs/*.log
|
rm -f ../main/resources/logs/*.log
|
||||||
# clean test/java/main folders from .class files for End-to-End tests
|
# clean test/java/main folders from .class files for End-to-End tests
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
|||||||
package main;
|
package main;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import javax.tools.JavaCompiler;
|
import javax.tools.JavaCompiler;
|
||||||
@ -51,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.
|
* This test method checks if invalid Java files fail to compile as expected.
|
||||||
|
@ -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
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user