Compare commits
137 Commits
8094a93582
...
ParserAlte
Author | SHA1 | Date | |
---|---|---|---|
|
7d441116bd | ||
|
8afa3b8461 | ||
|
ba73e1bd45 | ||
|
b7affd75ae | ||
bd76135895 | |||
3227d69fc1 | |||
4ca6972ccd | |||
0047f6c08e | |||
88ce9e52f0 | |||
|
437de74cc6 | ||
|
ca77307f0c | ||
|
5f46130439 | ||
3e1456351c | |||
d26cd0c13a | |||
|
cfde5219a4 | ||
|
f414e278bb | ||
|
741a56cb99 | ||
|
02e5f3a729 | ||
903e87901e | |||
775beb60fe | |||
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 | |||
|
b6cc925e02 | ||
|
6a971345d4 | ||
|
8d6190b130 | ||
09e36a84dc | |||
|
e395c4d96b | ||
|
8a5f307947 | ||
514f7d724a | |||
|
9f40949f5a | ||
|
de5c2a5002 | ||
|
1132ff015c | ||
|
2a20a91d35 | ||
407b03620e | |||
|
b2e1745d51 | ||
|
a0e55d7b27 | ||
|
5a28d88f6a |
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/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" />
|
||||
|
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -6,7 +6,7 @@
|
||||
<PerGrammarGenerationSettings>
|
||||
<option name="fileName" value="$PROJECT_DIR$/src/main/java/parser/SimpleJava.g4" />
|
||||
<option name="autoGen" value="true" />
|
||||
<option name="outputDir" value="C:\Users\Johannes\Documents\Github\JavaCompiler\src\main\java" />
|
||||
<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="parser.generated" />
|
||||
|
45
pom.xml
45
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>
|
||||
|
||||
@@ -43,6 +44,12 @@
|
||||
<version>3.26.0</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>
|
||||
@@ -53,7 +60,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,132 +0,0 @@
|
||||
import oldAst.ASTNode;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import oldAst.ProgramNode;
|
||||
import bytecode.ByteCodeGenerator;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import parser.astBuilder.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 {
|
||||
if(args.length > 0) {
|
||||
|
||||
} else {
|
||||
try {
|
||||
CharStream codeCharStream = CharStreams.fromPath(Paths.get("src/main/resources/CompilerInput.java"));
|
||||
parseFile(codeCharStream);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error reading the file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void parseFile(CharStream codeCharStream) {
|
||||
/* ------------------------- Scanner -> tokens ------------------------- */
|
||||
SimpleJavaLexer lexer = new SimpleJavaLexer(codeCharStream);
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
// Printing the tokens
|
||||
// tokenStream.fill();
|
||||
// List<Token> tokens = tokenStream.getTokens();
|
||||
// System.out.println("-------------------- Scanner -> tokens --------------------");
|
||||
// for (Token token : tokens) {
|
||||
// String tokenType = SimpleJavaLexer.VOCABULARY.getSymbolicName(token.getType());
|
||||
// String tokenText = token.getText();
|
||||
// // System.out.println("Token Type: " + tokenType + ", Token Text: " +
|
||||
// // tokenText);
|
||||
// System.out.println(tokenType + " " + tokenText);
|
||||
// }
|
||||
// System.out.println();
|
||||
|
||||
/* ------------------------- Parser -> Parsetree ------------------------- */
|
||||
SimpleJavaParser parser = new SimpleJavaParser(tokenStream);
|
||||
ParseTree parseTree = parser.program(); // parse the input
|
||||
|
||||
// Printing the parse tree
|
||||
// System.out.println("-------------------- Parser -> Parsetree --------------------");
|
||||
// System.out.println(parseTree.toStringTree(parser));
|
||||
// printTree(parseTree, parser, 0);
|
||||
// System.out.println();
|
||||
|
||||
/* ------------------------- AST builder -> AST ------------------------- */
|
||||
ASTBuilder astBuilder = new ASTBuilder();
|
||||
ProgramNode abstractSyntaxTree = (ProgramNode) astBuilder.visit(parseTree);
|
||||
|
||||
// Printing the AST
|
||||
// System.out.println("-------------------- AST builder -> AST --------------------");
|
||||
// // System.out.println("AST: " + ast.toString());
|
||||
// printAST(abstractSyntaxTree, 0);
|
||||
// System.out.println();
|
||||
|
||||
/*
|
||||
* ------------------------- Semantic Analyzer -> Tast -------------------------
|
||||
*/
|
||||
SemanticAnalyzer semanticAnalyzer = new SemanticAnalyzer();
|
||||
ProgramNode typedAst = (ProgramNode) semanticAnalyzer.generateTast(abstractSyntaxTree);
|
||||
|
||||
// Printing the Tast
|
||||
System.out.println("Tast generated");
|
||||
|
||||
/*
|
||||
* ------------------------- Bytecode Generator -> Bytecode
|
||||
* -------------------------
|
||||
*/
|
||||
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator();
|
||||
//byteCodeGenerator.generateByteCode(abstractSyntaxTree);
|
||||
byteCodeGenerator.visit(typedAst);
|
||||
System.out.println("Bytecode generated");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 printTree(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];
|
||||
System.out.println(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
|
||||
System.out.println(indentString + tree.getText());
|
||||
}
|
||||
|
||||
// Recursively print the children of the current node, increasing the
|
||||
// indentation level
|
||||
for (int i = 0; i < tree.getChildCount(); i++) {
|
||||
printTree(tree.getChild(i), parser, indent + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public static void printAST(ASTNode node, int indent) {
|
||||
String indentString = " ".repeat(indent * 2);
|
||||
System.out.println(indentString + node.getClass().toString());
|
||||
|
||||
// for (ASTNode child : node.) {
|
||||
// printAST(child, indent + 1);
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
@@ -1,12 +1,20 @@
|
||||
package ast;
|
||||
|
||||
//import java.util.List;
|
||||
import bytecode.visitor.ClassVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public interface ASTNode {
|
||||
/**
|
||||
* Please implement this method to return a list of children of each node.
|
||||
|
||||
//Todo: @BruderJohn & @i22007 Interface anwenden + geeignetetn Methodename.
|
||||
|
||||
/*
|
||||
Typecheck:
|
||||
public TypeCheckResult acceptType(SemanticVisitor visitor);
|
||||
|
||||
Bytecode:
|
||||
public void accepByteCode(ClassVisitor classVisitor);
|
||||
*/
|
||||
// public List<ASTNode> getChildren();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,12 +1,10 @@
|
||||
package ast;
|
||||
|
||||
import ast.type.AccessModifierNode;
|
||||
import ast.members.ConstructorNode;
|
||||
import ast.members.MemberNode;
|
||||
import ast.members.MethodNode;
|
||||
import bytecode.visitor.ClassVisitor;
|
||||
import oldAst.ASTNode;
|
||||
import oldAst.member.ConstructorNode;
|
||||
import oldAst.member.MemberNode;
|
||||
import oldAst.member.MethodNode;
|
||||
import oldAst.type.AccessTypeNode;
|
||||
import oldAst.type.EnumAccessTypeNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
@@ -15,32 +13,23 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ClassNode implements ASTNode, Visitable {
|
||||
public AccessModifierNode accessType;
|
||||
public String identifier;
|
||||
public AccessTypeNode accessType;
|
||||
public List<MemberNode> members = new ArrayList<>();
|
||||
public boolean hasConstructor = false;
|
||||
|
||||
public ClassNode() {}
|
||||
public ClassNode(){
|
||||
|
||||
public ClassNode(AccessTypeNode accessType, String identifier){
|
||||
this.accessType = accessType;
|
||||
}
|
||||
|
||||
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), identifier);
|
||||
members.add(0,constructor);
|
||||
}
|
||||
}
|
||||
|
||||
public List<MethodNode> getMethods(){
|
||||
List<MethodNode> methods = new ArrayList<>();
|
||||
for (MemberNode member : members) {
|
||||
@@ -60,4 +49,5 @@ public class ClassNode implements ASTNode, Visitable {
|
||||
public void accept(ClassVisitor classVisitor) {
|
||||
classVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,4 +0,0 @@
|
||||
package ast;
|
||||
|
||||
public class IdentifierNode {
|
||||
}
|
@@ -1,7 +1,5 @@
|
||||
package ast;
|
||||
|
||||
import ast.ASTNode;
|
||||
import ast.ClassNode;
|
||||
import bytecode.visitor.ProgramVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
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;
|
||||
}
|
||||
}
|
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;
|
||||
}
|
||||
}
|
@@ -1,20 +1,19 @@
|
||||
package oldAst.member;
|
||||
package ast.members;
|
||||
|
||||
import oldAst.type.AccessTypeNode;
|
||||
import oldAst.type.TypeNode;
|
||||
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 AccessTypeNode accessTypeNode;
|
||||
public TypeNode type;
|
||||
public AccessModifierNode accessTypeNode;
|
||||
public ITypeNode type;
|
||||
public String identifier;
|
||||
|
||||
public FieldNode(){}
|
||||
|
||||
public FieldNode(AccessTypeNode accessTypeNode, TypeNode type, String name){
|
||||
public FieldNode(AccessModifierNode accessTypeNode, ITypeNode type, String name){
|
||||
this.accessTypeNode = accessTypeNode;
|
||||
this.type = type;
|
||||
this.identifier = name;
|
||||
@@ -29,4 +28,5 @@ public class FieldNode implements MemberNode, Visitable {
|
||||
public void accept(ClassVisitor classVisitor) {
|
||||
classVisitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
18
src/main/java/ast/members/MainMethodNode.java
Normal file
18
src/main/java/ast/members/MainMethodNode.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package ast.members;
|
||||
|
||||
import ast.statements.BlockNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class MainMethodNode extends MethodNode implements Visitable {
|
||||
public BlockNode block;
|
||||
|
||||
public MainMethodNode(BlockNode block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
}
|
@@ -1,9 +1,9 @@
|
||||
package oldAst.member;
|
||||
package ast.members;
|
||||
|
||||
import oldAst.ASTNode;
|
||||
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)
|
||||
@@ -13,6 +13,4 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
@JsonSubTypes.Type(value = FieldNode.class, name = "Field") }
|
||||
)
|
||||
|
||||
public interface MemberNode extends ASTNode {
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
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);
|
||||
}
|
||||
|
||||
}
|
11
src/main/java/ast/statement/BlockStatementNode.java
Normal file
11
src/main/java/ast/statement/BlockStatementNode.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package ast.statement;
|
||||
|
||||
import ast.statements.IStatementNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BlockStatementNode {
|
||||
List<IStatementNode> statements;
|
||||
|
||||
public BlockStatementNode(List<IStatementNode> statements) {this.statements = statements;}
|
||||
}
|
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,41 @@
|
||||
package ast.statementexpressions.methodcallstatementnexpressions;
|
||||
|
||||
import ast.expressions.IExpressionNode;
|
||||
import ast.statements.IStatementNode;
|
||||
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 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);
|
||||
}
|
||||
|
||||
}
|
20
src/main/java/ast/statements/WhileNode.java
Normal file
20
src/main/java/ast/statements/WhileNode.java
Normal file
@@ -0,0 +1,20 @@
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
@@ -1,14 +1,28 @@
|
||||
package ast.type;
|
||||
|
||||
import oldAst.ASTNode;
|
||||
import oldAst.type.EnumAccessTypeNode;
|
||||
public class AccessModifierNode {
|
||||
public EnumAccessModifierNode accessType;
|
||||
|
||||
public class AccessModifierNode implements ASTNode {
|
||||
public EnumAccessModifierNode enumAccessModifierNode;
|
||||
public AccessModifierNode(String accessModifier) {
|
||||
setModifier(accessModifier);
|
||||
}
|
||||
|
||||
public AccessModifierNode(){}
|
||||
|
||||
public AccessModifierNode(EnumAccessModifierNode enumAccessTypeNode) {
|
||||
this.enumAccessModifierNode = enumAccessTypeNode;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,3 +3,4 @@ package ast.type;
|
||||
public enum EnumAccessModifierNode {
|
||||
PUBLIC, PRIVATE, PUBLIC_STATIC, PRIVATE_STATIC
|
||||
}
|
||||
|
||||
|
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
|
||||
}
|
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;
|
||||
|
||||
}
|
@@ -1,16 +1,90 @@
|
||||
package bytecode;
|
||||
|
||||
import oldAst.ProgramNode;
|
||||
import oldAst.ClassNode;
|
||||
import ast.ProgramNode;
|
||||
import ast.ClassNode;
|
||||
import ast.members.MainMethodNode;
|
||||
import ast.members.MemberNode;
|
||||
import bytecode.visitor.ProgramVisitor;
|
||||
|
||||
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 class ByteCodeGenerator implements ProgramVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(ProgramNode programNode) {
|
||||
for (ClassNode classDeclarationNode : programNode.classes) {
|
||||
ClassCodeGen classCodeGen = new ClassCodeGen();
|
||||
classDeclarationNode.accept(classCodeGen);
|
||||
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,25 +1,37 @@
|
||||
package bytecode;
|
||||
|
||||
import oldAst.ClassNode;
|
||||
import oldAst.member.FieldNode;
|
||||
import oldAst.member.MemberNode;
|
||||
import oldAst.member.MethodNode;
|
||||
import oldAst.type.BaseTypeNode;
|
||||
import ast.ClassNode;
|
||||
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 implements ClassVisitor {
|
||||
private Mapper mapper;
|
||||
private ClassWriter classWriter;
|
||||
private JarOutputStream jarOutputStream;
|
||||
private String outputDirectory;
|
||||
private boolean generateJar;
|
||||
private boolean generateClassFiles;
|
||||
|
||||
public ClassCodeGen() {
|
||||
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
|
||||
@@ -37,28 +49,31 @@ public class ClassCodeGen implements ClassVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
classWriter.visitEnd();
|
||||
printIntoClassFile(classWriter.toByteArray(), classNode.identifier);
|
||||
if (generateJar) {
|
||||
writeToJar(classWriter.toByteArray(), classNode.identifier);
|
||||
}
|
||||
if (generateClassFiles) {
|
||||
printIntoClassFile(classWriter.toByteArray(), classNode.identifier, outputDirectory);
|
||||
}
|
||||
|
||||
classWriter.visitEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(FieldNode fieldNode) {
|
||||
if(fieldNode.type instanceof BaseTypeNode baseTypeNode){
|
||||
classWriter.visitField(mapper.mapAccessTypeToOpcode(fieldNode.accessTypeNode), fieldNode.identifier, mapper.getTypeChar(baseTypeNode.enumType), null, null );
|
||||
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 directoryPath = "src/main/java/classFileOutput";
|
||||
File directory = new File(directoryPath);
|
||||
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);
|
||||
@@ -67,4 +82,15 @@ public class ClassCodeGen implements ClassVisitor {
|
||||
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,44 +1,59 @@
|
||||
package bytecode;
|
||||
|
||||
import oldAst.parameter.ParameterListNode;
|
||||
import oldAst.parameter.ParameterNode;
|
||||
import oldAst.type.*;
|
||||
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 oldAst.type.BaseTypeNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Mapper {
|
||||
public int mapAccessTypeToOpcode(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(BaseTypeNode baseTypeNode, ParameterListNode parameterListNode) {
|
||||
public String generateMethodDescriptor(BaseType type, List<ParameterNode> parameters) {
|
||||
String descriptor = "(";
|
||||
for(ParameterNode parameterNode : parameterListNode.parameters) {
|
||||
descriptor += getTypeChar(EnumTypeNode.INT);
|
||||
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(baseTypeNode.enumType);
|
||||
descriptor += getTypeChar(type);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public String getTypeChar(EnumTypeNode enumTypeNode) {
|
||||
public String getTypeChar(BaseType type) {
|
||||
String typeChar = "";
|
||||
switch (enumTypeNode) {
|
||||
case EnumTypeNode.INT:
|
||||
switch (type.getTypeEnum()) {
|
||||
case TypeEnum.INT:
|
||||
typeChar = "I";
|
||||
break;
|
||||
case EnumTypeNode.CHAR:
|
||||
case TypeEnum.CHAR:
|
||||
typeChar = "C";
|
||||
break;
|
||||
case EnumTypeNode.BOOLEAN:
|
||||
case TypeEnum.BOOL:
|
||||
typeChar = "Z";
|
||||
break;
|
||||
case TypeEnum.VOID:
|
||||
typeChar = "V";
|
||||
break;
|
||||
}
|
||||
return typeChar;
|
||||
}
|
||||
|
@@ -1,9 +1,27 @@
|
||||
package bytecode;
|
||||
|
||||
import oldAst.member.ConstructorNode;
|
||||
import oldAst.member.MethodNode;
|
||||
import oldAst.parameter.ParameterNode;
|
||||
import oldAst.type.BaseTypeNode;
|
||||
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;
|
||||
@@ -21,78 +39,498 @@ public class MethodCodeGen implements bytecode.visitor.MethodVisitor {
|
||||
private Mapper mapper;
|
||||
private MethodVisitor methodVisitor;
|
||||
|
||||
private List<String> localVaribales;
|
||||
private List<String> localVariables;
|
||||
|
||||
public MethodCodeGen(ClassWriter classWriter) {
|
||||
this.classWriter = classWriter;
|
||||
mapper = new Mapper();
|
||||
localVaribales = new ArrayList<>();
|
||||
localVariables = new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
// Method nodes
|
||||
|
||||
@Override
|
||||
public void visit(ConstructorNode constructorNode) {
|
||||
methodVisitor =
|
||||
classWriter.visitMethod(mapper.mapAccessTypeToOpcode(constructorNode.visibility),
|
||||
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);
|
||||
methodVisitor.visitInsn(RETURN);
|
||||
methodVisitor.visitMaxs(1, 1);
|
||||
|
||||
// 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) {
|
||||
if (methodNode.type instanceof BaseTypeNode baseTypeNode) {
|
||||
methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.visibility),
|
||||
methodNode.identifier,
|
||||
mapper.generateMethodDescriptor(baseTypeNode, methodNode.parameters),
|
||||
null,
|
||||
null);
|
||||
methodVisitor = classWriter.visitMethod(mapper.mapAccessTypeToOpcode(methodNode.accesModifier),
|
||||
methodNode.getIdentifier(),
|
||||
mapper.generateMethodDescriptor((BaseType) methodNode.getType(), methodNode.parameters),
|
||||
null,
|
||||
null);
|
||||
|
||||
methodVisitor.visitCode();
|
||||
localVaribales.add("this");
|
||||
for (ParameterNode parameterNode : methodNode.parameters.parameters) {
|
||||
localVaribales.add(parameterNode.identifier);
|
||||
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;
|
||||
}
|
||||
|
||||
//test();
|
||||
methodVisitor.visitMaxs(1, localVaribales.size());
|
||||
methodVisitor.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
public void test() {
|
||||
Label start = new Label();
|
||||
Label loop = new Label();
|
||||
Label end = new Label();
|
||||
methodVisitor.visitLabel(start);
|
||||
//methodVisitor.visitVarInsn(Opcodes.ICONST_M1, 99);
|
||||
//methodVisitor.visitInsn(Opcodes.ICONST_5);
|
||||
methodVisitor.visitLdcInsn(99);
|
||||
// methodVisitor.visitInsn(Opcodes.ICONST_0);
|
||||
//methodVisitor.visitVarInsn(Opcodes.ILOAD, 2);
|
||||
methodVisitor.visitVarInsn(Opcodes.ISTORE, 1);
|
||||
methodVisitor.visitLabel(loop);
|
||||
methodVisitor.visitVarInsn(Opcodes.ILOAD, 1);
|
||||
methodVisitor.visitInsn(Opcodes.ICONST_5);
|
||||
methodVisitor.visitJumpInsn(Opcodes.IF_ICMPGE, end);
|
||||
methodVisitor.visitFieldInsn(Opcodes.GETSTATIC,
|
||||
"java/lang/System", "out",
|
||||
"Ljava/io/PrintStream;");
|
||||
methodVisitor.visitLdcInsn("Bytecode");
|
||||
methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
|
||||
"java/io/PrintStream", "println",
|
||||
"(Ljava/lang/String;)V", false);
|
||||
methodVisitor.visitIincInsn(1, 1);
|
||||
methodVisitor.visitJumpInsn(Opcodes.GOTO, loop);
|
||||
methodVisitor.visitLabel(end);
|
||||
methodVisitor.visitVarInsn(Opcodes.ILOAD, 1);
|
||||
methodVisitor.visitInsn(Opcodes.IRETURN);
|
||||
methodVisitor.visitEnd();
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,10 @@
|
||||
package bytecode.visitor;
|
||||
|
||||
import ast.ClassNode;
|
||||
import ast.member.FieldNode;
|
||||
import ast.members.FieldNode;
|
||||
|
||||
public interface ClassVisitor {
|
||||
void visit(ClassNode classNode);
|
||||
void visit(FieldNode fieldNode);
|
||||
void visit(ClassNode classNode);
|
||||
|
||||
void visit(FieldNode fieldNode);
|
||||
}
|
||||
|
@@ -1,9 +1,56 @@
|
||||
package bytecode.visitor;
|
||||
|
||||
import oldAst.member.ConstructorNode;
|
||||
import oldAst.member.MethodNode;
|
||||
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);
|
||||
|
||||
}
|
||||
|
Binary file not shown.
106
src/main/java/main/Main.java
Normal file
106
src/main/java/main/Main.java
Normal file
@@ -0,0 +1,106 @@
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
* 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 -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 -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(abstractSyntaxTree);
|
||||
|
||||
/*------------------------- Bytecode Generator -> Bytecode -------------------------*/
|
||||
// Use the ByteCodeGenerator to generate bytecode from the typed AST and output it to the specified directory
|
||||
ByteCodeGenerator byteCodeGenerator = new ByteCodeGenerator(outputDirectoryPath, true, true);
|
||||
assert abstractSyntaxTree != null;
|
||||
byteCodeGenerator.visit((ProgramNode) abstractSyntaxTree);
|
||||
// Log the bytecode generation
|
||||
RaupenLogger.logBytecodeGenerator();
|
||||
}
|
||||
}
|
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,12 +0,0 @@
|
||||
package oldAst;
|
||||
|
||||
//import java.util.List;
|
||||
|
||||
public interface ASTNode {
|
||||
/**
|
||||
* Please implement this method to return a list of children of each node.
|
||||
*/
|
||||
// public List<ASTNode> getChildren();
|
||||
}
|
||||
|
||||
|
@@ -1,4 +0,0 @@
|
||||
package oldAst;
|
||||
|
||||
public class BlockNode {
|
||||
}
|
@@ -1,63 +0,0 @@
|
||||
package oldAst;
|
||||
|
||||
import oldAst.member.ConstructorNode;
|
||||
import oldAst.member.MemberNode;
|
||||
import oldAst.member.MethodNode;
|
||||
import oldAst.type.AccessTypeNode;
|
||||
import oldAst.type.EnumAccessTypeNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import bytecode.visitor.ClassVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class ClassNode implements ASTNode, Visitable {
|
||||
public String identifier;
|
||||
public AccessTypeNode accessType;
|
||||
public List<MemberNode> members = new ArrayList<>();
|
||||
public boolean hasConstructor = false;
|
||||
|
||||
public ClassNode() {}
|
||||
|
||||
public ClassNode(AccessTypeNode accessType, String identifier){
|
||||
this.accessType = 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), identifier);
|
||||
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 oldAst;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import bytecode.visitor.ProgramVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
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,22 +0,0 @@
|
||||
package oldAst.expression;
|
||||
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class BinaryExpressionNode implements ExpressionNode, Visitable {
|
||||
public ExpressionNode left;
|
||||
public ExpressionNode right;
|
||||
public ExpresssionOperator operator; // Stores the operator as a string (e.g., "+", "-", "&&")
|
||||
|
||||
public BinaryExpressionNode(ExpressionNode left, ExpressionNode right, ExpresssionOperator operator) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
package oldAst.expression;
|
||||
|
||||
import oldAst.ASTNode;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import visitor.Visitable;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = BinaryExpressionNode.class, name = "Binary"),
|
||||
@JsonSubTypes.Type(value = This.class, name = "This"),
|
||||
@JsonSubTypes.Type(value = InstVar.class, name = "InstVar"),
|
||||
@JsonSubTypes.Type(value = IdentifierExpressionNode.class, name = "Identifier"),
|
||||
@JsonSubTypes.Type(value = LiteralNode.class, name = "Literal"),
|
||||
@JsonSubTypes.Type(value = UnaryExpressionNode.class, name = "Unary")}
|
||||
)
|
||||
|
||||
public interface ExpressionNode extends ASTNode, Visitable {
|
||||
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
package oldAst.expression;
|
||||
|
||||
public enum ExpresssionOperator {
|
||||
DOT, // . NICHT MEHR GEBRAUCHT
|
||||
PLUS, // +
|
||||
MINUS, // -
|
||||
MULTIPLY, // *
|
||||
DIVIDE, // /
|
||||
NOT, // !
|
||||
ASSIGNMENT, // = (NICHT MEHR GEBRAUCHT ??)
|
||||
EQUALS, // ==
|
||||
UNEQUALS, // !=
|
||||
ERROR //TODO: Remove This
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
package oldAst.expression;
|
||||
|
||||
import oldAst.type.TypeNode;
|
||||
import semantic.SemanticVisitor;
|
||||
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class IdentifierExpressionNode implements ExpressionNode, Visitable {
|
||||
public String name;
|
||||
public TypeNode type;
|
||||
|
||||
|
||||
public IdentifierExpressionNode(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
package oldAst.expression;
|
||||
|
||||
import oldAst.type.TypeNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class InstVar implements ExpressionNode, Visitable {
|
||||
public String identifier;
|
||||
public ExpressionNode expression;
|
||||
public TypeNode type;
|
||||
|
||||
public InstVar(){}
|
||||
|
||||
public InstVar(ExpressionNode expression, String identifier) {
|
||||
this.identifier = identifier;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
package oldAst.expression;
|
||||
|
||||
import oldAst.type.TypeNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class LiteralNode implements ExpressionNode {
|
||||
|
||||
int value;
|
||||
private TypeNode type;
|
||||
|
||||
public LiteralNode(){}
|
||||
|
||||
public LiteralNode(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public TypeNode getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(TypeNode type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
package oldAst.expression;
|
||||
|
||||
import oldAst.ASTNode;
|
||||
import oldAst.type.ReferenceTypeNode;
|
||||
import oldAst.type.TypeNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class This implements ASTNode, ExpressionNode {
|
||||
private TypeNode type;
|
||||
|
||||
public This(){}
|
||||
|
||||
public This(String className) {
|
||||
type = new ReferenceTypeNode(className);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
public TypeNode getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
package oldAst.expression;
|
||||
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class UnaryExpressionNode implements ExpressionNode, Visitable {
|
||||
public ExpressionNode expression;
|
||||
public String operator; // Stores the operator (e.g., "-", "!")
|
||||
|
||||
public UnaryExpressionNode(ExpressionNode expression, String operator) {
|
||||
this.expression = expression;
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,16 +0,0 @@
|
||||
package oldAst.member;
|
||||
|
||||
import oldAst.type.AccessTypeNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class ConstructorNode extends MethodNode implements Visitable {
|
||||
public ConstructorNode(AccessTypeNode visibility, String name) {
|
||||
super(visibility, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
}
|
@@ -1,66 +0,0 @@
|
||||
package oldAst.member;
|
||||
|
||||
import oldAst.parameter.ParameterListNode;
|
||||
import oldAst.statement.StatementNode;
|
||||
import oldAst.type.AccessTypeNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import oldAst.type.TypeNode;
|
||||
import bytecode.visitor.MethodVisitor;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class MethodNode implements MemberNode, Visitable {
|
||||
public AccessTypeNode visibility;
|
||||
public TypeNode type;
|
||||
public String identifier;
|
||||
|
||||
public ParameterListNode parameters;
|
||||
|
||||
public List<StatementNode> statements = new ArrayList<>();
|
||||
|
||||
public MethodNode(){}
|
||||
|
||||
public MethodNode(AccessTypeNode visibility, TypeNode type, String identifier, ParameterListNode parameters,
|
||||
List<StatementNode> statements){
|
||||
this.visibility = visibility;
|
||||
this.type = type;
|
||||
this.identifier = identifier;
|
||||
this.parameters = parameters;
|
||||
this.statements = statements;
|
||||
}
|
||||
|
||||
public MethodNode(AccessTypeNode visibility, String identifier){
|
||||
this.visibility = visibility;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public boolean isSame(MethodNode methodNode){
|
||||
boolean isSame = false;
|
||||
if(methodNode.identifier.equals(identifier)){
|
||||
if(parameters != null && methodNode.parameters != null){
|
||||
if(parameters.parameters.size() == methodNode.parameters.parameters.size()){
|
||||
for(int i = 0; i < parameters.parameters.size(); i++){
|
||||
if(parameters.parameters.get(i).identifier.equals(methodNode.parameters.parameters.get(i).identifier)){
|
||||
isSame = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return isSame;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(MethodVisitor methodVisitor) {
|
||||
methodVisitor.visit(this);
|
||||
}
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
package oldAst.parameter;
|
||||
|
||||
import oldAst.ASTNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ParameterListNode implements ASTNode {
|
||||
public List<ParameterNode> parameters = new ArrayList<>();
|
||||
|
||||
public ParameterListNode() {}
|
||||
|
||||
public ParameterListNode(List<ParameterNode> parameters){
|
||||
this.parameters = parameters;
|
||||
}
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
package oldAst.parameter;
|
||||
|
||||
import oldAst.ASTNode;
|
||||
import oldAst.type.TypeNode;
|
||||
|
||||
public class ParameterNode implements ASTNode {
|
||||
public TypeNode type;
|
||||
public String identifier;
|
||||
|
||||
public ParameterNode(){}
|
||||
|
||||
public ParameterNode(TypeNode type, String identifier) {
|
||||
this.type = type;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
package oldAst.statement;
|
||||
|
||||
import oldAst.expression.ExpressionNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
import visitor.Visitable;
|
||||
|
||||
public class AssignmentStatementNode extends StatementNode implements Visitable {
|
||||
public ExpressionNode expressionLeft;
|
||||
public ExpressionNode expressionRight;
|
||||
// public TypeNode type;
|
||||
|
||||
public AssignmentStatementNode(){}
|
||||
|
||||
public AssignmentStatementNode(ExpressionNode expressionLeft, ExpressionNode expressionRight) {
|
||||
this.expressionLeft = expressionLeft;
|
||||
this.expressionRight = expressionRight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
package oldAst.statement;
|
||||
|
||||
import oldAst.expression.ExpressionNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
package oldAst.statement;
|
||||
|
||||
import oldAst.expression.ExpressionNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class ReturnStatementNode extends StatementNode {
|
||||
public ExpressionNode expression;
|
||||
|
||||
public ReturnStatementNode(ExpressionNode expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
package oldAst.statement;
|
||||
|
||||
import oldAst.ASTNode;
|
||||
import visitor.Visitable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = IfStatementNode.class, name = "IF"),
|
||||
@JsonSubTypes.Type(value = AssignmentStatementNode.class, name = "Assignment"),
|
||||
@JsonSubTypes.Type(value = VariableDeclarationStatementNode.class, name = "VariableDeclaration") }
|
||||
)
|
||||
|
||||
public abstract class StatementNode implements ASTNode, Visitable {
|
||||
}
|
||||
|
@@ -1,25 +0,0 @@
|
||||
package oldAst.statement;
|
||||
|
||||
import oldAst.expression.ExpressionNode;
|
||||
import oldAst.type.TypeNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class VariableDeclarationStatementNode extends StatementNode {
|
||||
public TypeNode type;
|
||||
public String identifier;
|
||||
public ExpressionNode expression;
|
||||
|
||||
public VariableDeclarationStatementNode(){}
|
||||
|
||||
public VariableDeclarationStatementNode(TypeNode type, String identifier, ExpressionNode expression) {
|
||||
this.type = type;
|
||||
this.identifier = identifier;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
package oldAst.statement;
|
||||
|
||||
import oldAst.expression.ExpressionNode;
|
||||
import semantic.SemanticVisitor;
|
||||
import typechecker.TypeCheckResult;
|
||||
|
||||
public class WhileStatementNode extends StatementNode {
|
||||
public ExpressionNode condition;
|
||||
public StatementNode body;
|
||||
|
||||
public WhileStatementNode(ExpressionNode condition, StatementNode body) {
|
||||
this.condition = condition;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult accept(SemanticVisitor visitor) {
|
||||
return visitor.analyze(this);
|
||||
}
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
package oldAst.type;
|
||||
|
||||
import oldAst.ASTNode;
|
||||
|
||||
public class AccessTypeNode implements ASTNode {
|
||||
public EnumAccessTypeNode enumAccessTypeNode;
|
||||
|
||||
public AccessTypeNode(){}
|
||||
|
||||
public AccessTypeNode(EnumAccessTypeNode enumAccessTypeNode) {
|
||||
this.enumAccessTypeNode = enumAccessTypeNode;
|
||||
}
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
package oldAst.type;
|
||||
|
||||
import oldAst.ASTNode;
|
||||
|
||||
public class BaseTypeNode implements ASTNode, TypeNode {
|
||||
|
||||
public EnumTypeNode enumType;
|
||||
|
||||
public BaseTypeNode(){}
|
||||
|
||||
public BaseTypeNode(EnumTypeNode enumType) {
|
||||
this.enumType = enumType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
BaseTypeNode other = (BaseTypeNode) obj;
|
||||
if (enumType != other.enumType)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
package oldAst.type;
|
||||
|
||||
public enum EnumAccessTypeNode {
|
||||
PUBLIC, PRIVATE
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
package oldAst.type;
|
||||
|
||||
public enum EnumTypeNode {
|
||||
INT, BOOLEAN, CHAR
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
package oldAst.type;
|
||||
|
||||
import oldAst.ASTNode;
|
||||
|
||||
public class ReferenceTypeNode implements ASTNode, TypeNode {
|
||||
|
||||
private String identifier;
|
||||
|
||||
public ReferenceTypeNode() {}
|
||||
|
||||
public ReferenceTypeNode(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;
|
||||
ReferenceTypeNode other = (ReferenceTypeNode) obj;
|
||||
if (identifier == null) {
|
||||
if (other.identifier != null)
|
||||
return false;
|
||||
} else if (!identifier.equals(other.identifier))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
package oldAst.type;
|
||||
|
||||
import oldAst.ASTNode;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = BaseTypeNode.class, name = "Base"),
|
||||
|
||||
@JsonSubTypes.Type(value = ReferenceTypeNode.class, name = "Reference") }
|
||||
)
|
||||
|
||||
public interface TypeNode extends ASTNode {
|
||||
}
|
@@ -1,21 +1,34 @@
|
||||
package parser.astBuilder;
|
||||
|
||||
import oldAst.*;
|
||||
import oldAst.expression.*;
|
||||
import oldAst.member.FieldNode;
|
||||
import oldAst.member.MemberNode;
|
||||
import oldAst.member.MethodNode;
|
||||
import oldAst.parameter.ParameterListNode;
|
||||
import oldAst.parameter.ParameterNode;
|
||||
import oldAst.statement.*;
|
||||
import oldAst.type.*;
|
||||
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;
|
||||
import parser.generated.*;
|
||||
import parser.generated.SimpleJavaParser.LiteralContext;
|
||||
import oldAst.type.BaseTypeNode;
|
||||
|
||||
public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
|
||||
@Override
|
||||
@@ -29,188 +42,563 @@ public class ASTBuilder extends SimpleJavaBaseVisitor<ASTNode> {
|
||||
|
||||
@Override
|
||||
public ASTNode visitClassDeclaration(SimpleJavaParser.ClassDeclarationContext ctx) {
|
||||
ClassNode classNode = new ClassNode((AccessTypeNode) visit(ctx.accessType()),ctx.IDENTIFIER().getText());
|
||||
classNode.identifier = ctx.IDENTIFIER().getText();
|
||||
for (SimpleJavaParser.MemberDeclarationContext member : ctx.memberDeclaration()) {
|
||||
classNode.addMember((MemberNode) visit(member));
|
||||
ClassNode classNode;
|
||||
if(ctx.AccessModifier() != null){
|
||||
classNode = new ClassNode(ctx.AccessModifier().getText(), ctx.Identifier().getText());
|
||||
}
|
||||
classNode.ensureConstructor();
|
||||
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 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);
|
||||
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) {
|
||||
AccessTypeNode accessType = (AccessTypeNode) visit(ctx.accessType());
|
||||
TypeNode returnType = (TypeNode) visit(ctx.type());
|
||||
String methodName = ctx.IDENTIFIER().getText();
|
||||
|
||||
ParameterListNode parameterListNode = null;
|
||||
if(ctx.parameterList() != null) {
|
||||
parameterListNode = (ParameterListNode) visit(ctx.parameterList());
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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));
|
||||
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());
|
||||
}
|
||||
return new ParameterListNode(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitParameter(SimpleJavaParser.ParameterContext ctx) {
|
||||
TypeNode typeNode = (TypeNode) visit(ctx.type());
|
||||
String identifier = ctx.IDENTIFIER().getText();
|
||||
return new ParameterNode(typeNode, identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitType(SimpleJavaParser.TypeContext ctx) {
|
||||
String typeStr = ctx.getText();
|
||||
switch (typeStr) {
|
||||
case "int":
|
||||
return new BaseTypeNode(EnumTypeNode.INT);
|
||||
case "boolean":
|
||||
return new BaseTypeNode(EnumTypeNode.BOOLEAN);
|
||||
case "char":
|
||||
return new BaseTypeNode(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);
|
||||
}
|
||||
return new ParameterNode(createTypeNode(ctx.type().getText()), ctx.Identifier().getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitStatement(SimpleJavaParser.StatementContext ctx) {
|
||||
if (ctx.variableDeclarationStatement() != null) {
|
||||
return visitVariableDeclarationStatement(ctx.variableDeclarationStatement());
|
||||
} else if (ctx.assignmentStatement() != null) {
|
||||
return visitAssignmentStatement(ctx.assignmentStatement());
|
||||
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 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) {
|
||||
ExpressionNode expression = (ExpressionNode) visit(ctx.expression());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitVar(SimpleJavaParser.VarContext ctx) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@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 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);
|
||||
}
|
||||
return new ReturnStatementNode(expression);
|
||||
|
||||
}
|
||||
|
||||
@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 = new IfElseNode((IfNode) visit(ctx.ifStatement()),
|
||||
(ElseNode) visit(ctx.elseStatement()));
|
||||
|
||||
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) {
|
||||
// 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));
|
||||
return new BinaryExpressionNode(left, right, ExpresssionOperator.ERROR);
|
||||
if(ctx.unaryExpression() != null) {
|
||||
return visit(ctx.unaryExpression());
|
||||
} else if(ctx.binaryExpression() != null) {
|
||||
return visit(ctx.binaryExpression());
|
||||
}
|
||||
// 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
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode visitLiteral(SimpleJavaParser.LiteralContext ctx) {
|
||||
LiteralContext literalContext = (LiteralContext) ctx;
|
||||
try {
|
||||
int intValue = Integer.parseInt(literalContext.getText());
|
||||
LiteralNode literalNode = new LiteralNode(intValue);
|
||||
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;
|
||||
}
|
||||
|
||||
literalNode.setType(new BaseTypeNode(EnumTypeNode.INT));
|
||||
return literalNode;
|
||||
} catch (NumberFormatException ignored) {}
|
||||
@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;
|
||||
}
|
||||
|
||||
return null; // Return null or throw an exception if no valid expression found
|
||||
@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