Compare commits
237 Commits
6b7fc09f8f
...
JannikChan
| Author | SHA1 | Date | |
|---|---|---|---|
| 91552ad147 | |||
| 084808c3ab | |||
| d19748766f | |||
|
|
4bdb65a6ce | ||
|
|
97e0c228d6 | ||
|
|
d4be77ceb2 | ||
| ca539add98 | |||
| 1bcf396f95 | |||
| 8ba58d492b | |||
|
|
ed25868ff7 | ||
| 879fa08cdc | |||
|
|
0e512161a0 | ||
|
|
ba08c6f6b0 | ||
| c5aea85965 | |||
| 2a1d0a0b8a | |||
| f1abe5d5a8 | |||
|
|
a9d7e841f5 | ||
|
|
b7863d0684 | ||
|
|
7ccff3208c | ||
|
|
3e0e6f8327 | ||
|
|
ab5a51d3b1 | ||
|
|
a4c1c502ab | ||
|
|
7d441116bd | ||
|
|
8afa3b8461 | ||
|
|
84ecf316cd | ||
|
|
7ddea8f18d | ||
| 46154fbb01 | |||
| 9aac795c07 | |||
| e59f4e7190 | |||
|
|
e6a2b0fe9d | ||
|
|
44c2f551de | ||
|
|
bad034acfd | ||
|
|
ba73e1bd45 | ||
|
|
b7affd75ae | ||
|
|
2ef50f93a9 | ||
|
|
1cf1aaf837 | ||
|
|
2bf73385af | ||
|
|
b072af346b | ||
|
|
27baa429b4 | ||
| bd76135895 | |||
|
|
6cec17eb45 | ||
| 87be850a0e | |||
| 72f82ff863 | |||
| 7419953510 | |||
| 449b895d20 | |||
| f0dd6d5eb6 | |||
| 8956362033 | |||
|
|
ed4aa2d59b | ||
|
|
6760a17f00 | ||
|
|
671317f28b | ||
|
|
e862a7427b | ||
| 233725778f | |||
| 3227d69fc1 | |||
| 4ca6972ccd | |||
| 0047f6c08e | |||
| 88ce9e52f0 | |||
|
|
437de74cc6 | ||
|
|
ca77307f0c | ||
|
|
5f46130439 | ||
| 3e1456351c | |||
| d26cd0c13a | |||
|
|
cfde5219a4 | ||
|
|
f414e278bb | ||
|
|
741a56cb99 | ||
|
|
02e5f3a729 | ||
|
|
f7338a06b3 | ||
|
|
3996082fa7 | ||
| 903e87901e | |||
| 775beb60fe | |||
|
|
2537051668 | ||
|
|
82356ec189 | ||
|
|
561eafbf4c | ||
| b58fa00c9a | |||
|
|
92990e4042 | ||
|
|
3500ffd377 | ||
|
|
771b92bfd7 | ||
| c94c7a6477 | |||
| c7ad574474 | |||
| 22c3850062 | |||
|
|
21da31dee3 | ||
|
|
294df16e89 | ||
| 3112660880 | |||
| c135819ba0 | |||
| e94cd9cc2a | |||
|
|
dcd20a2394 | ||
|
|
71ffb8bb83 | ||
|
|
2d455ba197 | ||
|
|
77fecfa476 | ||
|
|
36e56fa66e | ||
|
|
f3e3158460 | ||
|
|
7b1e6fced4 | ||
|
|
4d5c0017b4 | ||
| 093beb9ef1 | |||
| 2ae0988986 | |||
|
|
18fc17b707 | ||
|
|
bea71838ac | ||
| dfded3e592 | |||
| 0298e2cb76 | |||
|
|
dccd34db73 | ||
| 90f91d58d1 | |||
| 612c967023 | |||
| f12e553ffc | |||
| f24e279596 | |||
| c5fc378eed | |||
|
|
27f50b9c66 | ||
| 3e901ea254 | |||
| 85ae06048c | |||
| cd845cd91c | |||
|
|
4d21d8e94e | ||
|
|
a34c7ded50 | ||
| 78d5528733 | |||
|
|
10eb17497e | ||
|
|
576146c4fc | ||
|
|
bf365194be | ||
|
|
35b3e9ee46 | ||
|
|
88a25207e9 | ||
|
|
4e56760dd6 | ||
|
|
347bdcbd94 | ||
|
|
d594bacb7d | ||
|
|
eb313464f0 | ||
|
|
8163d0b61e | ||
|
|
92e1daab5b | ||
| 70a3788030 | |||
| b562a789a0 | |||
| c05ad761d7 | |||
|
|
34d17660ef | ||
|
|
cc6d26e17d | ||
|
|
f9743efddc | ||
|
|
b37e065857 | ||
| 4c5473827e | |||
| d631b01c82 | |||
|
|
8cd22c6e4c | ||
| ef0bc99bbf | |||
| 99948fef07 | |||
| 66c9481b3e | |||
| fd8d451ba7 | |||
| f27a7471bc | |||
| a15f684c04 | |||
| 4a78ab62a1 | |||
|
|
8d3602eda3 | ||
|
|
fcaeb850ba | ||
|
|
864ddbaeee | ||
| fb3f822160 | |||
| fd6da5cad2 | |||
|
|
c44118c872 | ||
|
|
0020f582a1 | ||
| 8b5a0d528e | |||
|
|
1b91e25d17 | ||
|
|
9edee73705 | ||
|
|
5bf9a4fc73 | ||
| 6d36eb109c | |||
|
|
7b41c45cd5 | ||
|
|
cf41babcb7 | ||
|
|
b9ada16dd1 | ||
|
|
b5738034b0 | ||
| b9f6014f59 | |||
| 50a52a1e87 | |||
| d3e9fa9b43 | |||
|
|
0ec65af9f9 | ||
|
|
fd8c3b066a | ||
| af64f88198 | |||
| 978b5a2b4a | |||
| 837e751094 | |||
|
|
8cc67080ec | ||
|
|
cfcb61d49e | ||
|
|
8f742191bb | ||
|
|
102961bccc | ||
|
|
f59d7e9918 | ||
|
|
0732712e61 | ||
| 57c2023215 | |||
|
|
12ab402746 | ||
| bf7a642233 | |||
| 3639b2a4f8 | |||
| 330b92a79f | |||
| 8094a93582 | |||
| 0271313a05 | |||
|
|
b6cc925e02 | ||
|
|
e552bd5ada | ||
|
|
6a971345d4 | ||
|
|
56d316a6d0 | ||
|
|
8d6190b130 | ||
| 09e36a84dc | |||
|
|
e395c4d96b | ||
|
|
8a5f307947 | ||
| 514f7d724a | |||
|
|
9f40949f5a | ||
|
|
de5c2a5002 | ||
|
|
22a30d5956 | ||
|
|
1132ff015c | ||
|
|
2a20a91d35 | ||
| 407b03620e | |||
|
|
b2e1745d51 | ||
|
|
a0e55d7b27 | ||
|
|
5a28d88f6a | ||
| 1c77a99f54 | |||
|
|
c483babaf5 | ||
|
|
403ab70655 | ||
|
|
d91e3ad819 | ||
|
|
8b9b70b9ee | ||
|
|
7906a38cdd | ||
|
|
dd424cda99 | ||
| 1d5bfdd88f | |||
|
|
149caf5202 | ||
| b03ea72eca | |||
| d2f8ea1e78 | |||
|
|
c5bb038fc3 | ||
| b7d5a5c625 | |||
|
|
f781d8eeb6 | ||
|
|
b64e2efc82 | ||
|
|
8b6189ea33 | ||
| 91f7db24f6 | |||
|
|
33df2c1c0a | ||
| 6250ee781c | |||
|
|
6318085c00 | ||
| f5da71478f | |||
|
|
a8638fe70c | ||
| edb7aafd77 | |||
| c4061125c4 | |||
|
|
1d9d7e1f00 | ||
| f77143599b | |||
|
|
1441e34078 | ||
|
|
dfe96d9a87 | ||
| 8e7b64c38d | |||
| d27ec0643a | |||
| 79a140b683 | |||
|
|
e4d0b93880 | ||
| b6bbf7e1d5 | |||
|
|
584dcc6beb | ||
|
|
1fbec0d754 | ||
|
|
e987faae64 | ||
|
|
2bae802cb2 | ||
|
|
0052b5b547 | ||
|
|
b773793937 | ||
|
|
43cafcd01f | ||
| 651a8b6ebf | |||
|
|
275eceb80a | ||
|
|
9d6717a9ce |
15
.gitea/workflows/test.yml
Normal file
15
.gitea/workflows/test.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
name: Gitea Actions Demo
|
||||
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
Explore-Gitea-Actions:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
- name: Run the Maven verify phase
|
||||
run: mvn --batch-mode --update-snapshots verify
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -76,4 +76,11 @@ fabric.properties
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
/target
|
||||
/target
|
||||
src/main/resources/logs/RaupenLog.log
|
||||
src/main/resources/output/CompilerInput.class
|
||||
src/test/resources/output/javac/CompilerInput$Test.class
|
||||
src/test/resources/output/javac/CompilerInput.class
|
||||
src/test/resources/output/raupenpiler/CompilerInput.class
|
||||
src/test/resources/output/raupenpiler/CompilerInput$Test.class
|
||||
.idea/inspectionProfiles/Project_Default.xml
|
||||
|
||||
19
.idea/ANTLRv4ToolGrammarProperties.xml
generated
Normal file
19
.idea/ANTLRv4ToolGrammarProperties.xml
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ANTLRv4ToolGrammarProperties">
|
||||
<option name="perGrammarGenerationSettings">
|
||||
<list>
|
||||
<PerGrammarGenerationSettings>
|
||||
<option name="fileName" value="$PROJECT_DIR$/src/main/java/parser/grammar/SimpleJava.g4" />
|
||||
<option name="autoGen" value="true" />
|
||||
<option name="outputDir" value="C:\Users\janni\Desktop\NichtHaskell2.0\src\main\java" />
|
||||
<option name="libDir" value="" />
|
||||
<option name="encoding" value="" />
|
||||
<option name="pkg" value="parser.generated" />
|
||||
<option name="language" value="" />
|
||||
<option name="generateVisitor" value="true" />
|
||||
</PerGrammarGenerationSettings>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
|
||||
</state>
|
||||
</component>
|
||||
5
.idea/jarRepositories.xml
generated
5
.idea/jarRepositories.xml
generated
@@ -6,6 +6,11 @@
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven_central" />
|
||||
<option name="name" value="Maven Central" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
|
||||
14
.idea/misc.xml
generated
14
.idea/misc.xml
generated
@@ -6,10 +6,20 @@
|
||||
<PerGrammarGenerationSettings>
|
||||
<option name="fileName" value="$PROJECT_DIR$/src/main/java/parser/SimpleJava.g4" />
|
||||
<option name="autoGen" value="true" />
|
||||
<option name="outputDir" value="C:\Users\Maxi\Documents\DHBW\Compilerbau\NichtHaskell2.0\src\main\java\parser" />
|
||||
<option name="outputDir" value="C:\Users\ARB00075\Documents\DH\Compilerbau\NichtHaskell2.0\src\main\java" />
|
||||
<option name="libDir" value="" />
|
||||
<option name="encoding" value="" />
|
||||
<option name="pkg" value="generated" />
|
||||
<option name="pkg" value="parser.generated" />
|
||||
<option name="language" value="" />
|
||||
<option name="generateVisitor" value="true" />
|
||||
</PerGrammarGenerationSettings>
|
||||
<PerGrammarGenerationSettings>
|
||||
<option name="fileName" value="$PROJECT_DIR$/src/main/java/parser/grammar/SimpleJava.g4" />
|
||||
<option name="autoGen" value="true" />
|
||||
<option name="outputDir" value="C:\Users\Maxi\Documents\DHBW\Compilerbau\NichtHaskell2.0\src\main\java" />
|
||||
<option name="libDir" value="" />
|
||||
<option name="encoding" value="" />
|
||||
<option name="pkg" value="parser.generated" />
|
||||
<option name="language" value="" />
|
||||
<option name="generateVisitor" value="true" />
|
||||
</PerGrammarGenerationSettings>
|
||||
|
||||
58
.lib/Kurzdokumentation.md
Normal file
58
.lib/Kurzdokumentation.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Kurzdokumentation
|
||||
|
||||
## Aufgabenverteilung
|
||||
|
||||
### Maximilian Stahl und Jannik Rombach:
|
||||
- **Scanner**
|
||||
- **Parser**
|
||||
- **AST**
|
||||
- **AstBuilder**
|
||||
- **Modul: ast**
|
||||
- Alle
|
||||
- **Modul: parser**
|
||||
- Alle
|
||||
- **Modul: visitor**
|
||||
- Alle
|
||||
- **Testmodul: parser**
|
||||
- AstBuildertest.java
|
||||
- Helper.java
|
||||
- **Testfiles: singleFeatureTests**
|
||||
- Alle
|
||||
|
||||
### Johannes Ehlert:
|
||||
- **Semantische Analyse**
|
||||
- **Modul: semantic**
|
||||
- **Modul: typecheck**
|
||||
- **Testmodul: parser**
|
||||
- AstBuildertest.java
|
||||
- **Testfiles: typedAstFeatureTests**
|
||||
- Großteil
|
||||
- **Testfiles: typedAstExceptionsTests**
|
||||
- Großteil
|
||||
|
||||
### David Große:
|
||||
- **Bytecodegenerator**
|
||||
- **Modul: bytecode**
|
||||
- Alle
|
||||
|
||||
### Lucas Janker:
|
||||
- **Tests**
|
||||
- **Modul: main**
|
||||
- Alle
|
||||
- **Testmodul: main**
|
||||
- Alle
|
||||
- **Testmodul: parser**
|
||||
- ScannerTest.java
|
||||
- ParserTest.java
|
||||
- **Testmodul: semantic**
|
||||
- **Testfiles: combinedFeatureTests**
|
||||
- Alle
|
||||
- **Testfiles: failureTests**
|
||||
- Alle
|
||||
- **Testfiles: Alle**
|
||||
- Refactoring
|
||||
- **Ordnerstrukturen**
|
||||
- Großteil
|
||||
- **Build**
|
||||
- **Makefile**
|
||||
- **Dokumentation**
|
||||
66
pom.xml
66
pom.xml
@@ -4,13 +4,14 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example</groupId>
|
||||
<groupId>de.dhbw-stuttgart</groupId>
|
||||
<artifactId>JavaCompiler</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<java.version>22</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
@@ -19,7 +20,7 @@
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.9.3</version> <!-- Change the version as needed -->
|
||||
<version>5.11.0-M2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -27,13 +28,34 @@
|
||||
<artifactId>antlr4-runtime</artifactId>
|
||||
<version>4.13.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
<version>9.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.16.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<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>
|
||||
@@ -44,7 +66,35 @@
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M5</version> <!-- Change the version as needed -->
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id> <!-- this is used for inheritance merges -->
|
||||
<phase>package</phase> <!-- bind to the packaging phase -->
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>main.Main</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>maven_central</id>
|
||||
<name>Maven Central</name>
|
||||
<url>https://repo.maven.apache.org/maven2/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
</project>
|
||||
@@ -1,21 +0,0 @@
|
||||
public class Example {
|
||||
|
||||
public int test;
|
||||
|
||||
public Example(int conInput) {
|
||||
|
||||
}
|
||||
|
||||
public static int test(char b){
|
||||
|
||||
test = 3;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class Test {
|
||||
|
||||
public char test;
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import ast.ClassNode;
|
||||
import ast.ProgramNode;
|
||||
import bytecode.ByteCodeGenerator;
|
||||
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 parser.ASTBuilder;
|
||||
import parser.generated.SimpleJavaLexer;
|
||||
import parser.generated.SimpleJavaParser;
|
||||
import semantic.SemanticAnalyzer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
CharStream codeCharStream = null;
|
||||
|
||||
try {
|
||||
codeCharStream = CharStreams.fromPath(Paths.get("src/main/java/CompilerInput.txt"));
|
||||
parsefile(codeCharStream);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error reading the file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void parsefile(CharStream codeCharStream){
|
||||
// CharStream codeCharStream = CharStreams.fromString("class javaFileInput.Example { } class Example2 { }");
|
||||
SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
SimpleJavaParser parser = new SimpleJavaParser(tokens);
|
||||
|
||||
ParseTree tree = parser.program(); // parse the input
|
||||
|
||||
ASTBuilder builder = new ASTBuilder();
|
||||
ProgramNode ast = (ProgramNode) builder.visit(tree); // build the AST
|
||||
|
||||
// Optionally print or process the AST
|
||||
System.out.println("Parsed " + ast.classes.size() + " classes with identifiers/names:");
|
||||
for (ClassNode classNode : ast.classes) {
|
||||
System.out.println(classNode.identifier.getName());
|
||||
}
|
||||
|
||||
SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer();
|
||||
semanticAnalyzer.analyze(ast);
|
||||
|
||||
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator();
|
||||
byteCodeGenerator.generateByteCode(ast);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,20 @@
|
||||
package ast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import bytecode.visitor.ClassVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public abstract class ASTNode { }
|
||||
public interface ASTNode {
|
||||
|
||||
//Todo: @BruderJohn & @i22007 Interface anwenden + geeignetetn Methodename.
|
||||
|
||||
/*
|
||||
Typecheck:
|
||||
public TypeCheckResult acceptType(SemanticVisitor visitor);
|
||||
|
||||
Bytecode:
|
||||
public void accepByteCode(ClassVisitor classVisitor);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
package ast;
|
||||
|
||||
public class BlockNode {
|
||||
}
|
||||
@@ -1,36 +1,53 @@
|
||||
package ast;
|
||||
|
||||
import ast.member.ConstructorNode;
|
||||
import ast.member.MemberNode;
|
||||
import ast.type.AccessTypeNode;
|
||||
import ast.type.EnumAccessTypeNode;
|
||||
import ast.type.AccessModifierNode;
|
||||
import ast.members.ConstructorNode;
|
||||
import ast.members.MemberNode;
|
||||
import ast.members.MethodNode;
|
||||
import bytecode.visitor.ClassVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ClassNode extends ASTNode{
|
||||
public IdentifierNode identifier;
|
||||
public AccessTypeNode accessType;
|
||||
public String name;
|
||||
public class ClassNode implements ASTNode, Visitable {
|
||||
public AccessModifierNode accessType;
|
||||
public String identifier;
|
||||
public List<MemberNode> members = new ArrayList<>();
|
||||
public boolean hasConstructor = false;
|
||||
|
||||
public ClassNode(AccessTypeNode accessType, String name){
|
||||
this.accessType = accessType;
|
||||
this.name = name;
|
||||
public ClassNode(){
|
||||
|
||||
}
|
||||
|
||||
public ClassNode(String accessType, String identifier){
|
||||
this.accessType = new AccessModifierNode(accessType);
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public void addMember(MemberNode member) {
|
||||
if (member instanceof ConstructorNode) {
|
||||
this.hasConstructor = true;
|
||||
}
|
||||
members.add(member);
|
||||
}
|
||||
|
||||
public void ensureConstructor(){
|
||||
if(!hasConstructor) {
|
||||
ConstructorNode constructor = new ConstructorNode(new AccessTypeNode(EnumAccessTypeNode.PUBLIC), name);
|
||||
members.add(0,constructor);
|
||||
public List<MethodNode> getMethods(){
|
||||
List<MethodNode> methods = new ArrayList<>();
|
||||
for (MemberNode member : members) {
|
||||
if (member instanceof MethodNode methodNode) {
|
||||
methods.add(methodNode);
|
||||
}
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ClassVisitor classVisitor) {
|
||||
classVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package ast;
|
||||
|
||||
public class IdentifierNode {
|
||||
|
||||
private String name;
|
||||
|
||||
public IdentifierNode(String name){
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName(){
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if(obj instanceof IdentifierNode){
|
||||
IdentifierNode identifier = (IdentifierNode) obj;
|
||||
if(name.equals(identifier.getName())){
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,27 @@
|
||||
package ast;
|
||||
|
||||
import bytecode.visitor.ProgramVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ProgramNode extends ASTNode {
|
||||
public class ProgramNode implements ASTNode, Visitable {
|
||||
public List<ClassNode> classes = new ArrayList<>();
|
||||
|
||||
public void addClass(ClassNode classNode) {
|
||||
classes.add(classNode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ProgramVisitor programVisitor) {
|
||||
programVisitor.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package ast.expression;
|
||||
|
||||
public class BinaryExpressionNode extends ExpressionNode {
|
||||
public ExpressionNode left;
|
||||
public ExpressionNode right;
|
||||
public String operator; // Stores the operator as a string (e.g., "+", "-", "&&")
|
||||
|
||||
public BinaryExpressionNode(ExpressionNode left, ExpressionNode right, String operator) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.operator = operator;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package ast.expression;
|
||||
|
||||
import ast.ASTNode;
|
||||
|
||||
public class ExpressionNode extends ASTNode {
|
||||
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package ast.expression;
|
||||
|
||||
public class IdentifierExpressionNode extends ExpressionNode {
|
||||
public String name;
|
||||
|
||||
public IdentifierExpressionNode(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package ast.expression;
|
||||
|
||||
public class UnaryExpressionNode extends ExpressionNode {
|
||||
public ExpressionNode expression;
|
||||
public String operator; // Stores the operator (e.g., "-", "!")
|
||||
|
||||
public UnaryExpressionNode(ExpressionNode expression, String operator) {
|
||||
this.expression = expression;
|
||||
this.operator = operator;
|
||||
}
|
||||
}
|
||||
13
src/main/java/ast/expressions/IExpressionNode.java
Normal file
13
src/main/java/ast/expressions/IExpressionNode.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package ast.expressions;
|
||||
|
||||
import ast.ASTNode;
|
||||
import ast.type.type.ITypeNode;
|
||||
import visitor.Visitable;
|
||||
|
||||
public interface IExpressionNode extends ASTNode, Visitable {
|
||||
|
||||
ITypeNode getType();
|
||||
|
||||
void setType(ITypeNode type);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package ast.expressions.binaryexpressions;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import ast.type.type.*;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class BinaryNode implements IExpressionNode, Visitable {
|
||||
|
||||
private ITypeNode typeNode;
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITypeNode getType() {
|
||||
return typeNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setType(ITypeNode type) {
|
||||
this.typeNode = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package ast.expressions.binaryexpressions;
|
||||
|
||||
import ast.type.type.*;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
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;
|
||||
setOperator(operator);
|
||||
this.dotExpression = dotExpression;
|
||||
}
|
||||
|
||||
public CalculationNode(DotNode dotExpression) {
|
||||
this.dotExpression = dotExpression;
|
||||
}
|
||||
|
||||
private void setOperator(String operator) {
|
||||
if(operator != null) {
|
||||
if(operator.equals("+")) {
|
||||
this.operator = EnumLineOperator.PLUS;
|
||||
} else if(operator.equals("-")) {
|
||||
this.operator = EnumLineOperator.MINUS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
42
src/main/java/ast/expressions/binaryexpressions/DotNode.java
Normal file
42
src/main/java/ast/expressions/binaryexpressions/DotNode.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package ast.expressions.binaryexpressions;
|
||||
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class DotNode extends BinaryNode {
|
||||
public DotNode dotExpression;
|
||||
public EnumDotOperator operator;
|
||||
public DotSubstractionNode dotSubstractionExpression;
|
||||
|
||||
public DotNode(DotNode dotExpression, String operator, DotSubstractionNode dotSubstractionExpression) {
|
||||
this.dotExpression = dotExpression;
|
||||
setOperator(operator);
|
||||
this.dotSubstractionExpression = dotSubstractionExpression;
|
||||
}
|
||||
|
||||
public DotNode(DotSubstractionNode dotSubstractionExpression) {
|
||||
this.dotSubstractionExpression = dotSubstractionExpression;
|
||||
}
|
||||
|
||||
private void setOperator(String operator) {
|
||||
if(operator.equals("*")) {
|
||||
this.operator = EnumDotOperator.MULT;
|
||||
} else if(operator.equals("/")) {
|
||||
this.operator = EnumDotOperator.DIV;
|
||||
} else if(operator.equals("%")) {
|
||||
this.operator = EnumDotOperator.MOD;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package ast.expressions.binaryexpressions;
|
||||
|
||||
import ast.expressions.unaryexpressions.MemberAccessNode;
|
||||
import ast.statementexpressions.methodcallstatementnexpressions.MethodCallNode;
|
||||
import ast.type.type.*;
|
||||
import ast.type.ValueNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class DotSubstractionNode extends BinaryNode {
|
||||
public ValueNode value;
|
||||
public String identifier;
|
||||
public MemberAccessNode memberAccess;
|
||||
public MethodCallNode methodCall;
|
||||
public CalculationNode calculationExpression;
|
||||
|
||||
public DotSubstractionNode(ValueNode value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public DotSubstractionNode(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public DotSubstractionNode(MemberAccessNode memberAccess) {
|
||||
this.memberAccess = memberAccess;
|
||||
}
|
||||
|
||||
public DotSubstractionNode(MethodCallNode methodCall, CalculationNode calculationExpression) {
|
||||
this.methodCall = methodCall;
|
||||
this.calculationExpression = calculationExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package ast.expressions.binaryexpressions;
|
||||
|
||||
public enum EnumDotOperator {
|
||||
MULT, DIV, MOD
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package ast.expressions.binaryexpressions;
|
||||
|
||||
public enum EnumLineOperator {
|
||||
PLUS, MINUS
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package ast.expressions.binaryexpressions;
|
||||
|
||||
public enum EnumNonCalculationOperator {
|
||||
AND, OR, GREATER, LESS, GREATER_EQUAL, LESS_EQUAL, EQUAL, NOT_EQUAL
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package ast.expressions.binaryexpressions;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import ast.expressions.unaryexpressions.UnaryNode;
|
||||
import ast.type.type.*;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class NonCalculationNode extends BinaryNode {
|
||||
public UnaryNode unaryExpression;
|
||||
public EnumNonCalculationOperator operator;
|
||||
public IExpressionNode expression;
|
||||
|
||||
public NonCalculationNode(UnaryNode unaryExpression, String operator, IExpressionNode expression) {
|
||||
this.unaryExpression = unaryExpression;
|
||||
setOperator(operator);
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
private void setOperator(String operator) {
|
||||
if(operator.equals("&&")) {
|
||||
this.operator = EnumNonCalculationOperator.AND;
|
||||
} else if(operator.equals("||")) {
|
||||
this.operator = EnumNonCalculationOperator.OR;
|
||||
} else if(operator.equals(">")) {
|
||||
this.operator = EnumNonCalculationOperator.GREATER;
|
||||
} else if(operator.equals("<")) {
|
||||
this.operator = EnumNonCalculationOperator.LESS;
|
||||
} else if(operator.equals(">=")) {
|
||||
this.operator = EnumNonCalculationOperator.GREATER_EQUAL;
|
||||
} else if(operator.equals("<=")) {
|
||||
this.operator = EnumNonCalculationOperator.LESS_EQUAL;
|
||||
} else if(operator.equals("==")) {
|
||||
this.operator = EnumNonCalculationOperator.EQUAL;
|
||||
} else if(operator.equals("!=")) {
|
||||
this.operator = EnumNonCalculationOperator.NOT_EQUAL;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package ast.expressions.unaryexpressions;
|
||||
|
||||
import ast.ASTNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import ast.type.type.ITypeNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MemberAccessNode implements ASTNode, Visitable {
|
||||
public Boolean thisExpr;
|
||||
public List<String> identifiers = new ArrayList<>();
|
||||
private ITypeNode typeNode;
|
||||
|
||||
public MemberAccessNode(Boolean thisExpr) {
|
||||
this.thisExpr = thisExpr;
|
||||
}
|
||||
|
||||
public void addIdentifier(String identifier) {
|
||||
identifiers.add(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
public ITypeNode getTypeNode() {
|
||||
return typeNode;
|
||||
}
|
||||
|
||||
public void setTypeNode(ITypeNode typeNode) {
|
||||
this.typeNode = typeNode;
|
||||
}
|
||||
|
||||
}
|
||||
27
src/main/java/ast/expressions/unaryexpressions/NotNode.java
Normal file
27
src/main/java/ast/expressions/unaryexpressions/NotNode.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package ast.expressions.unaryexpressions;
|
||||
|
||||
import ast.ASTNode;
|
||||
import ast.expressions.IExpressionNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class NotNode implements ASTNode, Visitable {
|
||||
public IExpressionNode expression;
|
||||
|
||||
public NotNode(IExpressionNode expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package ast.expressions.unaryexpressions;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import ast.statements.IStatementNode;
|
||||
import ast.type.type.*;
|
||||
import ast.type.ValueNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class UnaryNode implements IExpressionNode {
|
||||
public String thisExp;
|
||||
public String identifier;
|
||||
public MemberAccessNode memberAccess;
|
||||
public ValueNode value;
|
||||
public NotNode notExpression;
|
||||
public IStatementNode statement;
|
||||
public IExpressionNode expression;
|
||||
private ITypeNode type;
|
||||
|
||||
public UnaryNode(String value) {
|
||||
if(Objects.equals(value, "this")) {
|
||||
this.thisExp = "this";
|
||||
} else {
|
||||
this.identifier = value;
|
||||
}
|
||||
}
|
||||
|
||||
public UnaryNode(MemberAccessNode memberAccess) {
|
||||
this.memberAccess = memberAccess;
|
||||
}
|
||||
|
||||
public UnaryNode(ValueNode value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public UnaryNode(NotNode notExpression) {
|
||||
this.notExpression = notExpression;
|
||||
}
|
||||
|
||||
public UnaryNode(IStatementNode statement) {
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
public UnaryNode(IExpressionNode expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITypeNode getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(ITypeNode type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
11
src/main/java/ast/literal/BooleanLiteralNode.java
Normal file
11
src/main/java/ast/literal/BooleanLiteralNode.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package ast.literal;
|
||||
|
||||
public class BooleanLiteralNode {
|
||||
private String value;
|
||||
|
||||
public BooleanLiteralNode(String value) {this.value = value;}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
11
src/main/java/ast/literal/CharLiteralNode.java
Normal file
11
src/main/java/ast/literal/CharLiteralNode.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package ast.literal;
|
||||
|
||||
public class CharLiteralNode {
|
||||
public String value;
|
||||
|
||||
public CharLiteralNode(String value) {this.value = value;}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
31
src/main/java/ast/literal/LiteralNode.java
Normal file
31
src/main/java/ast/literal/LiteralNode.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package ast.literal;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import ast.type.type.ITypeNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class LiteralNode implements IExpressionNode {
|
||||
|
||||
public String value;
|
||||
private ITypeNode type;
|
||||
|
||||
public LiteralNode(String value, ITypeNode type) {
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public ITypeNode getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(ITypeNode type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package ast.member;
|
||||
|
||||
import ast.type.AccessTypeNode;
|
||||
|
||||
public class ConstructorNode extends MethodNode {
|
||||
public ConstructorNode(AccessTypeNode visibility, String name) {
|
||||
super(visibility, name);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package ast.member;
|
||||
|
||||
import ast.IdentifierNode;
|
||||
import ast.type.AccessTypeNode;
|
||||
import ast.type.TypeNode;
|
||||
|
||||
public class FieldNode extends MemberNode {
|
||||
public AccessTypeNode accessTypeNode;
|
||||
public TypeNode type;
|
||||
public IdentifierNode identifier;
|
||||
|
||||
public FieldNode(AccessTypeNode accessTypeNode, TypeNode type, String name){
|
||||
this.accessTypeNode = accessTypeNode;
|
||||
this.type = type;
|
||||
this.identifier = new IdentifierNode(name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package ast.member;
|
||||
|
||||
import ast.ASTNode;
|
||||
|
||||
public class MemberNode extends ASTNode {
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package ast.member;
|
||||
|
||||
import ast.IdentifierNode;
|
||||
import ast.parameter.ParameterListNode;
|
||||
import ast.statement.StatementNode;
|
||||
import ast.type.AccessTypeNode;
|
||||
import ast.type.TypeNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MethodNode extends MemberNode {
|
||||
public IdentifierNode identifier;
|
||||
public AccessTypeNode visibility;
|
||||
public TypeNode type;
|
||||
public String name;
|
||||
|
||||
public ParameterListNode parameters;
|
||||
|
||||
public List<StatementNode> statements = new ArrayList<>();
|
||||
|
||||
public MethodNode(AccessTypeNode visibility, TypeNode type, String name, ParameterListNode parameters,
|
||||
List<StatementNode> statements){
|
||||
this.visibility = visibility;
|
||||
this.identifier = new IdentifierNode(name);
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.parameters = parameters;
|
||||
this.statements = statements;
|
||||
}
|
||||
|
||||
public MethodNode(AccessTypeNode visibility, String name){
|
||||
this.visibility = visibility;
|
||||
this.identifier = new IdentifierNode(name);
|
||||
}
|
||||
}
|
||||
47
src/main/java/ast/members/ConstructorNode.java
Normal file
47
src/main/java/ast/members/ConstructorNode.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package ast.members;
|
||||
|
||||
import ast.parameters.ParameterNode;
|
||||
import ast.statements.BlockNode;
|
||||
import ast.type.AccessModifierNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import visitor.Visitable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ConstructorNode extends MethodNode implements Visitable {
|
||||
public AccessModifierNode accessType;
|
||||
public String identifier;
|
||||
public List<ParameterNode> parameters = new ArrayList<>();
|
||||
public BlockNode block;
|
||||
|
||||
public ConstructorNode(String accessType, String identifier, BlockNode block) {
|
||||
this.accessType = new AccessModifierNode(accessType);
|
||||
this.identifier = identifier;
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public void addParameter(ParameterNode parameterNode) {
|
||||
parameters.add(parameterNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
public boolean isSame(MethodNode methodNode) {
|
||||
if (!(Objects.equals(this.identifier, methodNode.getIdentifier()))
|
||||
|| getParameters().size() != methodNode.getParameters().size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.getParameters().size(); i++) {
|
||||
if (!this.getParameters().get(i).type.equals(methodNode.getParameters().get(i).type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
32
src/main/java/ast/members/FieldNode.java
Normal file
32
src/main/java/ast/members/FieldNode.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package ast.members;
|
||||
|
||||
import ast.type.AccessModifierNode;
|
||||
import ast.type.type.ITypeNode;
|
||||
import bytecode.visitor.ClassVisitor;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class FieldNode implements MemberNode, Visitable {
|
||||
public AccessModifierNode accessTypeNode;
|
||||
public ITypeNode type;
|
||||
public String identifier;
|
||||
|
||||
public FieldNode(AccessModifierNode accessTypeNode, ITypeNode type, String name){
|
||||
this.accessTypeNode = accessTypeNode;
|
||||
this.type = type;
|
||||
this.identifier = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ClassVisitor classVisitor) {
|
||||
classVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
17
src/main/java/ast/members/MainMethodNode.java
Normal file
17
src/main/java/ast/members/MainMethodNode.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package ast.members;
|
||||
|
||||
import ast.statements.BlockNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class MainMethodNode extends MethodNode implements Visitable {
|
||||
|
||||
public MainMethodNode(BlockNode block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
}
|
||||
16
src/main/java/ast/members/MemberNode.java
Normal file
16
src/main/java/ast/members/MemberNode.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package ast.members;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import ast.ASTNode;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = MethodNode.class, name = "Method"),
|
||||
|
||||
@JsonSubTypes.Type(value = FieldNode.class, name = "Field") }
|
||||
)
|
||||
|
||||
public interface MemberNode extends ASTNode {}
|
||||
83
src/main/java/ast/members/MethodNode.java
Normal file
83
src/main/java/ast/members/MethodNode.java
Normal file
@@ -0,0 +1,83 @@
|
||||
package ast.members;
|
||||
|
||||
import ast.parameters.ParameterNode;
|
||||
import ast.statements.BlockNode;
|
||||
import ast.type.AccessModifierNode;
|
||||
import ast.type.type.*;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MethodNode implements MemberNode, Visitable {
|
||||
public AccessModifierNode accesModifier;
|
||||
private ITypeNode type;
|
||||
public Boolean voidType;
|
||||
private String identifier;
|
||||
public List<ParameterNode> parameters = new ArrayList<>();
|
||||
public BlockNode block;
|
||||
|
||||
public MethodNode() {
|
||||
}
|
||||
|
||||
public MethodNode(String accessModifier, ITypeNode type, Boolean voidType, String identifier, BlockNode block){
|
||||
this.accesModifier = new AccessModifierNode(accessModifier);
|
||||
this.type = type;
|
||||
this.voidType = voidType;
|
||||
this.identifier = identifier;
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public void addParameter(ParameterNode parameter) {
|
||||
this.parameters.add(parameter);
|
||||
}
|
||||
|
||||
public List<ParameterNode> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public boolean isSame(MethodNode methodNode){
|
||||
if (!(Objects.equals(this.identifier, methodNode.getIdentifier())) || type.equals(methodNode.type)
|
||||
|| getParameters().size() != methodNode.getParameters().size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.getParameters().size(); i++) {
|
||||
if (!this.getParameters().get(i).type.equals(methodNode.getParameters().get(i).type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public ITypeNode getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(ITypeNode type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setIdentifier(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package ast.parameter;
|
||||
|
||||
import ast.ASTNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ParameterListNode extends ASTNode {
|
||||
List<ParameterNode> parameters = new ArrayList<>();
|
||||
|
||||
public ParameterListNode(List<ParameterNode> parameters){
|
||||
this.parameters = parameters;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package ast.parameter;
|
||||
|
||||
import ast.ASTNode;
|
||||
import ast.type.TypeNode;
|
||||
|
||||
public class ParameterNode extends ASTNode {
|
||||
public TypeNode type;
|
||||
public String identifier;
|
||||
|
||||
public ParameterNode(TypeNode type, String identifier) {
|
||||
this.type = type;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
}
|
||||
23
src/main/java/ast/parameters/ParameterNode.java
Normal file
23
src/main/java/ast/parameters/ParameterNode.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package ast.parameters;
|
||||
|
||||
import ast.ASTNode;
|
||||
import ast.type.type.*;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class ParameterNode implements ASTNode, Visitable {
|
||||
public ITypeNode type;
|
||||
public String identifier;
|
||||
|
||||
public ParameterNode(ITypeNode type, String identifier) {
|
||||
this.type = type;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package ast.statement;
|
||||
|
||||
import ast.expression.ExpressionNode;
|
||||
|
||||
public class AssignmentStatementNode extends StatementNode {
|
||||
public String identifier;
|
||||
public ExpressionNode expression;
|
||||
|
||||
public AssignmentStatementNode(String identifier, ExpressionNode expression) {
|
||||
this.identifier = identifier;
|
||||
this.expression = expression;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package ast.statement;
|
||||
|
||||
import ast.expression.ExpressionNode;
|
||||
|
||||
public class IfStatementNode extends StatementNode {
|
||||
public ExpressionNode condition;
|
||||
public StatementNode thenStatement;
|
||||
public StatementNode elseStatement;
|
||||
|
||||
public IfStatementNode(ExpressionNode condition, StatementNode thenStatement, StatementNode elseStatement) {
|
||||
this.condition = condition;
|
||||
this.thenStatement = thenStatement;
|
||||
this.elseStatement = elseStatement;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package ast.statement;
|
||||
|
||||
import ast.expression.ExpressionNode;
|
||||
|
||||
public class ReturnStatementNode extends StatementNode {
|
||||
public ExpressionNode expression;
|
||||
|
||||
public ReturnStatementNode(ExpressionNode expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package ast.statement;
|
||||
|
||||
import ast.ASTNode;
|
||||
|
||||
public abstract class StatementNode extends ASTNode {
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
package ast.statement;
|
||||
|
||||
import ast.type.TypeNode;
|
||||
import ast.expression.ExpressionNode;
|
||||
|
||||
public class VariableDeclarationStatementNode extends StatementNode {
|
||||
public TypeNode type;
|
||||
public String identifier;
|
||||
public ExpressionNode expression;
|
||||
public VariableDeclarationStatementNode(TypeNode type, String identifier, ExpressionNode expression) {
|
||||
this.type = type;
|
||||
this.identifier = identifier;
|
||||
this.expression = expression;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package ast.statement;
|
||||
|
||||
import ast.expression.ExpressionNode;
|
||||
|
||||
public class WhileStatementNode extends StatementNode {
|
||||
public ExpressionNode condition;
|
||||
public StatementNode body;
|
||||
|
||||
public WhileStatementNode(ExpressionNode condition, StatementNode body) {
|
||||
this.condition = condition;
|
||||
this.body = body;
|
||||
}
|
||||
}
|
||||
27
src/main/java/ast/statementexpressions/AssignNode.java
Normal file
27
src/main/java/ast/statementexpressions/AssignNode.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package ast.statementexpressions;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class AssignNode implements IStatementExpressionNode {
|
||||
public AssignableNode assignable;
|
||||
public IExpressionNode expression;
|
||||
|
||||
public AssignNode(AssignableNode assignable, IExpressionNode expression) {
|
||||
this.assignable = assignable;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
35
src/main/java/ast/statementexpressions/AssignableNode.java
Normal file
35
src/main/java/ast/statementexpressions/AssignableNode.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package ast.statementexpressions;
|
||||
|
||||
import ast.expressions.unaryexpressions.MemberAccessNode;
|
||||
import ast.type.type.ITypeNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class AssignableNode implements IStatementExpressionNode {
|
||||
public String identifier;
|
||||
private ITypeNode typeNode;
|
||||
|
||||
public MemberAccessNode memberAccess;
|
||||
|
||||
public AssignableNode(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public AssignableNode(MemberAccessNode memberAccess) {
|
||||
this.memberAccess = memberAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
public ITypeNode getTypeNode() {
|
||||
return typeNode;
|
||||
}
|
||||
|
||||
public void setTypeNode(ITypeNode typeNode) {
|
||||
this.typeNode = typeNode;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package ast.statementexpressions;
|
||||
|
||||
import ast.statements.IStatementNode;
|
||||
|
||||
public interface IStatementExpressionNode extends IStatementNode {}
|
||||
@@ -0,0 +1,33 @@
|
||||
package ast.statementexpressions;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NewDeclarationNode implements IStatementExpressionNode {
|
||||
public String identifier;
|
||||
public List<IExpressionNode> expressions = new ArrayList<>();
|
||||
|
||||
public NewDeclarationNode(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public void addExpression(IExpressionNode expression) {
|
||||
expressions.add(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package ast.statementexpressions.crementexpressions;
|
||||
|
||||
public enum CrementType {
|
||||
PREFIX, SUFFIX
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package ast.statementexpressions.crementexpressions;
|
||||
|
||||
import ast.statementexpressions.AssignableNode;
|
||||
import ast.statementexpressions.IStatementExpressionNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class DecrementNode implements IStatementExpressionNode {
|
||||
public CrementType crementType;
|
||||
public AssignableNode assignableExpression;
|
||||
|
||||
public DecrementNode(CrementType crementType, AssignableNode assignableExpression) {
|
||||
this.crementType = crementType;
|
||||
this.assignableExpression = assignableExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package ast.statementexpressions.crementexpressions;
|
||||
|
||||
import ast.statementexpressions.AssignableNode;
|
||||
import ast.statementexpressions.IStatementExpressionNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class IncrementNode implements IStatementExpressionNode {
|
||||
public CrementType crementType;
|
||||
public AssignableNode assignableExpression;
|
||||
|
||||
public IncrementNode(CrementType crementType, AssignableNode assignableExpression) {
|
||||
this.crementType = crementType;
|
||||
this.assignableExpression = assignableExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package ast.statementexpressions.methodcallstatementnexpressions;
|
||||
|
||||
import ast.ASTNode;
|
||||
import ast.expressions.IExpressionNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ChainedMethodNode implements ASTNode, Visitable {
|
||||
public String identifier;
|
||||
public List<IExpressionNode> expressions = new ArrayList<>();
|
||||
|
||||
public ChainedMethodNode(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public void addExpression(IExpressionNode expression) {
|
||||
expressions.add(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package ast.statementexpressions.methodcallstatementnexpressions;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import ast.statements.IStatementNode;
|
||||
import ast.type.type.ITypeNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MethodCallNode implements IStatementNode {
|
||||
public TargetNode target;
|
||||
public ITypeNode type;
|
||||
public List<ChainedMethodNode> chainedMethods = new ArrayList<>();
|
||||
public String identifier;
|
||||
public List<IExpressionNode> parameters = new ArrayList<>();
|
||||
|
||||
public MethodCallNode(TargetNode target, String identifier) {
|
||||
this.target = target;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public void addChainedMethod(ChainedMethodNode chainedMethode) {
|
||||
chainedMethods.add(chainedMethode);
|
||||
}
|
||||
|
||||
public void addExpression(IExpressionNode parameter) {
|
||||
parameters.add(parameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package ast.statementexpressions.methodcallstatementnexpressions;
|
||||
|
||||
import ast.ASTNode;
|
||||
import ast.expressions.unaryexpressions.MemberAccessNode;
|
||||
import ast.statementexpressions.NewDeclarationNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class TargetNode implements ASTNode, Visitable {
|
||||
public Boolean thisTar;
|
||||
public MemberAccessNode memberAccess;
|
||||
public NewDeclarationNode newDeclaration;
|
||||
public String identifier;
|
||||
|
||||
public TargetNode(Boolean thisTar) {
|
||||
this.thisTar = thisTar;
|
||||
}
|
||||
|
||||
public TargetNode(MemberAccessNode memberAccess) {
|
||||
this.memberAccess = memberAccess;
|
||||
}
|
||||
|
||||
public TargetNode(NewDeclarationNode newDeclaration) {
|
||||
this.newDeclaration = newDeclaration;
|
||||
}
|
||||
|
||||
public TargetNode(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
25
src/main/java/ast/statements/BlockNode.java
Normal file
25
src/main/java/ast/statements/BlockNode.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package ast.statements;
|
||||
|
||||
import ast.ASTNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BlockNode implements IStatementNode, Visitable {
|
||||
public List<IStatementNode> statements = new ArrayList<>();
|
||||
|
||||
public BlockNode() {}
|
||||
|
||||
public void addStatement(IStatementNode statement) {
|
||||
statements.add(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
}
|
||||
10
src/main/java/ast/statements/BlockStatementNode.java
Normal file
10
src/main/java/ast/statements/BlockStatementNode.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package ast.statements;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BlockStatementNode {
|
||||
List<IStatementNode> statements;
|
||||
|
||||
public BlockStatementNode(List<IStatementNode> statements) {this.statements = statements;}
|
||||
}
|
||||
18
src/main/java/ast/statements/ElseNode.java
Normal file
18
src/main/java/ast/statements/ElseNode.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package ast.statements;
|
||||
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class ElseNode implements IStatementNode {
|
||||
public BlockNode block;
|
||||
|
||||
public ElseNode(BlockNode block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
||||
7
src/main/java/ast/statements/IStatementNode.java
Normal file
7
src/main/java/ast/statements/IStatementNode.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package ast.statements;
|
||||
|
||||
import ast.ASTNode;
|
||||
import visitor.Visitable;
|
||||
|
||||
public interface IStatementNode extends ASTNode, Visitable {
|
||||
}
|
||||
27
src/main/java/ast/statements/IfElseNode.java
Normal file
27
src/main/java/ast/statements/IfElseNode.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package ast.statements;
|
||||
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class IfElseNode implements IStatementNode {
|
||||
public IfNode ifStatement;
|
||||
public List<IfNode> elseIfStatements = new ArrayList<>();
|
||||
public ElseNode elseStatement;
|
||||
|
||||
public IfElseNode(IfNode ifStatement, ElseNode elseNode) {
|
||||
this.ifStatement = ifStatement;
|
||||
this.elseStatement = elseNode;
|
||||
}
|
||||
|
||||
public void addElseIfStatement(IfNode elseIfStament) {
|
||||
elseIfStatements.add(elseIfStament);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
||||
20
src/main/java/ast/statements/IfNode.java
Normal file
20
src/main/java/ast/statements/IfNode.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package ast.statements;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class IfNode implements IStatementNode {
|
||||
public IExpressionNode expression;
|
||||
public BlockNode block;
|
||||
|
||||
public IfNode(IExpressionNode expression, BlockNode block) {
|
||||
this.expression = expression;
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package ast.statements;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import ast.type.type.*;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class LocalVariableDeclarationNode implements IStatementNode {
|
||||
public ITypeNode type;
|
||||
public String identifier;
|
||||
public String assign;
|
||||
public IExpressionNode expression;
|
||||
|
||||
public LocalVariableDeclarationNode(ITypeNode type, String identifier, String assign, IExpressionNode expression) {
|
||||
this.type = type;
|
||||
this.identifier = identifier;
|
||||
this.assign = assign;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
30
src/main/java/ast/statements/ReturnNode.java
Normal file
30
src/main/java/ast/statements/ReturnNode.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package ast.statements;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class ReturnNode implements IStatementNode {
|
||||
public IExpressionNode expression;
|
||||
public Boolean voidReturn = false;
|
||||
|
||||
public ReturnNode(IExpressionNode expression) {
|
||||
if(expression != null) {
|
||||
this.expression = expression;
|
||||
} else {
|
||||
voidReturn = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
25
src/main/java/ast/statements/WhileNode.java
Normal file
25
src/main/java/ast/statements/WhileNode.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package ast.statements;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class WhileNode implements IStatementNode {
|
||||
public IExpressionNode expression;
|
||||
public BlockNode block;
|
||||
|
||||
public WhileNode(IExpressionNode expression, BlockNode block) {
|
||||
this.expression = expression;
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public void test() {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
||||
28
src/main/java/ast/type/AccessModifierNode.java
Normal file
28
src/main/java/ast/type/AccessModifierNode.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package ast.type;
|
||||
|
||||
public class AccessModifierNode {
|
||||
public EnumAccessModifierNode accessType;
|
||||
|
||||
public AccessModifierNode(String accessModifier) {
|
||||
setModifier(accessModifier);
|
||||
}
|
||||
|
||||
private void setModifier(String accessType) {
|
||||
switch(accessType) {
|
||||
case "public":
|
||||
this.accessType = EnumAccessModifierNode.PUBLIC;
|
||||
break;
|
||||
case "public static":
|
||||
this.accessType = EnumAccessModifierNode.PUBLIC_STATIC;
|
||||
break;
|
||||
case "private":
|
||||
this.accessType = EnumAccessModifierNode.PRIVATE;
|
||||
break;
|
||||
case "private static":
|
||||
this.accessType = EnumAccessModifierNode.PRIVATE_STATIC;
|
||||
break;
|
||||
default:
|
||||
this.accessType = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package ast.type;
|
||||
|
||||
import ast.ASTNode;
|
||||
|
||||
public class AccessTypeNode extends ASTNode {
|
||||
public EnumAccessTypeNode enumAccessTypeNode;
|
||||
|
||||
public AccessTypeNode(EnumAccessTypeNode enumAccessTypeNode) {
|
||||
this.enumAccessTypeNode = enumAccessTypeNode;
|
||||
}
|
||||
}
|
||||
6
src/main/java/ast/type/EnumAccessModifierNode.java
Normal file
6
src/main/java/ast/type/EnumAccessModifierNode.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package ast.type;
|
||||
|
||||
public enum EnumAccessModifierNode {
|
||||
PUBLIC, PRIVATE, PUBLIC_STATIC, PRIVATE_STATIC
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
package ast.type;
|
||||
|
||||
public enum EnumAccessTypeNode {
|
||||
PUBLIC, PRIVATE
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package ast.type;
|
||||
|
||||
public enum EnumTypeNode {
|
||||
INT, BOOLEAN, CHAR
|
||||
}
|
||||
5
src/main/java/ast/type/EnumValueNode.java
Normal file
5
src/main/java/ast/type/EnumValueNode.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package ast.type;
|
||||
|
||||
public enum EnumValueNode {
|
||||
INT_VALUE, BOOLEAN_VALUE, CHAR_VALUE, NULL_VALUE
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package ast.type;
|
||||
|
||||
import ast.ASTNode;
|
||||
|
||||
public class TypeNode extends ASTNode {
|
||||
public EnumTypeNode enumTypeNode;
|
||||
|
||||
public TypeNode(EnumTypeNode enumTypeNode) {
|
||||
this.enumTypeNode = enumTypeNode;
|
||||
}
|
||||
}
|
||||
27
src/main/java/ast/type/ValueNode.java
Normal file
27
src/main/java/ast/type/ValueNode.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package ast.type;
|
||||
|
||||
import ast.ASTNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class ValueNode implements ASTNode, Visitable {
|
||||
public EnumValueNode valueType;
|
||||
public String value;
|
||||
|
||||
public ValueNode(EnumValueNode valueType, String value) {
|
||||
this.valueType = valueType;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
||||
28
src/main/java/ast/type/type/BaseType.java
Normal file
28
src/main/java/ast/type/type/BaseType.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package ast.type.type;
|
||||
|
||||
public class BaseType implements ITypeNode {
|
||||
|
||||
private TypeEnum typeEnum;
|
||||
|
||||
public BaseType(TypeEnum typeEnum) {
|
||||
this.typeEnum = typeEnum;
|
||||
}
|
||||
|
||||
public TypeEnum getTypeEnum() {
|
||||
return typeEnum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
BaseType other = (BaseType) obj;
|
||||
if (typeEnum != other.typeEnum)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
5
src/main/java/ast/type/type/ITypeNode.java
Normal file
5
src/main/java/ast/type/type/ITypeNode.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package ast.type.type;
|
||||
|
||||
public interface ITypeNode {
|
||||
|
||||
}
|
||||
33
src/main/java/ast/type/type/ReferenceType.java
Normal file
33
src/main/java/ast/type/type/ReferenceType.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package ast.type.type;
|
||||
|
||||
public class ReferenceType implements ITypeNode{
|
||||
|
||||
private String identifier;
|
||||
|
||||
public ReferenceType(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ReferenceType other = (ReferenceType) obj;
|
||||
if (identifier == null) {
|
||||
if (other.identifier != null)
|
||||
return false;
|
||||
} else if (!identifier.equals(other.identifier))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
9
src/main/java/ast/type/type/TypeEnum.java
Normal file
9
src/main/java/ast/type/type/TypeEnum.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package ast.type.type;
|
||||
|
||||
public enum TypeEnum {
|
||||
VOID,
|
||||
INT,
|
||||
CHAR,
|
||||
BOOL;
|
||||
|
||||
}
|
||||
@@ -2,13 +2,89 @@ package bytecode;
|
||||
|
||||
import ast.ProgramNode;
|
||||
import ast.ClassNode;
|
||||
import ast.members.MainMethodNode;
|
||||
import ast.members.MemberNode;
|
||||
import bytecode.visitor.ProgramVisitor;
|
||||
|
||||
public class ByteCodeGenerator {
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
public void generateByteCode(ProgramNode ast) {
|
||||
for (ClassNode classDeclarationNode : ast.classes) {
|
||||
ClassCodeGen classCodeGen = new ClassCodeGen();
|
||||
classCodeGen.generateClassCode(classDeclarationNode);
|
||||
public class ByteCodeGenerator implements ProgramVisitor {
|
||||
|
||||
private JarOutputStream jarOutputStream;
|
||||
private ByteArrayOutputStream byteArrayOutputStream;
|
||||
private String outputDirectory;
|
||||
private boolean generateJar;
|
||||
private boolean generateClassFiles;
|
||||
|
||||
public ByteCodeGenerator(String outputDirectory, boolean generateJar, boolean generateClassFiles) {
|
||||
this.outputDirectory = outputDirectory;
|
||||
this.generateJar = generateJar;
|
||||
this.generateClassFiles = generateClassFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ProgramNode programNode) {
|
||||
if(generateJar) {
|
||||
byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
try {
|
||||
Manifest manifest = new Manifest();
|
||||
manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
|
||||
boolean foundMainClass = false;
|
||||
for (ClassNode classNode : programNode.classes) {
|
||||
if (foundMainClass) {
|
||||
break;
|
||||
}
|
||||
for (MemberNode memberNode : classNode.members) {
|
||||
if (memberNode instanceof MainMethodNode) {
|
||||
manifest.getMainAttributes().putValue("Main-Class", classNode.identifier);
|
||||
foundMainClass = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
jarOutputStream = new JarOutputStream(byteArrayOutputStream, manifest);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
for (ClassNode classDeclarationNode : programNode.classes) {
|
||||
ClassCodeGen classCodeGen = new ClassCodeGen(jarOutputStream, outputDirectory, generateJar, generateClassFiles);
|
||||
classDeclarationNode.accept(classCodeGen);
|
||||
}
|
||||
|
||||
try {
|
||||
jarOutputStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
saveJarFile(byteArrayOutputStream.toByteArray(), "output.jar");
|
||||
} else {
|
||||
for (ClassNode classDeclarationNode : programNode.classes) {
|
||||
ClassCodeGen classCodeGen = new ClassCodeGen(jarOutputStream, outputDirectory, generateJar, generateClassFiles);
|
||||
classDeclarationNode.accept(classCodeGen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveJarFile(byte[] jarBytes, String jarFileName) {
|
||||
File directory = new File(outputDirectory);
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs();
|
||||
}
|
||||
|
||||
File jarFile = new File(directory, jarFileName);
|
||||
try (FileOutputStream fos = new FileOutputStream(jarFile)) {
|
||||
fos.write(jarBytes);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,47 +1,79 @@
|
||||
package bytecode;
|
||||
|
||||
import ast.ClassNode;
|
||||
import ast.member.FieldNode;
|
||||
import ast.member.MemberNode;
|
||||
import ast.member.MethodNode;
|
||||
import ast.members.FieldNode;
|
||||
import ast.members.MemberNode;
|
||||
import ast.members.MethodNode;
|
||||
import ast.type.type.BaseType;
|
||||
import bytecode.visitor.ClassVisitor;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
public class ClassCodeGen {
|
||||
public void generateClassCode(ClassNode classNode) {
|
||||
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
Mapper mapper = new Mapper();
|
||||
classWriter.visit(Opcodes.V1_8, mapper.mapAccesTypeToOpcode(classNode.accessType), classNode.name, null,
|
||||
|
||||
public class ClassCodeGen implements ClassVisitor {
|
||||
private Mapper mapper;
|
||||
private ClassWriter classWriter;
|
||||
private JarOutputStream jarOutputStream;
|
||||
private String outputDirectory;
|
||||
private boolean generateJar;
|
||||
private boolean generateClassFiles;
|
||||
|
||||
public ClassCodeGen(JarOutputStream jarOutputStream, String outputDirectory, boolean generateJar, boolean generateClassFiles) {
|
||||
mapper = new Mapper();
|
||||
this.jarOutputStream = jarOutputStream;
|
||||
this.outputDirectory = outputDirectory;
|
||||
this.generateJar = generateJar;
|
||||
this.generateClassFiles = generateClassFiles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ClassNode classNode) {
|
||||
classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
classWriter.visit(Opcodes.V1_5, mapper.mapAccessTypeToOpcode(classNode.accessType), classNode.identifier, null,
|
||||
"java/lang/Object", null);
|
||||
|
||||
for (MemberNode memberNode : classNode.members) {
|
||||
if (memberNode instanceof FieldNode) {
|
||||
FieldCodeGen fieldCodeGen = new FieldCodeGen();
|
||||
fieldCodeGen.generateFieldCode(classWriter, (FieldNode) memberNode);
|
||||
visit((FieldNode) memberNode);
|
||||
} else if (memberNode instanceof MethodNode) {
|
||||
MethodCodeGen methodCodeGen = new MethodCodeGen();
|
||||
methodCodeGen.generateMethodCode(classWriter, (MethodNode) memberNode);
|
||||
MethodCodeGen methodCodeGen = new MethodCodeGen(classWriter);
|
||||
((MethodNode) memberNode).accept(methodCodeGen);
|
||||
}
|
||||
}
|
||||
|
||||
classWriter.visitEnd();
|
||||
printIntoClassFile(classWriter.toByteArray(), classNode.identifier.getName());
|
||||
if (generateJar) {
|
||||
writeToJar(classWriter.toByteArray(), classNode.identifier);
|
||||
}
|
||||
if (generateClassFiles) {
|
||||
printIntoClassFile(classWriter.toByteArray(), classNode.identifier, outputDirectory);
|
||||
}
|
||||
|
||||
classWriter.visitEnd();
|
||||
}
|
||||
|
||||
private void printIntoClassFile(byte[] byteCode, String name) {
|
||||
String directoryPath = "src/main/java/classFileOutput";
|
||||
File directory = new File(directoryPath);
|
||||
@Override
|
||||
public void visit(FieldNode fieldNode) {
|
||||
if (fieldNode.type instanceof BaseType) {
|
||||
classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar((BaseType) fieldNode.type), null, null);
|
||||
}
|
||||
classWriter.visitEnd();
|
||||
}
|
||||
|
||||
private void printIntoClassFile(byte[] byteCode, String name, String outputDirectory) {
|
||||
File directory = new File(outputDirectory);
|
||||
if (!directory.exists()) {
|
||||
directory.mkdirs();
|
||||
}
|
||||
|
||||
String filePath = directoryPath + "/" + name + ".class";
|
||||
String filePath = outputDirectory + "/" + name + ".class";
|
||||
try {
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(filePath);
|
||||
fileOutputStream.write(byteCode);
|
||||
@@ -50,4 +82,15 @@ public class ClassCodeGen {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeToJar(byte[] byteCode, String className) {
|
||||
try {
|
||||
JarEntry jarEntry = new JarEntry(className + ".class");
|
||||
jarOutputStream.putNextEntry(jarEntry);
|
||||
jarOutputStream.write(byteCode);
|
||||
jarOutputStream.closeEntry();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package bytecode;
|
||||
|
||||
import ast.member.FieldNode;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
|
||||
public class FieldCodeGen {
|
||||
|
||||
public void generateFieldCode(ClassWriter classWriter, FieldNode fieldNode) {
|
||||
Mapper mapper = new Mapper();
|
||||
FieldVisitor fieldVisitor = classWriter.visitField(mapper.mapAccesTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier.getName(), "", null, null);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,60 @@
|
||||
package bytecode;
|
||||
|
||||
import ast.type.AccessTypeNode;
|
||||
import ast.type.EnumAccessTypeNode;
|
||||
import ast.parameters.ParameterNode;
|
||||
import ast.type.*;
|
||||
import ast.type.type.BaseType;
|
||||
import ast.type.type.ReferenceType;
|
||||
import ast.type.type.TypeEnum;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Mapper {
|
||||
public int mapAccesTypeToOpcode(AccessTypeNode type) {
|
||||
switch (type.enumAccessTypeNode) {
|
||||
case EnumAccessTypeNode.PUBLIC:
|
||||
public int mapAccessTypeToOpcode(AccessModifierNode accessModifierNode) {
|
||||
switch (accessModifierNode.accessType) {
|
||||
case EnumAccessModifierNode.PUBLIC:
|
||||
return Opcodes.ACC_PUBLIC;
|
||||
case EnumAccessTypeNode.PRIVATE:
|
||||
case EnumAccessModifierNode.PRIVATE:
|
||||
return Opcodes.ACC_PRIVATE;
|
||||
case EnumAccessModifierNode.PUBLIC_STATIC:
|
||||
return Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC;
|
||||
case EnumAccessModifierNode.PRIVATE_STATIC:
|
||||
return Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String generateMethodDescriptor(BaseType type, List<ParameterNode> parameters) {
|
||||
String descriptor = "(";
|
||||
for (ParameterNode parameterNode : parameters) {
|
||||
if(parameterNode.type instanceof BaseType) {
|
||||
descriptor += getTypeChar((BaseType) parameterNode.type);
|
||||
} else {
|
||||
ReferenceType referenceType = (ReferenceType) parameterNode.type;
|
||||
descriptor += "L" + referenceType.getIdentifier() + ";";
|
||||
}
|
||||
}
|
||||
descriptor += ")";
|
||||
descriptor += getTypeChar(type);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public String getTypeChar(BaseType type) {
|
||||
String typeChar = "";
|
||||
switch (type.getTypeEnum()) {
|
||||
case TypeEnum.INT:
|
||||
typeChar = "I";
|
||||
break;
|
||||
case TypeEnum.CHAR:
|
||||
typeChar = "C";
|
||||
break;
|
||||
case TypeEnum.BOOL:
|
||||
typeChar = "Z";
|
||||
break;
|
||||
case TypeEnum.VOID:
|
||||
typeChar = "V";
|
||||
break;
|
||||
}
|
||||
return typeChar;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,536 @@
|
||||
package bytecode;
|
||||
|
||||
import ast.member.MethodNode;
|
||||
import ast.expressions.IExpressionNode;
|
||||
import ast.expressions.binaryexpressions.*;
|
||||
import ast.expressions.unaryexpressions.MemberAccessNode;
|
||||
import ast.expressions.unaryexpressions.NotNode;
|
||||
import ast.expressions.unaryexpressions.UnaryNode;
|
||||
import ast.members.ConstructorNode;
|
||||
import ast.members.MainMethodNode;
|
||||
import ast.members.MethodNode;
|
||||
import ast.parameters.ParameterNode;
|
||||
import ast.statementexpressions.AssignNode;
|
||||
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;
|
||||
import ast.type.type.ReferenceType;
|
||||
import ast.type.type.TypeEnum;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
public class MethodCodeGen {
|
||||
public void generateMethodCode(ClassWriter classWriter, MethodNode methodNode) {
|
||||
Mapper mapper = new Mapper();
|
||||
MethodVisitor constructor =
|
||||
classWriter.visitMethod(mapper.mapAccesTypeToOpcode(methodNode.visibility),
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
|
||||
public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
|
||||
private ClassWriter classWriter;
|
||||
private Mapper mapper;
|
||||
private MethodVisitor methodVisitor;
|
||||
|
||||
private List<String> localVariables;
|
||||
|
||||
public MethodCodeGen(ClassWriter classWriter) {
|
||||
this.classWriter = classWriter;
|
||||
mapper = new Mapper();
|
||||
localVariables = new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
// Method nodes
|
||||
|
||||
@Override
|
||||
public void visit(ConstructorNode constructorNode) {
|
||||
methodVisitor =
|
||||
classWriter.visitMethod(mapper.mapAccessTypeToOpcode(constructorNode.accessType),
|
||||
"<init>",
|
||||
"()V",
|
||||
mapper.generateMethodDescriptor(new BaseType(TypeEnum.VOID), constructorNode.parameters),
|
||||
null,
|
||||
null);
|
||||
|
||||
methodVisitor.visitCode();
|
||||
localVariables.add("this");
|
||||
// Add all method parameters to localVariables
|
||||
for (ParameterNode parameterNode : constructorNode.parameters) {
|
||||
localVariables.add(parameterNode.identifier);
|
||||
}
|
||||
|
||||
methodVisitor.visitVarInsn(ALOAD, 0);
|
||||
methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||
|
||||
// Visit all statements
|
||||
for (IStatementNode statementNode : constructorNode.block.statements) {
|
||||
if (statementNode != null) {
|
||||
statementNode.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
methodVisitor.visitMaxs(0, 0);
|
||||
methodVisitor.visitEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MainMethodNode mainMethodNode) {
|
||||
methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(mainMethodNode.accesModifier),
|
||||
mainMethodNode.getIdentifier(),
|
||||
"([Ljava/lang/String;)V",
|
||||
null,
|
||||
null);
|
||||
|
||||
methodVisitor.visitCode();
|
||||
localVariables.add("this");
|
||||
localVariables.add("args");
|
||||
|
||||
// Visit all statements
|
||||
for (IStatementNode statementNode : mainMethodNode.block.statements) {
|
||||
statementNode.accept(this);
|
||||
}
|
||||
|
||||
methodVisitor.visitMaxs(0, 0);
|
||||
methodVisitor.visitEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MethodNode methodNode) {
|
||||
methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.accesModifier),
|
||||
methodNode.getIdentifier(),
|
||||
mapper.generateMethodDescriptor((BaseType) methodNode.getType(), methodNode.parameters),
|
||||
null,
|
||||
null);
|
||||
|
||||
methodVisitor.visitCode();
|
||||
localVariables.add("this");
|
||||
// Add all method parameters to localVariables
|
||||
for (ParameterNode parameterNode : methodNode.parameters) {
|
||||
localVariables.add(parameterNode.identifier);
|
||||
}
|
||||
|
||||
// Visit all statements
|
||||
for (IStatementNode statementNode : methodNode.block.statements) {
|
||||
statementNode.accept(this);
|
||||
}
|
||||
|
||||
methodVisitor.visitMaxs(0, 0);
|
||||
methodVisitor.visitEnd();
|
||||
}
|
||||
|
||||
|
||||
// Binary expressions
|
||||
|
||||
@Override
|
||||
public void visit(BinaryNode binaryNode) {
|
||||
binaryNode.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(CalculationNode calculationNode) {
|
||||
if (calculationNode.dotExpression != null) {
|
||||
calculationNode.dotExpression.accept(this);
|
||||
}
|
||||
if (calculationNode.calculationExpression != null) {
|
||||
calculationNode.calculationExpression.accept(this);
|
||||
}
|
||||
if (calculationNode.operator != null) {
|
||||
switch (calculationNode.operator) {
|
||||
case PLUS:
|
||||
methodVisitor.visitInsn(IADD);
|
||||
break;
|
||||
case MINUS:
|
||||
methodVisitor.visitInsn(ISUB);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(DotNode dotNode) {
|
||||
if (dotNode.dotExpression != null) {
|
||||
dotNode.dotExpression.accept(this);
|
||||
}
|
||||
if (dotNode.dotSubstractionExpression != null) {
|
||||
dotNode.dotSubstractionExpression.accept(this);
|
||||
}
|
||||
if (dotNode.operator != null) {
|
||||
switch (dotNode.operator) {
|
||||
case DIV:
|
||||
methodVisitor.visitInsn(IDIV);
|
||||
break;
|
||||
case MULT:
|
||||
methodVisitor.visitInsn(IMUL);
|
||||
break;
|
||||
case MOD:
|
||||
methodVisitor.visitInsn(IREM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(DotSubstractionNode dotSubstractionNode) {
|
||||
if (dotSubstractionNode.value != null) {
|
||||
dotSubstractionNode.value.accept(this);
|
||||
} else if (dotSubstractionNode.identifier != null) {
|
||||
methodVisitor.visitVarInsn(ILOAD, localVariables.indexOf(dotSubstractionNode.identifier));
|
||||
} else if (dotSubstractionNode.memberAccess != null) {
|
||||
dotSubstractionNode.memberAccess.accept(this);
|
||||
} else if (dotSubstractionNode.methodCall != null) {
|
||||
dotSubstractionNode.methodCall.accept(this);
|
||||
} else if (dotSubstractionNode.calculationExpression != null) {
|
||||
dotSubstractionNode.calculationExpression.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NonCalculationNode nonCalculationNode) {
|
||||
Label labelFalse = new Label();
|
||||
Label labelTrue = new Label();
|
||||
switch (nonCalculationNode.operator) {
|
||||
case AND:
|
||||
nonCalculationNode.unaryExpression.accept(this);
|
||||
methodVisitor.visitJumpInsn(IFEQ, labelFalse); // Value compared to 0 (false)
|
||||
nonCalculationNode.expression.accept(this);
|
||||
methodVisitor.visitJumpInsn(IFEQ, labelFalse);
|
||||
break;
|
||||
case OR:
|
||||
nonCalculationNode.unaryExpression.accept(this);
|
||||
methodVisitor.visitJumpInsn(IFNE, labelTrue);
|
||||
nonCalculationNode.expression.accept(this);
|
||||
methodVisitor.visitJumpInsn(IFEQ, labelFalse);
|
||||
break;
|
||||
case GREATER:
|
||||
nonCalculationNode.unaryExpression.accept(this);
|
||||
nonCalculationNode.expression.accept(this);
|
||||
methodVisitor.visitJumpInsn(IF_ICMPLE, labelFalse);
|
||||
break;
|
||||
case LESS:
|
||||
nonCalculationNode.unaryExpression.accept(this);
|
||||
nonCalculationNode.expression.accept(this);
|
||||
methodVisitor.visitJumpInsn(IF_ICMPGE, labelFalse);
|
||||
break;
|
||||
case GREATER_EQUAL:
|
||||
nonCalculationNode.unaryExpression.accept(this);
|
||||
nonCalculationNode.expression.accept(this);
|
||||
methodVisitor.visitJumpInsn(IF_ICMPLT, labelFalse);
|
||||
break;
|
||||
case LESS_EQUAL:
|
||||
nonCalculationNode.unaryExpression.accept(this);
|
||||
nonCalculationNode.expression.accept(this);
|
||||
methodVisitor.visitJumpInsn(IF_ICMPGT, labelFalse);
|
||||
break;
|
||||
case EQUAL:
|
||||
nonCalculationNode.unaryExpression.accept(this);
|
||||
nonCalculationNode.expression.accept(this);
|
||||
if (nonCalculationNode.unaryExpression.getType() instanceof BaseType && nonCalculationNode.expression.getType() instanceof BaseType) {
|
||||
methodVisitor.visitJumpInsn(IF_ICMPNE, labelFalse);
|
||||
} else {
|
||||
methodVisitor.visitJumpInsn(IF_ACMPNE, labelFalse);
|
||||
}
|
||||
break;
|
||||
case NOT_EQUAL:
|
||||
nonCalculationNode.unaryExpression.accept(this);
|
||||
nonCalculationNode.expression.accept(this);
|
||||
if (nonCalculationNode.unaryExpression.getType() instanceof BaseType && nonCalculationNode.expression.getType() instanceof BaseType) {
|
||||
methodVisitor.visitJumpInsn(IF_ACMPEQ, labelFalse);
|
||||
} else {
|
||||
methodVisitor.visitJumpInsn(IF_ACMPEQ, labelFalse);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Label labelEndLogicalExpression = new Label();
|
||||
|
||||
methodVisitor.visitLabel(labelTrue);
|
||||
methodVisitor.visitInsn(ICONST_1); // true
|
||||
methodVisitor.visitJumpInsn(GOTO, labelEndLogicalExpression);
|
||||
|
||||
methodVisitor.visitLabel(labelFalse);
|
||||
methodVisitor.visitInsn(ICONST_0); // false
|
||||
|
||||
methodVisitor.visitLabel(labelEndLogicalExpression);
|
||||
}
|
||||
|
||||
|
||||
// Unary expressions
|
||||
|
||||
@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
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NotNode notNode) {
|
||||
Label labelFalse = new Label();
|
||||
Label labelTrue = new Label();
|
||||
|
||||
notNode.expression.accept(this);
|
||||
methodVisitor.visitJumpInsn(Opcodes.IFNE, labelFalse); // false if value is true (value != 0)
|
||||
|
||||
Label labelEndLogicalExpression = new Label();
|
||||
|
||||
methodVisitor.visitLabel(labelTrue);
|
||||
methodVisitor.visitInsn(ICONST_1); // true
|
||||
methodVisitor.visitJumpInsn(GOTO, labelEndLogicalExpression);
|
||||
|
||||
methodVisitor.visitLabel(labelFalse);
|
||||
methodVisitor.visitInsn(ICONST_0); // false
|
||||
|
||||
methodVisitor.visitLabel(labelEndLogicalExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(UnaryNode unaryNode) {
|
||||
if (unaryNode.thisExp != null) {
|
||||
methodVisitor.visitVarInsn(ALOAD, 0); // this
|
||||
} else if (unaryNode.identifier != null) {
|
||||
methodVisitor.visitVarInsn(ILOAD, localVariables.indexOf(unaryNode.identifier));
|
||||
} else if (unaryNode.memberAccess != null) {
|
||||
unaryNode.memberAccess.accept(this);
|
||||
} else if (unaryNode.value != null) {
|
||||
unaryNode.value.accept(this);
|
||||
} else if (unaryNode.notExpression != null) {
|
||||
unaryNode.notExpression.accept(this);
|
||||
} else if (unaryNode.statement != null) {
|
||||
unaryNode.statement.accept(this);
|
||||
} else if (unaryNode.expression != null) {
|
||||
unaryNode.expression.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Statements
|
||||
|
||||
@Override
|
||||
public void visit(IfElseNode ifElseNode) {
|
||||
Label elseLabel = new Label();
|
||||
|
||||
Label[] elseIfLabels = new Label[ifElseNode.elseIfStatements.size()];
|
||||
for (int i = 0; i < ifElseNode.elseIfStatements.size(); i++) {
|
||||
elseIfLabels[i] = new Label();
|
||||
}
|
||||
|
||||
ifElseNode.ifStatement.expression.accept(this);
|
||||
if (ifElseNode.elseIfStatements.isEmpty()) {
|
||||
// No else if
|
||||
methodVisitor.visitJumpInsn(IFEQ, elseLabel);
|
||||
} else {
|
||||
// else if statements
|
||||
methodVisitor.visitJumpInsn(IFEQ, elseIfLabels[0]);
|
||||
}
|
||||
ifElseNode.ifStatement.block.accept(this); // accept if block
|
||||
|
||||
Label endLabel = new Label();
|
||||
methodVisitor.visitJumpInsn(GOTO, endLabel);
|
||||
|
||||
for (int i = 0; i < ifElseNode.elseIfStatements.size(); i++) {
|
||||
methodVisitor.visitLabel(elseIfLabels[i]);
|
||||
ifElseNode.elseIfStatements.get(i).expression.accept(this);
|
||||
if (i + 1 < elseIfLabels.length) {
|
||||
// at least one more else if
|
||||
methodVisitor.visitJumpInsn(IFEQ, elseIfLabels[i + 1]);
|
||||
} else {
|
||||
methodVisitor.visitJumpInsn(IFEQ, elseLabel);
|
||||
}
|
||||
ifElseNode.elseIfStatements.get(i).block.accept(this);
|
||||
methodVisitor.visitJumpInsn(GOTO, endLabel);
|
||||
}
|
||||
|
||||
if (ifElseNode.elseStatement != null) {
|
||||
methodVisitor.visitLabel(elseLabel);
|
||||
ifElseNode.elseStatement.block.accept(this);
|
||||
}
|
||||
|
||||
methodVisitor.visitLabel(endLabel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LocalVariableDeclarationNode localVariableDeclarationNode) {
|
||||
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 {
|
||||
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));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!localVariables.contains(localVariableDeclarationNode.identifier)) {
|
||||
localVariables.add(localVariableDeclarationNode.identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(AssignNode assignNode) {
|
||||
// Process expression
|
||||
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);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
} else {
|
||||
assignNode.expression.accept(this);
|
||||
assign(assignNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void assign(AssignNode assignNode) {
|
||||
if (assignNode.assignable.memberAccess.thisExpr) {
|
||||
assignField(assignNode);
|
||||
} else {
|
||||
assignLocalVar(assignNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void assignLocalVar(AssignNode assignNode) {
|
||||
if (assignNode.expression instanceof BaseType) {
|
||||
methodVisitor.visitVarInsn(ISTORE, localVariables.indexOf(assignNode.assignable.identifier));
|
||||
} else if (assignNode.expression instanceof ReferenceType) {
|
||||
methodVisitor.visitVarInsn(ASTORE, localVariables.indexOf(assignNode.assignable.identifier));
|
||||
}
|
||||
}
|
||||
|
||||
private void assignField(AssignNode 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()+";");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NewDeclarationNode newDeclarationNode) {
|
||||
methodVisitor.visitTypeInsn(NEW, newDeclarationNode.identifier);
|
||||
methodVisitor.visitInsn(DUP);
|
||||
List<ParameterNode> parameterNodes = new ArrayList<>();
|
||||
for (IExpressionNode expressionNode : newDeclarationNode.expressions) {
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ValueNode valueNode) {
|
||||
switch (valueNode.valueType) {
|
||||
case INT_VALUE:
|
||||
int intValue = Integer.parseInt(valueNode.value);
|
||||
if (intValue >= Byte.MIN_VALUE && intValue <= Byte.MAX_VALUE) { // load int as byte
|
||||
methodVisitor.visitIntInsn(BIPUSH, intValue);
|
||||
} else if (intValue >= Short.MIN_VALUE && intValue <= Short.MAX_VALUE) { // load int as short
|
||||
methodVisitor.visitIntInsn(SIPUSH, intValue);
|
||||
} else { // load int as const
|
||||
methodVisitor.visitLdcInsn(intValue);
|
||||
}
|
||||
break;
|
||||
case BOOLEAN_VALUE:
|
||||
if (valueNode.value.equals("true")) {
|
||||
methodVisitor.visitInsn(ICONST_1);
|
||||
} else {
|
||||
methodVisitor.visitInsn(ICONST_0);
|
||||
}
|
||||
break;
|
||||
case CHAR_VALUE:
|
||||
char charValue = valueNode.value.charAt(0);
|
||||
if (charValue <= Byte.MAX_VALUE) { // load char as byte
|
||||
methodVisitor.visitIntInsn(BIPUSH, charValue);
|
||||
} else if (charValue <= Short.MAX_VALUE) { // load char as short
|
||||
methodVisitor.visitIntInsn(SIPUSH, charValue);
|
||||
} else { // load char as const
|
||||
methodVisitor.visitLdcInsn(charValue);
|
||||
}
|
||||
break;
|
||||
case NULL_VALUE:
|
||||
methodVisitor.visitInsn(ACONST_NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ReturnNode returnNode) {
|
||||
if (returnNode.voidReturn) { // Return nothing
|
||||
methodVisitor.visitInsn(RETURN);
|
||||
} else { // Return something
|
||||
// Process expression
|
||||
returnNode.expression.accept(this);
|
||||
// Return result of expression
|
||||
if (returnNode.expression.getType() instanceof BaseType) {
|
||||
methodVisitor.visitInsn(IRETURN);
|
||||
} else if (returnNode.expression.getType() instanceof ReferenceType) {
|
||||
methodVisitor.visitInsn(ARETURN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void visit(WhileNode whileNode) {
|
||||
Label loopLabel = new Label();
|
||||
Label endOfLoopLabel = new Label();
|
||||
|
||||
methodVisitor.visitLabel(loopLabel);
|
||||
// while loop
|
||||
whileNode.expression.accept(this);
|
||||
methodVisitor.visitJumpInsn(IFEQ, endOfLoopLabel); // if condition is false, jump out of loop
|
||||
|
||||
whileNode.block.accept(this);
|
||||
methodVisitor.visitJumpInsn(GOTO, loopLabel);
|
||||
|
||||
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) {
|
||||
expressionNode.accept(this);
|
||||
parameterNodes.add(new ParameterNode(expressionNode.getType(), ""));
|
||||
}
|
||||
// TODO: Klassenname und Returntype
|
||||
//methodVisitor.visitMethodInsn(INVOKEVIRTUAL, classname, methodCallNode.identifier, mapper.generateMethodDescriptor(returntype, parameterNodes), false);
|
||||
}
|
||||
}
|
||||
|
||||
10
src/main/java/bytecode/visitor/ClassVisitor.java
Normal file
10
src/main/java/bytecode/visitor/ClassVisitor.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package bytecode.visitor;
|
||||
|
||||
import ast.ClassNode;
|
||||
import ast.members.FieldNode;
|
||||
|
||||
public interface ClassVisitor {
|
||||
void visit(ClassNode classNode);
|
||||
|
||||
void visit(FieldNode fieldNode);
|
||||
}
|
||||
56
src/main/java/bytecode/visitor/MethodVisitor.java
Normal file
56
src/main/java/bytecode/visitor/MethodVisitor.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package bytecode.visitor;
|
||||
|
||||
import ast.expressions.binaryexpressions.*;
|
||||
import ast.expressions.unaryexpressions.MemberAccessNode;
|
||||
import ast.expressions.unaryexpressions.NotNode;
|
||||
import ast.expressions.unaryexpressions.UnaryNode;
|
||||
import ast.members.ConstructorNode;
|
||||
import ast.members.MainMethodNode;
|
||||
import ast.members.MethodNode;
|
||||
import ast.statementexpressions.AssignNode;
|
||||
import ast.statementexpressions.AssignableNode;
|
||||
import ast.statementexpressions.NewDeclarationNode;
|
||||
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;
|
||||
|
||||
public interface MethodVisitor {
|
||||
// members
|
||||
void visit(ConstructorNode constructorNode);
|
||||
void visit(MethodNode methodNode);
|
||||
void visit(MainMethodNode mainMethodNode);
|
||||
|
||||
// Binary expressions
|
||||
void visit(BinaryNode binaryNode);
|
||||
void visit(CalculationNode calculationNode);
|
||||
void visit(DotNode dotNode);
|
||||
void visit(DotSubstractionNode dotSubstractionNode);
|
||||
void visit(NonCalculationNode nonCalculationNode);
|
||||
|
||||
// Unary expressions
|
||||
void visit(MemberAccessNode memberAccessNode);
|
||||
void visit(NotNode notExpressionNode);
|
||||
void visit(UnaryNode unaryExpressionNode);
|
||||
|
||||
// statements
|
||||
void visit(IfElseNode ifElseNode);
|
||||
|
||||
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);
|
||||
void visit(NewDeclarationNode newDeclarationNode);
|
||||
|
||||
// type
|
||||
void visit(ValueNode valueNode);
|
||||
|
||||
}
|
||||
7
src/main/java/bytecode/visitor/ProgramVisitor.java
Normal file
7
src/main/java/bytecode/visitor/ProgramVisitor.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package bytecode.visitor;
|
||||
|
||||
import ast.ProgramNode;
|
||||
|
||||
public interface ProgramVisitor {
|
||||
void visit(ProgramNode programNode);
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
119
src/main/java/main/Main.java
Normal file
119
src/main/java/main/Main.java
Normal file
@@ -0,0 +1,119 @@
|
||||
package main;
|
||||
|
||||
import ast.ASTNode;
|
||||
import ast.ProgramNode;
|
||||
import parser.astBuilder.ASTBuilder;
|
||||
import parser.generated.SimpleJavaLexer;
|
||||
import parser.generated.SimpleJavaParser;
|
||||
import semantic.SemanticAnalyzer;
|
||||
import bytecode.ByteCodeGenerator;
|
||||
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
/**
|
||||
* Start Raupenpiler using make:
|
||||
* <p> <code> cd .\src\test\ </code>
|
||||
* <p> <code> make clean compile-raupenpiler </code>
|
||||
* <p> Start Raupenpiler using jar:
|
||||
* <p> <code> java.exe -DgenJar=true_OR_false -DgenClass=true_OR_false -jar path_to_jar\JavaCompiler-1.0-jar-with-dependencies.jar 'path_to_input_file.java' 'path_to_output_directory' </code>
|
||||
* <p> Example (jar needs to be in the target directory, compile with make or mvn package first):
|
||||
* <code> java.exe -DgenJar=true -DgenClass=true -jar .\target\JavaCompiler-1.0-jar-with-dependencies.jar 'src/main/resources/input/CompilerInput.java' 'src/main/resources/output' </code>
|
||||
*/
|
||||
public class Main {
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length == 2) {
|
||||
// args[0] is the input file path
|
||||
// args[1] is the output directory path
|
||||
String inputFilePath = args[0];
|
||||
String outputDirectoryPath = args[1];
|
||||
System.out.println("Compiling file: " + inputFilePath);
|
||||
try {
|
||||
CharStream inputCharStream = CharStreams.fromPath(Paths.get(inputFilePath));
|
||||
compileFile(inputCharStream, outputDirectoryPath);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error reading the file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
/* !!! Else Branch (main ohne args starten) ist nicht zur Verwendung vorgesehen, immer mit args starten !!!
|
||||
else {
|
||||
try {
|
||||
CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/input/CompilerInput.java"));
|
||||
compileFile(codeCharStream);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error reading the file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to compile a file from a given CharStream and output the bytecode to a specified directory.
|
||||
* It goes through the following steps:
|
||||
* <p>1. Scanner: It uses the SimpleJavaLexer to tokenize the input CharStream.
|
||||
* <p>2. Parser: It uses the SimpleJavaParser to parse the tokens and generate a ParseTree.
|
||||
* <p>3. AST Builder: It uses the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST).
|
||||
* <p>4. Semantic Analyzer: It uses the SemanticAnalyzer to generate a typed AST.
|
||||
* <p>5. Bytecode Generator: It uses the ByteCodeGenerator to generate bytecode from the typed AST and output it to the specified directory.
|
||||
*
|
||||
* @param inputCharStream The CharStream representing the input file to be compiled.
|
||||
* @param outputDirectoryPath The path of the directory where the output bytecode should be written.
|
||||
*/
|
||||
static void compileFile(CharStream inputCharStream, String outputDirectoryPath) {
|
||||
// Initialize the logger
|
||||
new RaupenLogger();
|
||||
|
||||
/* ------------------------- Scanner -> tokens ------------------------- */
|
||||
// Use the SimpleJavaLexer to tokenize the input CharStream
|
||||
SimpleJavaLexer lexer = new SimpleJavaLexer(inputCharStream);
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
tokenStream.fill();
|
||||
// Log the tokens
|
||||
RaupenLogger.logScanner(tokenStream);
|
||||
|
||||
/*------------------------- Parser -> Parsetree -------------------------*/
|
||||
// Use the SimpleJavaParser to parse the tokens and generate a ParseTree
|
||||
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
|
||||
ParseTree parseTree = parser.program(); // parse the input
|
||||
// Log the ParseTree
|
||||
RaupenLogger.logParser(parseTree, parser);
|
||||
|
||||
/*------------------------- AST builder -> AST -------------------------*/
|
||||
// Use the ASTBuilder to visit the ParseTree and generate an Abstract Syntax Tree (AST)
|
||||
ASTBuilder astBuilder = new ASTBuilder();
|
||||
ASTNode abstractSyntaxTree = astBuilder.visit(parseTree);
|
||||
// Log the AST
|
||||
RaupenLogger.logAST(abstractSyntaxTree);
|
||||
|
||||
/*------------------------- Semantic Analyzer -> typed AST -------------------------*/
|
||||
// Use the SemanticAnalyzer to generate a typed AST
|
||||
ASTNode typedAst = SemanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
// Log the typed AST
|
||||
RaupenLogger.logSemanticAnalyzer(typedAst);
|
||||
|
||||
if(SemanticAnalyzer.errors.isEmpty()){
|
||||
/*------------------------- Bytecode Generator -> Bytecode -------------------------*/
|
||||
// Use the ByteCodeGenerator to generate bytecode from the typed AST and output it to the specified directory
|
||||
|
||||
final boolean genJar = Optional.ofNullable(System.getProperty("genJar")).map(String::toLowerCase).map(Boolean::parseBoolean).orElse(true);
|
||||
final boolean genClass = Optional.ofNullable(System.getProperty("genClass")).map(String::toLowerCase).map(Boolean::parseBoolean).orElse(true);
|
||||
|
||||
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(outputDirectoryPath, genJar, genClass);
|
||||
assert typedAst != null;
|
||||
byteCodeGenerator.visit((ProgramNode) typedAst);
|
||||
// Log the bytecode generation
|
||||
RaupenLogger.logBytecodeGenerator();
|
||||
} else {
|
||||
for(Exception exception : SemanticAnalyzer.errors){
|
||||
exception.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
180
src/main/java/main/RaupenLogger.java
Normal file
180
src/main/java/main/RaupenLogger.java
Normal file
@@ -0,0 +1,180 @@
|
||||
package main;
|
||||
|
||||
import ast.ASTNode;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.Parser;
|
||||
import org.antlr.v4.runtime.RuleContext;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import parser.generated.SimpleJavaLexer;
|
||||
import parser.generated.SimpleJavaParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.logging.*;
|
||||
|
||||
/**
|
||||
* Beispiel für Logging-Arten:
|
||||
* <p><code>logger.severe("Schwerwiegender Fehler");</code>
|
||||
* <p><code>logger.warning("Warnung");</code>
|
||||
* <p><code>logger.info("Information");</code>
|
||||
* <p><code>logger.config("Konfigurationshinweis");</code>
|
||||
* <p><code>logger.fine("Fein");</code>
|
||||
* <p><code>logger.finer("Feiner");</code>
|
||||
* <p><code>logger.finest("Am feinsten");</code>
|
||||
* <p>You may toggle the logging level of the console and file handlers by
|
||||
* changing the level ALL/OFF/etc. in the constructor.
|
||||
* <code>consoleHandler.setLevel(Level.OFF);</code>
|
||||
* <code>fileHandler.setLevel(Level.ALL);</code>
|
||||
*/
|
||||
public class RaupenLogger {
|
||||
|
||||
static Logger logger = Logger.getLogger("RaupenLogs");
|
||||
|
||||
public RaupenLogger() {
|
||||
// ------------------------- Logging -------------------------
|
||||
logger.setLevel(Level.ALL);
|
||||
logger.getParent().getHandlers()[0].setLevel(Level.ALL);
|
||||
logger.setUseParentHandlers(false);
|
||||
|
||||
// Custom formatter class
|
||||
class CustomFormatter extends Formatter {
|
||||
private final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss dd-MM-yyyy");
|
||||
|
||||
@Override
|
||||
public String format(LogRecord record) {
|
||||
return formatMessage(record) + System.lineSeparator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHead(Handler h) {
|
||||
Date now = new Date();
|
||||
String dateTime = dateFormat.format(now);
|
||||
return "Log Start Time: " + dateTime + "\n"
|
||||
+ "Logger Name: " + h.getFormatter().getClass().getName() + "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Configure console handler
|
||||
Handler consoleHandler = new ConsoleHandler();
|
||||
// Toggle console logging on/off
|
||||
consoleHandler.setLevel(Level.OFF);
|
||||
consoleHandler.setFormatter(new CustomFormatter());
|
||||
logger.addHandler(consoleHandler);
|
||||
|
||||
// Configure file handler
|
||||
Handler fileHandler = new FileHandler("src/main/resources/logs/RaupenLog.log");
|
||||
// Toggle file logging on/off
|
||||
fileHandler.setLevel(Level.ALL);
|
||||
fileHandler.setFormatter(new CustomFormatter());
|
||||
logger.addHandler(fileHandler);
|
||||
|
||||
} catch (SecurityException | IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void logScanner(CommonTokenStream tokenStream) {
|
||||
// Printing the tokens
|
||||
logger.info("-------------------- Scanner -> Tokens --------------------");
|
||||
List<Token> tokens = tokenStream.getTokens();
|
||||
for (Token token : tokens) {
|
||||
String tokenType =
|
||||
SimpleJavaLexer.VOCABULARY.getSymbolicName(token.getType());
|
||||
String tokenText = token.getText();
|
||||
// logger.info("Token Type: " + tokenType + ", Token Text: " + tokenText);
|
||||
logger.info(tokenType + " " + tokenText);
|
||||
}
|
||||
logger.info("\n");
|
||||
}
|
||||
|
||||
public static void logParser(ParseTree parseTree, SimpleJavaParser parser) {
|
||||
// Printing the parse tree
|
||||
logger.info("-------------------- Parser -> Parsetree --------------------");
|
||||
logger.info(parseTree.toStringTree(parser)); //one line representation
|
||||
logTree(parseTree, parser, 0);
|
||||
logger.info("\n");
|
||||
}
|
||||
|
||||
public static void logAST(ASTNode abstractSyntaxTree) {
|
||||
// Printing the AST
|
||||
logger.info("-------------------- AST builder -> AST --------------------");
|
||||
// logger.info("AST: " + ast.toString());
|
||||
logAST(abstractSyntaxTree, 0);
|
||||
logger.info("\n");
|
||||
}
|
||||
|
||||
public static void logSemanticAnalyzer(ASTNode typedAst) {
|
||||
// Printing the typed AST
|
||||
logger.info("-------------------- Semantic Analyzer -> typed AST --------------------");
|
||||
logAST(typedAst, 0);
|
||||
logger.info("\n");
|
||||
}
|
||||
|
||||
public static void logBytecodeGenerator() {
|
||||
// Printing the bytecode
|
||||
logger.info("-------------------- Bytecode Generator -> Bytecode --------------------");
|
||||
logger.info("Bytecode generated");
|
||||
logger.info("\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ------------------------- Printing methods ------------------------- */
|
||||
|
||||
/**
|
||||
* This method is used to print the parse tree in a structured format.
|
||||
* It recursively traverses the tree and prints the rule names and text of the
|
||||
* nodes.
|
||||
*
|
||||
* @param tree The parse tree to be printed.
|
||||
* @param parser The parser used to parse the input. It's used to get the rule
|
||||
* names.
|
||||
* @param indent The current indentation level. It's used to format the output.
|
||||
*/
|
||||
public static void logTree(ParseTree tree, Parser parser, int indent) {
|
||||
// Create an indentation string based on the current indentation level
|
||||
String indentString = " ".repeat(indent * 2);
|
||||
|
||||
// If the tree node is an instance of RuleContext (i.e., it's an internal node),
|
||||
// print the rule name
|
||||
if (tree instanceof RuleContext) {
|
||||
int ruleIndex = ((RuleContext) tree).getRuleIndex();
|
||||
String ruleName = parser.getRuleNames()[ruleIndex];
|
||||
logger.info(indentString + ruleName);
|
||||
} else {
|
||||
// If the tree node is not an instance of RuleContext (i.e., it's a leaf node),
|
||||
// print the text of the node
|
||||
logger.info(indentString + tree.getText());
|
||||
}
|
||||
|
||||
// Recursively print the children of the current node, increasing the
|
||||
// indentation level
|
||||
for (int i = 0; i < tree.getChildCount(); i++) {
|
||||
logTree(tree.getChild(i), parser, indent + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Fix this method
|
||||
public static void logAST(ASTNode abstractSyntaxTree, int indent) {
|
||||
if (abstractSyntaxTree == null) {
|
||||
logger.severe("AST is null !!!");
|
||||
return;
|
||||
}
|
||||
String indentString = " ".repeat(indent * 2);
|
||||
logger.info(indentString + abstractSyntaxTree.getClass());
|
||||
//for (ASTNode child : abstractSyntaxTree.getChildren()) {
|
||||
// logAST(child, indent + 1);
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
package parser;
|
||||
|
||||
import ast.*;
|
||||
import ast.expression.BinaryExpressionNode;
|
||||
import ast.expression.ExpressionNode;
|
||||
import ast.expression.IdentifierExpressionNode;
|
||||
import ast.expression.UnaryExpressionNode;
|
||||
import ast.member.FieldNode;
|
||||
import ast.member.MemberNode;
|
||||
import ast.member.MethodNode;
|
||||
import ast.parameter.ParameterListNode;
|
||||
import ast.parameter.ParameterNode;
|
||||
import ast.statement.*;
|
||||
import ast.type.AccessTypeNode;
|
||||
import ast.type.EnumAccessTypeNode;
|
||||
import ast.type.EnumTypeNode;
|
||||
import ast.type.TypeNode;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
import parser.generated.SimpleJavaBaseVisitor;
|
||||
import parser.generated.SimpleJavaParser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
|
||||
@Override
|
||||
public ASTNode visitProgram(SimpleJavaParser.ProgramContext ctx) {
|
||||
ProgramNode program = new ProgramNode();
|
||||
for (SimpleJavaParser.ClassDeclarationContext classDeclCtx : ctx.classDeclaration()) {
|
||||
program.addClass((ClassNode) visit(classDeclCtx));
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitClassDeclaration(SimpleJavaParser.ClassDeclarationContext ctx) {
|
||||
ClassNode classNode = new ClassNode((AccessTypeNode) visit(ctx.accessType()),ctx.IDENTIFIER().getText());
|
||||
classNode.identifier = new IdentifierNode(ctx.IDENTIFIER().getText());
|
||||
for (SimpleJavaParser.MemberDeclarationContext member : ctx.memberDeclaration()) {
|
||||
classNode.addMember((MemberNode) visit(member));
|
||||
}
|
||||
classNode.ensureConstructor();
|
||||
return classNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitFieldDeclaration(SimpleJavaParser.FieldDeclarationContext ctx) {
|
||||
AccessTypeNode accessType = (AccessTypeNode) visit(ctx.accessType());
|
||||
TypeNode type = (TypeNode) visit(ctx.type());
|
||||
String identifier = ctx.IDENTIFIER().getText();
|
||||
return new FieldNode(accessType, type, identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitMethodDeclaration(SimpleJavaParser.MethodDeclarationContext ctx) {
|
||||
AccessTypeNode accessType = (AccessTypeNode) visit(ctx.accessType());
|
||||
TypeNode returnType = (TypeNode) visit(ctx.type());
|
||||
String methodName = ctx.IDENTIFIER().getText();
|
||||
ParameterListNode parameterListNode = (ParameterListNode) visit(ctx.parameterList());
|
||||
List<StatementNode> statements = new ArrayList<>();
|
||||
for (SimpleJavaParser.StatementContext stmtCtx : ctx.statement()) {
|
||||
statements.add((StatementNode) visit(stmtCtx));
|
||||
}
|
||||
|
||||
MethodNode method = new MethodNode(accessType,returnType, methodName, parameterListNode, statements);
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitParameterList(SimpleJavaParser.ParameterListContext ctx) {
|
||||
List<ParameterNode> parameters = new ArrayList<>();
|
||||
for (SimpleJavaParser.ParameterContext paramCtx : ctx.parameter()) {
|
||||
parameters.add((ParameterNode) visitParameter(paramCtx));
|
||||
}
|
||||
return new ParameterListNode(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitParameter(SimpleJavaParser.ParameterContext ctx) {
|
||||
TypeNode type = (TypeNode) visit(ctx.type());
|
||||
String identifier = ctx.IDENTIFIER().getText();
|
||||
return new ParameterNode(type, identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitType(SimpleJavaParser.TypeContext ctx) {
|
||||
String typeStr = ctx.getText();
|
||||
switch (typeStr) {
|
||||
case "int":
|
||||
return new TypeNode(EnumTypeNode.INT);
|
||||
case "boolean":
|
||||
return new TypeNode(EnumTypeNode.BOOLEAN);
|
||||
case "char":
|
||||
return new TypeNode(EnumTypeNode.CHAR);
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported type: " + typeStr);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitAccessType(SimpleJavaParser.AccessTypeContext ctx) {
|
||||
String typeStr = ctx.getText();
|
||||
switch (typeStr) {
|
||||
case "public":
|
||||
return new AccessTypeNode(EnumAccessTypeNode.PUBLIC);
|
||||
case "private":
|
||||
return new AccessTypeNode(EnumAccessTypeNode.PRIVATE);
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported type: " + typeStr);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitStatement(SimpleJavaParser.StatementContext ctx) {
|
||||
if (ctx.variableDeclarationStatement() != null) {
|
||||
return visitVariableDeclarationStatement(ctx.variableDeclarationStatement());
|
||||
} else if (ctx.assignmentStatement() != null) {
|
||||
return visitAssignmentStatement(ctx.assignmentStatement());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitVariableDeclarationStatement(SimpleJavaParser.VariableDeclarationStatementContext ctx) {
|
||||
TypeNode type = (TypeNode) visit(ctx.type());
|
||||
String identifier = ctx.IDENTIFIER().getText();
|
||||
ExpressionNode expression = null;
|
||||
if (ctx.expression() != null) {
|
||||
expression = (ExpressionNode) visit(ctx.expression());
|
||||
}
|
||||
return new VariableDeclarationStatementNode(type, identifier, expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitAssignmentStatement(SimpleJavaParser.AssignmentStatementContext ctx) {
|
||||
String identifier = ctx.IDENTIFIER().getText();
|
||||
ExpressionNode expression = (ExpressionNode) visit(ctx.expression());
|
||||
return new AssignmentStatementNode(identifier, expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitIfStatement(SimpleJavaParser.IfStatementContext ctx) {
|
||||
ExpressionNode condition = (ExpressionNode) visit(ctx.expression());
|
||||
StatementNode thenStatement = (StatementNode) visit(ctx.statement(0)); // The 'then' branch
|
||||
StatementNode elseStatement = null;
|
||||
if (ctx.statement().size() > 1) {
|
||||
elseStatement = (StatementNode) visit(ctx.statement(1)); // The 'else' branch, if present
|
||||
}
|
||||
return new IfStatementNode(condition, thenStatement, elseStatement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitWhileStatement(SimpleJavaParser.WhileStatementContext ctx) {
|
||||
ExpressionNode condition = (ExpressionNode) visit(ctx.expression()); // Visit the condition part of the while statement
|
||||
StatementNode body = (StatementNode) visit(ctx.statement()); // Visit the body part of the while statement
|
||||
return new WhileStatementNode(condition, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitReturnStatement(SimpleJavaParser.ReturnStatementContext ctx) {
|
||||
ExpressionNode expression = null;
|
||||
if (ctx.expression() != null) {
|
||||
expression = (ExpressionNode) visit(ctx.expression()); // Visit the expression part of the return statement, if it exists
|
||||
}
|
||||
return new ReturnStatementNode(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitExpression(SimpleJavaParser.ExpressionContext ctx) {
|
||||
// Handle binary operations
|
||||
if (ctx.getChildCount() == 3 && ctx.getChild(1) instanceof TerminalNode) {
|
||||
ExpressionNode left = (ExpressionNode) visit(ctx.expression(0));
|
||||
ExpressionNode right = (ExpressionNode) visit(ctx.expression(1));
|
||||
String operator = ctx.getChild(1).getText();
|
||||
return new BinaryExpressionNode(left, right, operator);
|
||||
}
|
||||
// Handle unary operations
|
||||
else if (ctx.getChildCount() == 2) {
|
||||
String operator = ctx.getChild(0).getText();
|
||||
ExpressionNode expression = (ExpressionNode) visit(ctx.expression(0));
|
||||
return new UnaryExpressionNode(expression, operator);
|
||||
}
|
||||
// Handle parentheses
|
||||
else if (ctx.getChildCount() == 3 && ctx.getChild(0).getText().equals("(")) {
|
||||
return visit(ctx.expression(0)); // Simply return the inner expression
|
||||
}
|
||||
// Handle literals and identifiers
|
||||
else if (ctx.literal() != null) {
|
||||
return visit(ctx.literal());
|
||||
}
|
||||
else if (ctx.IDENTIFIER() != null) {
|
||||
return new IdentifierExpressionNode(ctx.IDENTIFIER().getText());
|
||||
}
|
||||
|
||||
return null; // Return null or throw an exception if no valid expression found
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
grammar SimpleJava;
|
||||
|
||||
program : classDeclaration+;
|
||||
|
||||
classDeclaration : accessType 'class' IDENTIFIER '{' memberDeclaration* '}';
|
||||
|
||||
memberDeclaration : fieldDeclaration | methodDeclaration | constructorDeclaration;
|
||||
|
||||
fieldDeclaration : accessType type IDENTIFIER ';';
|
||||
|
||||
methodDeclaration : accessType 'static' type IDENTIFIER '(' parameterList? ')' '{' statement* '}' ;
|
||||
|
||||
constructorDeclaration : accessType IDENTIFIER '(' parameterList? ')' '{' statement* '}' ;
|
||||
|
||||
parameterList : parameter (',' parameter)* ;
|
||||
parameter : type IDENTIFIER ;
|
||||
|
||||
type : 'int' | 'boolean' | 'char' ;
|
||||
accessType : 'public' | 'private' ;
|
||||
|
||||
statement
|
||||
: variableDeclarationStatement
|
||||
| assignmentStatement
|
||||
| ifStatement
|
||||
| whileStatement
|
||||
| returnStatement
|
||||
| block
|
||||
;
|
||||
|
||||
variableDeclarationStatement : type IDENTIFIER ('=' expression)? ';' ;
|
||||
|
||||
assignmentStatement : IDENTIFIER '=' expression ';' ;
|
||||
|
||||
ifStatement : 'if' '(' expression ')' statement ('else' statement)? ;
|
||||
|
||||
whileStatement : 'while' '(' expression ')' statement ;
|
||||
|
||||
returnStatement : 'return' (expression)? ';' ;
|
||||
|
||||
block : '{' statement* '}' ;
|
||||
|
||||
expression
|
||||
: expression ('&&' | '||') expression
|
||||
| expression ('==' | '!=' | '<' | '<=' | '>' | '>=') expression
|
||||
| expression ('+' | '-' | '*' | '/' | '%') expression
|
||||
| '-' expression
|
||||
| '!' expression
|
||||
| '(' expression ')'
|
||||
| literal
|
||||
| IDENTIFIER
|
||||
;
|
||||
|
||||
literal : INTEGERLITERAL | booleanLiteral | charLiteral ;
|
||||
|
||||
INTEGERLITERAL : [0-9]+ ;
|
||||
booleanLiteral : 'true' | 'false' ;
|
||||
charLiteral : '\'' . '\'' ;
|
||||
IDENTIFIER : [a-zA-Z][a-zA-Z0-9_]* ;
|
||||
|
||||
WS : [ \t\r\n]+ -> skip;
|
||||
607
src/main/java/parser/astBuilder/ASTBuilder.java
Normal file
607
src/main/java/parser/astBuilder/ASTBuilder.java
Normal file
@@ -0,0 +1,607 @@
|
||||
package parser.astBuilder;
|
||||
|
||||
import ast.*;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import ast.expressions.binaryexpressions.*;
|
||||
import ast.expressions.unaryexpressions.MemberAccessNode;
|
||||
import ast.expressions.unaryexpressions.NotNode;
|
||||
import ast.expressions.unaryexpressions.UnaryNode;
|
||||
import ast.members.*;
|
||||
import ast.parameters.ParameterNode;
|
||||
import ast.statementexpressions.AssignNode;
|
||||
import ast.statementexpressions.AssignableNode;
|
||||
import ast.statementexpressions.IStatementExpressionNode;
|
||||
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.AccessModifierNode;
|
||||
import ast.type.type.*;
|
||||
import ast.type.EnumValueNode;
|
||||
import ast.type.ValueNode;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
import parser.generated.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
|
||||
@Override
|
||||
public ASTNode visitProgram(SimpleJavaParser.ProgramContext ctx) {
|
||||
ProgramNode program = new ProgramNode();
|
||||
for (SimpleJavaParser.ClassDeclarationContext classDeclCtx : ctx.classDeclaration()) {
|
||||
program.addClass((ClassNode) visit(classDeclCtx));
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitClassDeclaration(SimpleJavaParser.ClassDeclarationContext ctx) {
|
||||
ClassNode classNode;
|
||||
if(ctx.AccessModifier() != null){
|
||||
classNode = new ClassNode(ctx.AccessModifier().getText(), ctx.Identifier().getText());
|
||||
}
|
||||
else{
|
||||
classNode = new ClassNode("public", ctx.Identifier().getText());
|
||||
}
|
||||
|
||||
boolean hasConstructor = false;
|
||||
|
||||
for (SimpleJavaParser.MemberDeclarationContext member : ctx.memberDeclaration()) {
|
||||
MemberNode memberNode = (MemberNode) visit(member);
|
||||
if(memberNode != null) {
|
||||
if(memberNode instanceof ConstructorNode){
|
||||
hasConstructor = true;
|
||||
}
|
||||
classNode.addMember(memberNode);
|
||||
}
|
||||
}
|
||||
|
||||
if(!hasConstructor){
|
||||
BlockNode blockNode = new BlockNode();
|
||||
blockNode.addStatement(new ReturnNode(null));
|
||||
classNode.members.addFirst(new ConstructorNode("public", ctx.Identifier().getText(), blockNode));
|
||||
}
|
||||
|
||||
return classNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitConstructorDeclaration(SimpleJavaParser.ConstructorDeclarationContext ctx) {
|
||||
ConstructorNode constructorNode;
|
||||
if(ctx.AccessModifier() != null) {
|
||||
constructorNode = new ConstructorNode(ctx.AccessModifier().getText(), ctx.Identifier().getText(), (BlockNode) visit(ctx.blockStatement()));
|
||||
} else {
|
||||
constructorNode = new ConstructorNode("public", ctx.Identifier().getText(), (BlockNode) visit(ctx.blockStatement()));
|
||||
}
|
||||
if(ctx.parameterList() != null) {
|
||||
for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) {
|
||||
constructorNode.addParameter((ParameterNode) visit(parameter));
|
||||
}
|
||||
}
|
||||
constructorNode.block.addStatement(new ReturnNode(null));
|
||||
return constructorNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitMethodDeclaration(SimpleJavaParser.MethodDeclarationContext ctx) {
|
||||
if(ctx.MainMethodDeclaration() != null) {
|
||||
MainMethodNode mainMethod = new MainMethodNode((BlockNode) visit(ctx.blockStatement()));
|
||||
mainMethod.block.addStatement(new ReturnNode(null));
|
||||
return mainMethod;
|
||||
} else {
|
||||
if(ctx.type() != null) {
|
||||
if(ctx.AccessModifier() != null) {
|
||||
MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), createTypeNode(ctx.type().getText()), false, ctx.Identifier().getText(), (BlockNode) visit(ctx.blockStatement()));
|
||||
if(ctx.parameterList() != null) {
|
||||
for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) {
|
||||
methodNode.addParameter((ParameterNode) visit(parameter));
|
||||
}
|
||||
}
|
||||
return methodNode;
|
||||
} else {
|
||||
MethodNode methodNode = new MethodNode("public", createTypeNode(ctx.type().getText()), false, ctx.Identifier().getText(), (BlockNode) visit(ctx.blockStatement()));
|
||||
if(ctx.parameterList() != null) {
|
||||
for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) {
|
||||
methodNode.addParameter((ParameterNode) visit(parameter));
|
||||
}
|
||||
}
|
||||
return methodNode;
|
||||
}
|
||||
} else {
|
||||
if(ctx.AccessModifier() != null) {
|
||||
MethodNode methodNode = new MethodNode(ctx.AccessModifier().getText(), null, true, ctx.Identifier().getText(), (BlockNode) visit(ctx.blockStatement()));
|
||||
if(ctx.parameterList() != null) {
|
||||
for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) {
|
||||
methodNode.addParameter((ParameterNode) visit(parameter));
|
||||
}
|
||||
}
|
||||
methodNode.block.addStatement(new ReturnNode(null));
|
||||
return methodNode;
|
||||
} else {
|
||||
MethodNode methodNode = new MethodNode("public", null, true, ctx.Identifier().getText(), (BlockNode) visit(ctx.blockStatement()));
|
||||
if(ctx.parameterList() != null) {
|
||||
for(SimpleJavaParser.ParameterContext parameter : ctx.parameterList().parameter()) {
|
||||
methodNode.addParameter((ParameterNode) visit(parameter));
|
||||
}
|
||||
}
|
||||
methodNode.block.addStatement(new ReturnNode(null));
|
||||
return methodNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitFieldDeclaration(SimpleJavaParser.FieldDeclarationContext ctx) {
|
||||
if(ctx.AccessModifier() != null) {
|
||||
return new FieldNode(new AccessModifierNode(ctx.AccessModifier().getText()), createTypeNode(ctx.type().getText()), ctx.Identifier().getText());
|
||||
} else {
|
||||
return new FieldNode(new AccessModifierNode("public"), createTypeNode(ctx.type().getText()), ctx.Identifier().getText());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitParameter(SimpleJavaParser.ParameterContext ctx) {
|
||||
return new ParameterNode(createTypeNode(ctx.type().getText()), ctx.Identifier().getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitStatement(SimpleJavaParser.StatementContext ctx) {
|
||||
if(ctx.returnStatement() != null) {
|
||||
return visitReturnStatement(ctx.returnStatement());
|
||||
} else if(ctx.localVariableDeclaration() != null) {
|
||||
return visitLocalVariableDeclaration(ctx.localVariableDeclaration());
|
||||
} else if(ctx.blockStatement() != null) {
|
||||
return visitBlockStatement(ctx.blockStatement());
|
||||
} else if(ctx.whileStatement() != null) {
|
||||
return visitWhileStatement(ctx.whileStatement());
|
||||
} else if(ctx.doWhileStatement() != null) {
|
||||
return visitDoWhileStatement(ctx.doWhileStatement());
|
||||
} else if(ctx.forStatement() != null) {
|
||||
return visitForStatement(ctx.forStatement());
|
||||
} else if(ctx.ifElseStatement() != null) {
|
||||
return visitIfElseStatement(ctx.ifElseStatement());
|
||||
} else if(ctx.switchStatement() != null) {
|
||||
return visitSwitchStatement(ctx.switchStatement());
|
||||
} else if(ctx.statementExpression() != null) {
|
||||
return visitStatementExpression(ctx.statementExpression());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitReturnStatement(SimpleJavaParser.ReturnStatementContext ctx) {
|
||||
return new ReturnNode((IExpressionNode) visit(ctx.expression()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitLocalVariableDeclaration(SimpleJavaParser.LocalVariableDeclarationContext ctx) {
|
||||
if(ctx.Assign() != null) {
|
||||
return new LocalVariableDeclarationNode(createTypeNode(ctx.type().getText()), ctx.Identifier().getText(), ctx.Assign().getText(), (IExpressionNode) visit(ctx.expression()));
|
||||
} else {
|
||||
return new LocalVariableDeclarationNode(createTypeNode(ctx.type().getText()), ctx.Identifier().getText(), null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitBlockStatement(SimpleJavaParser.BlockStatementContext ctx) {
|
||||
BlockNode blockNode = new BlockNode();
|
||||
for(SimpleJavaParser.StatementContext statement : ctx.statement()) {
|
||||
blockNode.addStatement((IStatementNode) visit(statement));
|
||||
}
|
||||
return blockNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitWhileStatement(SimpleJavaParser.WhileStatementContext ctx) {
|
||||
return new WhileNode((IExpressionNode) visit(ctx.expression()), (BlockNode) visit(ctx.blockStatement()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitDoWhileStatement(SimpleJavaParser.DoWhileStatementContext ctx) {
|
||||
IExpressionNode condition = (IExpressionNode) visit(ctx.expression());
|
||||
BlockNode doBlock = (BlockNode) visit(ctx.blockStatement());
|
||||
|
||||
WhileNode While = new WhileNode(condition, doBlock);
|
||||
BlockNode resultBlock = new BlockNode();
|
||||
resultBlock.addStatement((IStatementNode) doBlock);
|
||||
resultBlock.addStatement((IStatementNode) While);
|
||||
|
||||
return resultBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitForStatement(SimpleJavaParser.ForStatementContext ctx) {
|
||||
List<IStatementNode> statements = new ArrayList<>();
|
||||
|
||||
// Initialisierung
|
||||
int i = 0;
|
||||
if (ctx.localVariableDeclaration() != null) {
|
||||
statements.add((IStatementNode) visit(ctx.localVariableDeclaration()));
|
||||
} else if (ctx.statementExpression(i) != null) {
|
||||
statements.add((IStatementNode) visit(ctx.statementExpression(i)));
|
||||
i++;
|
||||
}
|
||||
|
||||
// Bedingung
|
||||
IExpressionNode condition = (IExpressionNode) visit(ctx.expression());
|
||||
|
||||
// Inkrement
|
||||
IStatementExpressionNode crement = null;
|
||||
boolean isPrefix = false;
|
||||
if (ctx.statementExpression(i) != null) {
|
||||
crement = (IStatementExpressionNode) visit(ctx.statementExpression(i));
|
||||
|
||||
if (crement instanceof IncrementNode) {
|
||||
isPrefix = ((IncrementNode) crement).crementType == CrementType.PREFIX;
|
||||
} else if (crement instanceof DecrementNode) {
|
||||
isPrefix = ((DecrementNode) crement).crementType == CrementType.PREFIX;
|
||||
}
|
||||
}
|
||||
|
||||
BlockNode forBlock = (BlockNode) visit(ctx.blockStatement());
|
||||
|
||||
// While-Schleife
|
||||
BlockNode whileBody = new BlockNode();
|
||||
|
||||
// Prä-Inkrement: Das Inkrement kommt vor dem Block
|
||||
if (crement != null && isPrefix) {
|
||||
whileBody.addStatement((IStatementNode) crement);
|
||||
}
|
||||
|
||||
// Block Statements der For-Schleife in den While-Block kopieren
|
||||
for (IStatementNode statement : forBlock.statements) {
|
||||
whileBody.addStatement(statement);
|
||||
}
|
||||
|
||||
// Post-Inkrement: Das Inkrement kommt nach dem Block
|
||||
if (crement != null && !isPrefix) {
|
||||
whileBody.addStatement((IStatementNode) crement);
|
||||
}
|
||||
|
||||
// Bedingung der While-Schleife
|
||||
WhileNode whileNode = new WhileNode(condition, whileBody);
|
||||
|
||||
statements.add(whileNode);
|
||||
|
||||
BlockNode resultBlock = new BlockNode();
|
||||
for (IStatementNode statement : statements) {
|
||||
resultBlock.addStatement((IStatementNode) statement);
|
||||
}
|
||||
|
||||
return resultBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitIfElseStatement(SimpleJavaParser.IfElseStatementContext ctx) {
|
||||
IfElseNode ifElseStatementNode;
|
||||
if(ctx.elseStatement() != null) {
|
||||
ifElseStatementNode = new IfElseNode((IfNode) visit(ctx.ifStatement()),
|
||||
(ElseNode) visit(ctx.elseStatement()));
|
||||
} else {
|
||||
ifElseStatementNode = new IfElseNode((IfNode) visit(ctx.ifStatement()), null);
|
||||
}
|
||||
|
||||
for (SimpleJavaParser.ElseIfStatementContext elseIf : ctx.elseIfStatement()){
|
||||
ifElseStatementNode.addElseIfStatement(((IfNode) visit(elseIf)));
|
||||
}
|
||||
|
||||
return ifElseStatementNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitIfStatement(SimpleJavaParser.IfStatementContext ctx) {
|
||||
return new IfNode((IExpressionNode) visit(ctx.expression()), (BlockNode) visit(ctx.blockStatement()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitElseIfStatement(SimpleJavaParser.ElseIfStatementContext ctx) {
|
||||
return new IfNode((IExpressionNode) visit(ctx.expression()), (BlockNode) visit(ctx.blockStatement()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitElseStatement(SimpleJavaParser.ElseStatementContext ctx) {
|
||||
return new ElseNode((BlockNode) visit(ctx.blockStatement()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitStatementExpression(SimpleJavaParser.StatementExpressionContext ctx) {
|
||||
if(ctx.assign() != null) {
|
||||
return visitAssign(ctx.assign());
|
||||
} else if(ctx.newDeclaration() != null) {
|
||||
return visitNewDeclaration(ctx.newDeclaration());
|
||||
} else if(ctx.methodCall() != null) {
|
||||
return visitMethodCall(ctx.methodCall());
|
||||
} else if(ctx.crementExpression() != null) {
|
||||
return visitCrementExpression(ctx.crementExpression());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitSwitchStatement(SimpleJavaParser.SwitchStatementContext ctx) {
|
||||
UnaryNode switchExpression = (UnaryNode) visit(ctx.expression());
|
||||
|
||||
List<IfNode> ifNodes = new ArrayList<>();
|
||||
|
||||
for (SimpleJavaParser.CaseStatementContext caseCtx : ctx.caseStatement()) {
|
||||
IExpressionNode caseExpression = (IExpressionNode) visit(caseCtx.value());
|
||||
|
||||
// Condition as NonCalculationNode -> Equals Expression
|
||||
NonCalculationNode condition = new NonCalculationNode(switchExpression, "==", caseExpression);
|
||||
|
||||
BlockNode caseBlock = new BlockNode();
|
||||
for (SimpleJavaParser.StatementContext stmtCtx : caseCtx.statement()) {
|
||||
caseBlock.addStatement((IStatementNode) visit(stmtCtx));
|
||||
}
|
||||
|
||||
// Each case as if
|
||||
IfNode ifNode = new IfNode(condition, caseBlock);
|
||||
ifNodes.add(ifNode);
|
||||
}
|
||||
|
||||
// Check if has Default
|
||||
ElseNode defaulElseNode = null;
|
||||
if (ctx.defaultStatement() != null) {
|
||||
BlockNode defaultBlock = new BlockNode();
|
||||
for (SimpleJavaParser.StatementContext stmtCtx : ctx.defaultStatement().statement()) {
|
||||
defaultBlock.addStatement((IStatementNode) visit(stmtCtx));
|
||||
}
|
||||
// Default als letztes Else Statement
|
||||
defaulElseNode = new ElseNode(defaultBlock);
|
||||
}
|
||||
|
||||
IfElseNode ifElseNode = new IfElseNode(ifNodes.getFirst(),defaulElseNode);
|
||||
ifNodes.removeFirst();
|
||||
|
||||
for (IfNode ifNode : ifNodes){
|
||||
ifElseNode.addElseIfStatement(ifNode);
|
||||
}
|
||||
|
||||
return ifElseNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitAssign(SimpleJavaParser.AssignContext ctx) {
|
||||
return new AssignNode((AssignableNode) visit(ctx.assignableExpression()), (IExpressionNode) visit(ctx.expression()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitNewDeclaration(SimpleJavaParser.NewDeclarationContext ctx) {
|
||||
NewDeclarationNode newDeclarationNode = new NewDeclarationNode(ctx.Identifier().getText());
|
||||
for(SimpleJavaParser.ExpressionContext expression : ctx.argumentList().expression()) {
|
||||
newDeclarationNode.addExpression((IExpressionNode) visit(expression));
|
||||
}
|
||||
return newDeclarationNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitMethodCall(SimpleJavaParser.MethodCallContext ctx) {
|
||||
MethodCallNode methodCallStatementExpressionNode;
|
||||
if(ctx.target() != null) {
|
||||
methodCallStatementExpressionNode = new MethodCallNode((TargetNode) visit(ctx.target()), ctx.Identifier().getText());
|
||||
} else {
|
||||
methodCallStatementExpressionNode = new MethodCallNode(null, ctx.Identifier().getText());
|
||||
}
|
||||
for(SimpleJavaParser.ChainedMethodContext chainedMethod : ctx.chainedMethod()) {
|
||||
methodCallStatementExpressionNode.addChainedMethod((ChainedMethodNode) visit(chainedMethod));
|
||||
}
|
||||
for(SimpleJavaParser.ExpressionContext expression : ctx.argumentList().expression()) {
|
||||
methodCallStatementExpressionNode.addExpression((IExpressionNode) visit(expression));
|
||||
}
|
||||
return methodCallStatementExpressionNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitTarget(SimpleJavaParser.TargetContext ctx) {
|
||||
if(ctx.This() != null) {
|
||||
return new TargetNode(true);
|
||||
} else if(ctx.memberAccess() != null) {
|
||||
return new TargetNode((MemberAccessNode) visit(ctx.memberAccess()));
|
||||
} else if(ctx.newDeclaration() != null) {
|
||||
return new TargetNode((NewDeclarationNode) visit(ctx.newDeclaration()));
|
||||
} else if(ctx.Identifier() != null) {
|
||||
return new TargetNode(ctx.Identifier().getText());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitChainedMethod(SimpleJavaParser.ChainedMethodContext ctx) {
|
||||
ChainedMethodNode chainedMethodNode = new ChainedMethodNode(ctx.Identifier().getText());
|
||||
for(SimpleJavaParser.ExpressionContext expression : ctx.argumentList().expression()) {
|
||||
chainedMethodNode.addExpression((IExpressionNode) visit(expression));
|
||||
}
|
||||
return chainedMethodNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitCrementExpression(SimpleJavaParser.CrementExpressionContext ctx) {
|
||||
if(ctx.incrementExpression() != null) {
|
||||
return visitIncrementExpression(ctx.incrementExpression());
|
||||
} else if(ctx.decrementExpression() != null) {
|
||||
return visitDecrementExpression(ctx.decrementExpression());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitIncrementExpression(SimpleJavaParser.IncrementExpressionContext ctx) {
|
||||
if(ctx.prefixIncrementExpression() != null) {
|
||||
return visitPrefixIncrementExpression(ctx.prefixIncrementExpression());
|
||||
} else if(ctx.suffixIncrementExpression() != null) {
|
||||
return visitSuffixIncrementExpression(ctx.suffixIncrementExpression());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitPrefixIncrementExpression(SimpleJavaParser.PrefixIncrementExpressionContext ctx) {
|
||||
return new IncrementNode(CrementType.PREFIX, (AssignableNode) visit(ctx.assignableExpression()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitSuffixIncrementExpression(SimpleJavaParser.SuffixIncrementExpressionContext ctx) {
|
||||
return new IncrementNode(CrementType.SUFFIX, (AssignableNode) visit(ctx.assignableExpression()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitDecrementExpression(SimpleJavaParser.DecrementExpressionContext ctx) {
|
||||
if(ctx.prefixDecrementExpression() != null) {
|
||||
return visitPrefixDecrementExpression(ctx.prefixDecrementExpression());
|
||||
} else if(ctx.suffixDecrementExpression() != null) {
|
||||
return visitSuffixDecrementExpression(ctx.suffixDecrementExpression());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitPrefixDecrementExpression(SimpleJavaParser.PrefixDecrementExpressionContext ctx) {
|
||||
return new DecrementNode(CrementType.PREFIX, (AssignableNode) visit(ctx.assignableExpression()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitSuffixDecrementExpression(SimpleJavaParser.SuffixDecrementExpressionContext ctx) {
|
||||
return new DecrementNode(CrementType.SUFFIX, (AssignableNode) visit(ctx.assignableExpression()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitExpression(SimpleJavaParser.ExpressionContext ctx) {
|
||||
if(ctx.unaryExpression() != null) {
|
||||
return visit(ctx.unaryExpression());
|
||||
} else if(ctx.binaryExpression() != null) {
|
||||
return visit(ctx.binaryExpression());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitUnaryExpression(SimpleJavaParser.UnaryExpressionContext ctx) {
|
||||
if(ctx.This() != null) {
|
||||
return new UnaryNode(ctx.This().getText());
|
||||
} else if(ctx.Identifier() != null) {
|
||||
return new UnaryNode(ctx.Identifier().getText());
|
||||
} else if(ctx.memberAccess() != null) {
|
||||
return new UnaryNode((MemberAccessNode) visitMemberAccess(ctx.memberAccess()));
|
||||
} else if(ctx.value() != null) {
|
||||
return new UnaryNode((ValueNode) visitValue(ctx.value()));
|
||||
} else if(ctx.notExpression() != null) {
|
||||
return new UnaryNode((NotNode) visitNotExpression(ctx.notExpression()));
|
||||
} else if(ctx.statementExpression() != null) {
|
||||
return new UnaryNode((IStatementNode) visitStatementExpression(ctx.statementExpression()));
|
||||
} else if(ctx.expression() != null) {
|
||||
return new UnaryNode((IExpressionNode) visitExpression(ctx.expression()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitMemberAccess(SimpleJavaParser.MemberAccessContext ctx) {
|
||||
MemberAccessNode memberAccessNode;
|
||||
if(ctx.This() != null) {
|
||||
memberAccessNode = new MemberAccessNode(true);
|
||||
} else {
|
||||
memberAccessNode = new MemberAccessNode(false);
|
||||
}
|
||||
for (TerminalNode identifierNode : ctx.Identifier()) {
|
||||
memberAccessNode.addIdentifier(identifierNode.getText());
|
||||
}
|
||||
return memberAccessNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitValue(SimpleJavaParser.ValueContext ctx) {
|
||||
if(ctx.IntValue() != null) {
|
||||
return new ValueNode(EnumValueNode.INT_VALUE, ctx.IntValue().getText());
|
||||
} else if(ctx.BooleanValue() != null) {
|
||||
return new ValueNode(EnumValueNode.BOOLEAN_VALUE, ctx.BooleanValue().getText());
|
||||
} else if(ctx.CharValue() != null) {
|
||||
return new ValueNode(EnumValueNode.CHAR_VALUE, ctx.CharValue().getText());
|
||||
} else if(ctx.NullValue() != null) {
|
||||
return new ValueNode(EnumValueNode.NULL_VALUE, ctx.NullValue().getText());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitNotExpression(SimpleJavaParser.NotExpressionContext ctx) {
|
||||
return new NotNode((IExpressionNode) visitExpression(ctx.expression()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ASTNode visitBinaryExpression(SimpleJavaParser.BinaryExpressionContext ctx) {
|
||||
if(ctx.calculationExpression() != null) {
|
||||
return visit(ctx.calculationExpression());
|
||||
} else if(ctx.nonCalculationExpression() != null) {
|
||||
return visit(ctx.nonCalculationExpression());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitCalculationExpression(SimpleJavaParser.CalculationExpressionContext ctx) {
|
||||
if(ctx.calculationExpression() != null) {
|
||||
return new CalculationNode((CalculationNode) visit(ctx.calculationExpression()), ctx.LineOperator().getText(), (DotNode) visit(ctx.dotExpression()));
|
||||
} else if(ctx.dotExpression() != null) {
|
||||
return new CalculationNode((DotNode) visit(ctx.dotExpression()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitDotExpression(SimpleJavaParser.DotExpressionContext ctx) {
|
||||
if(ctx.dotExpression() != null) {
|
||||
return new DotNode((DotNode) visit(ctx.dotExpression()), ctx.DotOperator().getText(), (DotSubstractionNode) visit(ctx.dotSubtractionExpression()));
|
||||
} else if(ctx.dotSubtractionExpression() != null) {
|
||||
return new DotNode((DotSubstractionNode) visit(ctx.dotSubtractionExpression()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitDotSubtractionExpression(SimpleJavaParser.DotSubtractionExpressionContext ctx) {
|
||||
if(ctx.IntValue() != null) {
|
||||
return new DotSubstractionNode(new ValueNode(EnumValueNode.INT_VALUE, ctx.IntValue().getText()));
|
||||
} else if(ctx.Identifier() != null) {
|
||||
return new DotSubstractionNode(ctx.Identifier().getText());
|
||||
} else if(ctx.memberAccess() != null) {
|
||||
return new DotSubstractionNode((MemberAccessNode) visit(ctx.memberAccess()));
|
||||
} else if(ctx.methodCall() != null && ctx.calculationExpression() != null) {
|
||||
return new DotSubstractionNode((MethodCallNode) visit(ctx.methodCall()), (CalculationNode) visit(ctx.calculationExpression()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitNonCalculationExpression(SimpleJavaParser.NonCalculationExpressionContext ctx) {
|
||||
return new NonCalculationNode((UnaryNode) visit(ctx.unaryExpression()), ctx.nonCalculationOperator().getText(), (IExpressionNode) visit(ctx.expression()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitAssignableExpression(SimpleJavaParser.AssignableExpressionContext ctx) {
|
||||
if(ctx.Identifier() != null) {
|
||||
return new AssignableNode(ctx.Identifier().getText());
|
||||
} else if(ctx.memberAccess() != null) {
|
||||
return new AssignableNode((MemberAccessNode) visit(ctx.memberAccess()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ITypeNode createTypeNode(String identifier){
|
||||
return switch (identifier) {
|
||||
case "int" -> new BaseType(TypeEnum.INT);
|
||||
case "boolean" -> new BaseType(TypeEnum.BOOL);
|
||||
case "char" -> new BaseType(TypeEnum.CHAR);
|
||||
case "void" -> new BaseType(TypeEnum.VOID);
|
||||
default -> new ReferenceType(identifier);
|
||||
};
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user