Compare commits
23 Commits
Tests
...
code-gener
Author | SHA1 | Date | |
---|---|---|---|
4f688474a2 | |||
5fc3927c5d | |||
a4d08aacb8 | |||
8eba420d48 | |||
fbff03c3d7 | |||
721e1caa79 | |||
6d3e1f859e | |||
f6b34bf70b | |||
430d551f7d | |||
8e0d627505 | |||
6b6051cad8 | |||
1f8e045b1e | |||
ceb1231632 | |||
|
31929878b0 | ||
|
ea97f34398 | ||
|
2f7b310254 | ||
|
9b8155ebab | ||
|
4775c3f47e | ||
|
2e3a7850a4 | ||
|
d925a3258c | ||
|
fb5372bc8f | ||
|
f29be4fd8c | ||
|
34bb86c7f4 |
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
|
||||
|
||||

|
||||
|
||||
## 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
|
@@ -7,7 +7,7 @@ import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class DecrementNode implements IStatementExpressionNode {
|
||||
public class DecrementNode implements IStatementExpressionNode, Visitable {
|
||||
public CrementType crementType;
|
||||
public AssignableNode assignableExpression;
|
||||
|
||||
@@ -20,4 +20,9 @@ public class DecrementNode implements IStatementExpressionNode {
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
@@ -5,8 +5,9 @@ import ast.statementexpressions.IStatementExpressionNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class IncrementNode implements IStatementExpressionNode {
|
||||
public class IncrementNode implements IStatementExpressionNode, Visitable {
|
||||
public CrementType crementType;
|
||||
public AssignableNode assignableExpression;
|
||||
|
||||
@@ -19,4 +20,9 @@ public class IncrementNode implements IStatementExpressionNode {
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
@@ -22,11 +22,6 @@ public class ChainedMethodNode implements ASTNode, Visitable {
|
||||
expressions.add(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return null;
|
||||
|
@@ -27,7 +27,7 @@ public class ClassCodeGen implements ClassVisitor {
|
||||
private boolean generateClassFiles;
|
||||
|
||||
public ClassCodeGen(JarOutputStream jarOutputStream, String outputDirectory, boolean generateJar, boolean generateClassFiles) {
|
||||
mapper = new Mapper();
|
||||
this.mapper = new Mapper();
|
||||
this.jarOutputStream = jarOutputStream;
|
||||
this.outputDirectory = outputDirectory;
|
||||
this.generateJar = generateJar;
|
||||
|
@@ -3,6 +3,7 @@ package bytecode;
|
||||
import ast.parameters.ParameterNode;
|
||||
import ast.type.*;
|
||||
import ast.type.type.BaseType;
|
||||
import ast.type.type.ITypeNode;
|
||||
import ast.type.type.ReferenceType;
|
||||
import ast.type.type.TypeEnum;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -24,7 +25,7 @@ public class Mapper {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String generateMethodDescriptor(BaseType type, List<ParameterNode> parameters) {
|
||||
public String generateMethodDescriptor(ITypeNode type, List<ParameterNode> parameters) {
|
||||
String descriptor = "(";
|
||||
for (ParameterNode parameterNode : parameters) {
|
||||
if(parameterNode.type instanceof BaseType) {
|
||||
@@ -35,7 +36,11 @@ public class Mapper {
|
||||
}
|
||||
}
|
||||
descriptor += ")";
|
||||
descriptor += getTypeChar(type);
|
||||
if(type instanceof BaseType) {
|
||||
descriptor += getTypeChar((BaseType) type);
|
||||
} else if(type instanceof ReferenceType) {
|
||||
descriptor += "L" + ((ReferenceType) type).getIdentifier() +";";
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
|
@@ -14,9 +14,7 @@ import ast.statementexpressions.NewDeclarationNode;
|
||||
import ast.statementexpressions.crementexpressions.CrementType;
|
||||
import ast.statementexpressions.crementexpressions.DecrementNode;
|
||||
import ast.statementexpressions.crementexpressions.IncrementNode;
|
||||
import ast.statementexpressions.methodcallstatementnexpressions.ChainedMethodNode;
|
||||
import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode;
|
||||
import ast.statementexpressions.methodcallstatementnexpressions.TargetNode;
|
||||
import ast.statements.*;
|
||||
import ast.type.ValueNode;
|
||||
import ast.type.type.BaseType;
|
||||
@@ -71,9 +69,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
|
||||
// Visit all statements
|
||||
for (IStatementNode statementNode : constructorNode.block.statements) {
|
||||
if (statementNode != null) {
|
||||
statementNode.accept(this);
|
||||
}
|
||||
statementNode.accept(this);
|
||||
}
|
||||
|
||||
methodVisitor.visitMaxs(0, 0);
|
||||
@@ -105,7 +101,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
public void visit(MethodNode methodNode) {
|
||||
methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.accesModifier),
|
||||
methodNode.getIdentifier(),
|
||||
mapper.generateMethodDescriptor((BaseType) methodNode.getType(), methodNode.parameters),
|
||||
mapper.generateMethodDescriptor(methodNode.getType(), methodNode.parameters),
|
||||
null,
|
||||
null);
|
||||
|
||||
@@ -241,7 +237,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
nonCalculationNode.unaryExpression.accept(this);
|
||||
nonCalculationNode.expression.accept(this);
|
||||
if (nonCalculationNode.unaryExpression.getType() instanceof BaseType && nonCalculationNode.expression.getType() instanceof BaseType) {
|
||||
methodVisitor.visitJumpInsn(IF_ACMPEQ, labelFalse);
|
||||
methodVisitor.visitJumpInsn(IF_ICMPEQ, labelFalse);
|
||||
} else {
|
||||
methodVisitor.visitJumpInsn(IF_ACMPEQ, labelFalse);
|
||||
}
|
||||
@@ -266,9 +262,17 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
@Override
|
||||
public void visit(MemberAccessNode memberAccessNode) {
|
||||
// Only used to get, not to put
|
||||
if (memberAccessNode.thisExpr) { // Field
|
||||
// methodVisitor.visitFieldInsn(GETFIELD, memberAccessNode.identifiers.get(0), memberAccessNode.identifiers.get(1), );
|
||||
} else { // Object Attribut
|
||||
int localVarIndex = localVariables.indexOf("memberAccessNode.identifier"); // TODO
|
||||
if (localVarIndex >= 0) { // local var object
|
||||
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
||||
} else { // this field
|
||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||
}
|
||||
|
||||
if (memberAccessNode.getTypeNode() instanceof BaseType) {
|
||||
methodVisitor.visitFieldInsn(GETFIELD, memberAccessNode.identifiers.get(0), memberAccessNode.identifiers.get(1), mapper.getTypeChar((BaseType) memberAccessNode.getTypeNode()));
|
||||
} else if (memberAccessNode.getTypeNode() instanceof ReferenceType) {
|
||||
methodVisitor.visitFieldInsn(GETFIELD, memberAccessNode.identifiers.get(0), memberAccessNode.identifiers.get(1), "L" + ((ReferenceType) memberAccessNode.getTypeNode()).getIdentifier() + ";");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,6 +335,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
// else if statements
|
||||
methodVisitor.visitJumpInsn(IFEQ, elseIfLabels[0]);
|
||||
}
|
||||
|
||||
ifElseNode.ifStatement.block.accept(this); // accept if block
|
||||
|
||||
Label endLabel = new Label();
|
||||
@@ -362,22 +367,17 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
if (localVariableDeclarationNode.expression != null) {
|
||||
// Process expression
|
||||
localVariableDeclarationNode.expression.accept(this);
|
||||
// Store result of expression in variable
|
||||
if (localVariables.contains(localVariableDeclarationNode.identifier)) {
|
||||
if (localVariableDeclarationNode.type instanceof BaseType) {
|
||||
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
||||
} else if (localVariableDeclarationNode.type instanceof ReferenceType) {
|
||||
methodVisitor.visitVarInsn(ASTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
||||
}
|
||||
} else {
|
||||
// add local var to list if not in list
|
||||
if (!localVariables.contains(localVariableDeclarationNode.identifier)) {
|
||||
localVariables.add(localVariableDeclarationNode.identifier);
|
||||
if (localVariableDeclarationNode.type instanceof BaseType) {
|
||||
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
||||
} else if (localVariableDeclarationNode.type instanceof ReferenceType) {
|
||||
methodVisitor.visitVarInsn(ASTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
||||
}
|
||||
}
|
||||
if (localVariableDeclarationNode.type instanceof BaseType) {
|
||||
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
||||
} else if (localVariableDeclarationNode.type instanceof ReferenceType) {
|
||||
methodVisitor.visitVarInsn(ASTORE, localVariables.indexOf(localVariableDeclarationNode.identifier));
|
||||
}
|
||||
} else {
|
||||
// Local var declaration
|
||||
if (!localVariables.contains(localVariableDeclarationNode.identifier)) {
|
||||
localVariables.add(localVariableDeclarationNode.identifier);
|
||||
}
|
||||
@@ -386,40 +386,106 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(AssignNode assignNode) {
|
||||
// Process expression
|
||||
if (assignNode.assignable.memberAccess != null) { // this / object
|
||||
if (assignNode.expression instanceof IncrementNode) {
|
||||
if (((IncrementNode) assignNode.expression).crementType.equals(CrementType.PREFIX)) { // ++i
|
||||
fieldOrObjectVarPrefixCrementAssign(assignNode);
|
||||
} else { // i++
|
||||
fieldOrObjectVarSuffixCrementAssign(assignNode);
|
||||
}
|
||||
} else if (assignNode.expression instanceof DecrementNode) {
|
||||
if (((DecrementNode) assignNode.expression).crementType.equals(CrementType.PREFIX)) {
|
||||
fieldOrObjectVarPrefixCrementAssign(assignNode);
|
||||
} else {
|
||||
fieldOrObjectVarSuffixCrementAssign(assignNode);
|
||||
}
|
||||
} else {
|
||||
assignFieldOrObjectVar(assignNode);
|
||||
}
|
||||
} else { // local var
|
||||
if (assignNode.expression instanceof IncrementNode || assignNode.expression instanceof DecrementNode) {
|
||||
localVarCrementAssign(assignNode);
|
||||
} else {
|
||||
assignNode.expression.accept(this);
|
||||
assignLocalVar(assignNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void localVarCrementAssign(AssignNode assignNode) {
|
||||
if (assignNode.expression instanceof IncrementNode) {
|
||||
IncrementNode incrementNode = (IncrementNode) assignNode.expression;
|
||||
if (incrementNode.crementType.equals(CrementType.PREFIX)) { // ++i
|
||||
methodVisitor.visitIincInsn(localVariables.indexOf(incrementNode.assignableExpression.identifier), 1);
|
||||
assign(assignNode);
|
||||
} else if (incrementNode.crementType.equals(CrementType.SUFFIX)) { // Suffix: i++
|
||||
assign(assignNode);
|
||||
methodVisitor.visitIincInsn(localVariables.indexOf(incrementNode.assignableExpression.identifier), 1);
|
||||
incrementNode.accept(this);
|
||||
assignLocalVar(assignNode);
|
||||
} else { // i++
|
||||
loadBeforeCrement(assignNode);
|
||||
assignLocalVar(assignNode);
|
||||
incrementNode.accept(this);
|
||||
}
|
||||
} else if (assignNode.expression instanceof DecrementNode) {
|
||||
DecrementNode decrementNode = (DecrementNode) assignNode.expression;
|
||||
if (decrementNode.crementType.equals(CrementType.PREFIX)) {
|
||||
methodVisitor.visitIincInsn(localVariables.indexOf(decrementNode.assignableExpression.identifier), -1);
|
||||
assign(assignNode);
|
||||
} else if (decrementNode.crementType.equals(CrementType.SUFFIX)) {
|
||||
assign(assignNode);
|
||||
methodVisitor.visitIincInsn(localVariables.indexOf(decrementNode.assignableExpression.identifier), 1);
|
||||
decrementNode.accept(this);
|
||||
assignLocalVar(assignNode);
|
||||
} else {
|
||||
loadBeforeCrement(assignNode);
|
||||
assignLocalVar(assignNode);
|
||||
decrementNode.accept(this);
|
||||
}
|
||||
} else {
|
||||
assignNode.expression.accept(this);
|
||||
assign(assignNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void assign(AssignNode assignNode) {
|
||||
if (assignNode.assignable.memberAccess.thisExpr) {
|
||||
assignField(assignNode);
|
||||
private void fieldOrObjectVarPrefixCrementAssign(AssignNode assignNode) {
|
||||
int localVarIndex = localVariables.indexOf(assignNode.assignable.identifier);
|
||||
if(localVarIndex >= 0) { // object
|
||||
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
||||
} else if(assignNode.assignable.memberAccess.thisExpr) { // field
|
||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||
} else {
|
||||
assignLocalVar(assignNode);
|
||||
localVariables.add(assignNode.assignable.identifier);
|
||||
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||
}
|
||||
|
||||
assignNode.expression.accept(this);
|
||||
methodVisitor.visitInsn(DUP_X1);
|
||||
|
||||
if (assignNode.expression instanceof BaseType) {
|
||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) assignNode.expression.getType()));
|
||||
} else if (assignNode.expression instanceof ReferenceType) {
|
||||
ReferenceType referenceType = (ReferenceType) assignNode.expression.getType();
|
||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), "L" + referenceType.getIdentifier() + ";");
|
||||
}
|
||||
}
|
||||
|
||||
private void fieldOrObjectVarSuffixCrementAssign(AssignNode assignNode) {
|
||||
int localVarIndex = localVariables.indexOf(assignNode.assignable.identifier);
|
||||
if(localVarIndex >= 0) { // object
|
||||
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
||||
} else if(assignNode.assignable.memberAccess.thisExpr) { // field
|
||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||
} else {
|
||||
localVariables.add(assignNode.assignable.identifier);
|
||||
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||
}
|
||||
|
||||
loadBeforeCrement(assignNode);
|
||||
|
||||
if (assignNode.expression instanceof BaseType) {
|
||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) assignNode.expression.getType()));
|
||||
} else if (assignNode.expression instanceof ReferenceType) {
|
||||
ReferenceType referenceType = (ReferenceType) assignNode.expression.getType();
|
||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), "L" + referenceType.getIdentifier() + ";");
|
||||
}
|
||||
|
||||
assignNode.expression.accept(this);
|
||||
}
|
||||
|
||||
private void assignLocalVar(AssignNode assignNode) {
|
||||
methodVisitor.visitInsn(DUP);
|
||||
if (!localVariables.contains(assignNode.assignable.identifier)) {
|
||||
localVariables.add(assignNode.assignable.identifier);
|
||||
}
|
||||
if (assignNode.expression instanceof BaseType) {
|
||||
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(assignNode.assignable.identifier));
|
||||
} else if (assignNode.expression instanceof ReferenceType) {
|
||||
@@ -427,12 +493,105 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private void assignField(AssignNode assignNode) {
|
||||
private void assignFieldOrObjectVar(AssignNode assignNode) {
|
||||
int localVarIndex = localVariables.indexOf(assignNode.assignable.identifier);
|
||||
if (localVarIndex >= 0) { // object
|
||||
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
||||
} else if (assignNode.assignable.memberAccess.thisExpr) { // this
|
||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||
} else {
|
||||
localVariables.add(assignNode.assignable.identifier);
|
||||
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||
}
|
||||
|
||||
assignNode.expression.accept(this);
|
||||
methodVisitor.visitInsn(DUP_X1);
|
||||
|
||||
if (assignNode.expression instanceof BaseType) {
|
||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) assignNode.expression.getType()));
|
||||
} else if (assignNode.expression instanceof ReferenceType) {
|
||||
ReferenceType referenceType = (ReferenceType) assignNode.expression.getType();
|
||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), "L"+referenceType.getIdentifier()+";");
|
||||
methodVisitor.visitFieldInsn(PUTFIELD, assignNode.assignable.memberAccess.identifiers.get(0), assignNode.assignable.memberAccess.identifiers.get(1), "L" + referenceType.getIdentifier() + ";");
|
||||
}
|
||||
}
|
||||
|
||||
private void loadBeforeCrement(AssignNode assignNode) {
|
||||
if(assignNode.expression instanceof IncrementNode) {
|
||||
IncrementNode incrementNode = (IncrementNode) assignNode.expression;
|
||||
if(incrementNode.assignableExpression.memberAccess != null) {
|
||||
incrementNode.assignableExpression.memberAccess.accept(this);
|
||||
} else {
|
||||
if(assignNode.assignable.getTypeNode() instanceof BaseType) {
|
||||
methodVisitor.visitVarInsn(ILOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||
} else if(assignNode.assignable.getTypeNode() instanceof ReferenceType) {
|
||||
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||
}
|
||||
}
|
||||
} else if(assignNode.expression instanceof DecrementNode) {
|
||||
DecrementNode decrementNode = (DecrementNode) assignNode.expression;
|
||||
if(decrementNode.assignableExpression.memberAccess != null) {
|
||||
decrementNode.assignableExpression.memberAccess.accept(this);
|
||||
} else {
|
||||
if(assignNode.assignable.getTypeNode() instanceof BaseType) {
|
||||
methodVisitor.visitVarInsn(ILOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||
} else if(assignNode.assignable.getTypeNode() instanceof ReferenceType) {
|
||||
methodVisitor.visitVarInsn(ALOAD, localVariables.indexOf(assignNode.assignable.identifier));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IncrementNode incrementNode) {
|
||||
if (incrementNode.assignableExpression.memberAccess != null) { // Object var / field
|
||||
int localVarIndex = localVariables.indexOf(incrementNode.assignableExpression.identifier);
|
||||
if (localVarIndex >= 0) { // object
|
||||
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
||||
} else { // this
|
||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||
}
|
||||
if (incrementNode.assignableExpression.memberAccess.getTypeNode() instanceof BaseType) {
|
||||
methodVisitor.visitFieldInsn(GETFIELD, incrementNode.assignableExpression.memberAccess.identifiers.get(0), incrementNode.assignableExpression.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) incrementNode.assignableExpression.memberAccess.getTypeNode()));
|
||||
} else if (incrementNode.assignableExpression.memberAccess.getTypeNode() instanceof ReferenceType) {
|
||||
methodVisitor.visitFieldInsn(GETFIELD, incrementNode.assignableExpression.memberAccess.identifiers.get(0), incrementNode.assignableExpression.memberAccess.identifiers.get(1), "L" + (((ReferenceType) incrementNode.assignableExpression.memberAccess.getTypeNode()).getIdentifier() + ";"));
|
||||
}
|
||||
methodVisitor.visitInsn(DUP);
|
||||
methodVisitor.visitInsn(ICONST_1);
|
||||
methodVisitor.visitInsn(IADD);
|
||||
if (incrementNode.assignableExpression.memberAccess.getTypeNode() instanceof BaseType) {
|
||||
methodVisitor.visitFieldInsn(PUTFIELD, incrementNode.assignableExpression.memberAccess.identifiers.get(0), incrementNode.assignableExpression.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) incrementNode.assignableExpression.memberAccess.getTypeNode()));
|
||||
} else if (incrementNode.assignableExpression.memberAccess.getTypeNode() instanceof ReferenceType) {
|
||||
methodVisitor.visitFieldInsn(PUTFIELD, incrementNode.assignableExpression.memberAccess.identifiers.get(0), incrementNode.assignableExpression.memberAccess.identifiers.get(1), "L" + (((ReferenceType) incrementNode.assignableExpression.memberAccess.getTypeNode()).getIdentifier() + ";"));
|
||||
}
|
||||
} else { // local var
|
||||
methodVisitor.visitIincInsn(localVariables.indexOf(incrementNode.assignableExpression.identifier), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(DecrementNode decrementNode) {
|
||||
if (decrementNode.assignableExpression.memberAccess != null) { // Object var / field
|
||||
int localVarIndex = localVariables.indexOf(decrementNode.assignableExpression.identifier);
|
||||
if (localVarIndex >= 0) { // object
|
||||
methodVisitor.visitVarInsn(ALOAD, localVarIndex);
|
||||
} else { // this
|
||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||
}
|
||||
methodVisitor.visitInsn(DUP);
|
||||
if (decrementNode.assignableExpression.memberAccess.getTypeNode() instanceof BaseType) {
|
||||
methodVisitor.visitFieldInsn(GETFIELD, decrementNode.assignableExpression.memberAccess.identifiers.get(0), decrementNode.assignableExpression.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) decrementNode.assignableExpression.memberAccess.getTypeNode()));
|
||||
} else if (decrementNode.assignableExpression.memberAccess.getTypeNode() instanceof ReferenceType) {
|
||||
methodVisitor.visitFieldInsn(GETFIELD, decrementNode.assignableExpression.memberAccess.identifiers.get(0), decrementNode.assignableExpression.memberAccess.identifiers.get(1), "L" + (((ReferenceType) decrementNode.assignableExpression.memberAccess.getTypeNode()).getIdentifier() + ";"));
|
||||
}
|
||||
methodVisitor.visitInsn(ICONST_1);
|
||||
methodVisitor.visitInsn(ISUB);
|
||||
if (decrementNode.assignableExpression.memberAccess.getTypeNode() instanceof BaseType) {
|
||||
methodVisitor.visitFieldInsn(PUTFIELD, decrementNode.assignableExpression.memberAccess.identifiers.get(0), decrementNode.assignableExpression.memberAccess.identifiers.get(1), mapper.getTypeChar((BaseType) decrementNode.assignableExpression.memberAccess.getTypeNode()));
|
||||
} else if (decrementNode.assignableExpression.memberAccess.getTypeNode() instanceof ReferenceType) {
|
||||
methodVisitor.visitFieldInsn(PUTFIELD, decrementNode.assignableExpression.memberAccess.identifiers.get(0), decrementNode.assignableExpression.memberAccess.identifiers.get(1), "L" + (((ReferenceType) decrementNode.assignableExpression.memberAccess.getTypeNode()).getIdentifier() + ";"));
|
||||
}
|
||||
} else { // local var
|
||||
methodVisitor.visitIincInsn(localVariables.indexOf(decrementNode.assignableExpression.identifier), -1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,8 +604,7 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
expressionNode.accept(this);
|
||||
parameterNodes.add(new ParameterNode(expressionNode.getType(), ""));
|
||||
}
|
||||
methodVisitor.visitMethodInsn(INVOKESPECIAL, newDeclarationNode.identifier, "<init>", mapper.generateMethodDescriptor(new BaseType(TypeEnum.VOID),parameterNodes), false);
|
||||
localVariables.add(newDeclarationNode.identifier);
|
||||
methodVisitor.visitMethodInsn(INVOKESPECIAL, newDeclarationNode.identifier, "<init>", mapper.generateMethodDescriptor(new BaseType(TypeEnum.VOID), parameterNodes), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -518,19 +676,13 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
methodVisitor.visitLabel(endOfLoopLabel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ChainedMethodNode chainedMethodNode) {
|
||||
// TODO: Erstmal abwarten
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MethodCallNode methodCallNode) {
|
||||
List<ParameterNode> parameterNodes = new ArrayList<>();
|
||||
for(IExpressionNode expressionNode : methodCallNode.parameters) {
|
||||
for (IExpressionNode expressionNode : methodCallNode.parameters) {
|
||||
expressionNode.accept(this);
|
||||
parameterNodes.add(new ParameterNode(expressionNode.getType(), ""));
|
||||
}
|
||||
// TODO: Klassenname und Returntype
|
||||
//methodVisitor.visitMethodInsn(INVOKEVIRTUAL, classname, methodCallNode.identifier, mapper.generateMethodDescriptor(returntype, parameterNodes), false);
|
||||
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, methodCallNode.target.memberAccess.identifiers.get(0), methodCallNode.identifier, mapper.generateMethodDescriptor(methodCallNode.type, parameterNodes), false);
|
||||
}
|
||||
}
|
||||
|
@@ -5,6 +5,5 @@ import ast.members.FieldNode;
|
||||
|
||||
public interface ClassVisitor {
|
||||
void visit(ClassNode classNode);
|
||||
|
||||
void visit(FieldNode fieldNode);
|
||||
}
|
||||
|
@@ -39,12 +39,14 @@ public interface MethodVisitor {
|
||||
// statements
|
||||
void visit(IfElseNode ifElseNode);
|
||||
|
||||
void visit(IncrementNode incrementNode);
|
||||
void visit(DecrementNode decrementNode);
|
||||
|
||||
void visit(LocalVariableDeclarationNode localVariableDeclarationNode);
|
||||
void visit(ReturnNode returnNode);
|
||||
void visit(WhileNode whileNode);
|
||||
|
||||
// statement expression
|
||||
void visit(ChainedMethodNode chainedMethodNode);
|
||||
void visit(MethodCallNode methodCallNode);
|
||||
|
||||
void visit(AssignNode assignNode);
|
||||
|
@@ -253,6 +253,7 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
||||
|
||||
if (toCheck.memberAccess != null) {
|
||||
var result = toCheck.memberAccess.accept(this);
|
||||
toCheck.identifier = toCheck.memberAccess.identifiers.getLast();
|
||||
toCheck.setTypeNode(result.getType());
|
||||
return result;
|
||||
} else {
|
||||
@@ -316,9 +317,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
|
||||
@@ -604,11 +609,15 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
||||
ITypeNode currentType = null;
|
||||
int start = 0;
|
||||
if(!memberAccessNode.identifiers.isEmpty()){
|
||||
if(currentFields.get(memberAccessNode.identifiers.get(0)) != null){
|
||||
memberAccessNode.identifiers.add(0, currentClass.identifier);
|
||||
start = 1;
|
||||
if(currentFields.get(memberAccessNode.identifiers.getFirst()) != null){
|
||||
memberAccessNode.identifiers.addFirst(currentClass.identifier);
|
||||
start++;
|
||||
}
|
||||
}
|
||||
if(context.getClasses().get(memberAccessNode.identifiers.getFirst()) == null){
|
||||
memberAccessNode.identifiers.addFirst(currentClass.identifier);
|
||||
start++;
|
||||
}
|
||||
for (int i = start; i < memberAccessNode.identifiers.size(); i++) {
|
||||
|
||||
String s = memberAccessNode.identifiers.get(i);
|
||||
@@ -626,7 +635,8 @@ public class SemanticAnalyzer implements SemanticVisitor {
|
||||
} else {
|
||||
if (currentType instanceof ReferenceType reference) {
|
||||
var currentTypeClass = context.getClass(reference.getIdentifier());
|
||||
|
||||
memberAccessNode.identifiers.add(i, reference.getIdentifier());
|
||||
i++;
|
||||
var currentField = currentTypeClass.getField(s);
|
||||
if (currentField.getAccessModifier().accessType == EnumAccessModifierNode.PUBLIC) {
|
||||
currentType = currentField.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
|
||||
}
|
@@ -338,6 +338,17 @@ public class EndToTypedAstTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void Expression(){
|
||||
|
||||
ASTNode tast = SemanticHelper.generateTypedASTFrom("src/test/resources/input/singleFeatureSemanticTests/Expression.java");
|
||||
|
||||
SemanticAnalyzer.generateTast(tast);
|
||||
|
||||
assertTrue(SemanticAnalyzer.errors.isEmpty());
|
||||
|
||||
}
|
||||
|
||||
// ------------------ Helpers ------------------
|
||||
|
||||
/**
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,10 @@
|
||||
class VariableCompare{
|
||||
|
||||
void trueMethod(boolean a, int c) {
|
||||
if(a && c == 10){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,13 +1,16 @@
|
||||
public class Klasse1 {
|
||||
public int test;
|
||||
|
||||
public int test1() {
|
||||
test = 5;
|
||||
return 1;
|
||||
public class Compiler {
|
||||
Node node;
|
||||
public int add(int i, int j) {
|
||||
node = new Node();
|
||||
node.x = 1;
|
||||
return i+j;
|
||||
}
|
||||
}
|
||||
|
||||
public void test2() {
|
||||
int testInt;
|
||||
testInt = this.test1();
|
||||
public class Node {
|
||||
public int x;
|
||||
public void main() {
|
||||
Compiler compiler = new Compiler();
|
||||
int i = compiler.add(5, 8);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user