Compare commits
254 Commits
dfa5588514
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22d925810f | ||
|
|
b4f59ce5c3 | ||
|
|
5239e608bc | ||
|
|
079668b9f8 | ||
|
|
58f6dc74e4 | ||
|
|
88ce2a985c | ||
|
|
a2fa6f55d4 | ||
|
|
8d4e8a9269 | ||
| c2c0c0b442 | |||
|
|
ec400479bb | ||
| 167b8e80b5 | |||
|
|
0baac36f35 | ||
|
|
da53e5d6dc | ||
|
|
0593d988b4 | ||
|
|
8e55eaca93 | ||
|
|
31ac237ffd | ||
|
|
e56139080f | ||
|
|
f807721293 | ||
|
|
271bbf4b4b | ||
|
|
5b4d08ba01 | ||
|
|
3b5f157bb5 | ||
|
|
59183f5b44 | ||
|
|
302b907d36 | ||
|
|
32353b9a37 | ||
|
|
3e908293ee | ||
|
|
aed7af7c68 | ||
|
|
3a8b9ea9cd | ||
|
|
aa8a647fa1 | ||
|
|
51240806b9 | ||
|
|
8f55a15aef | ||
| edfaa93980 | |||
|
|
4b36453ff3 | ||
|
|
78d6d402a2 | ||
|
|
0533ddbc5d | ||
|
|
920fa2fa48 | ||
|
|
dbb61e2a81 | ||
|
|
7fb7cea2f7 | ||
|
|
7e8c297d9a | ||
|
|
c9ce9e02db | ||
|
|
4dfea0d69d | ||
|
|
e801717444 | ||
|
|
6a56f51050 | ||
| 403b31c550 | |||
|
|
82384886c6 | ||
|
|
1dd405a00f | ||
| 6948797001 | |||
|
|
d7016df1ba | ||
|
|
384a5e9066 | ||
|
|
5d75c23f49 | ||
|
|
ba9760fe43 | ||
|
|
888534955a | ||
|
|
f6358867f0 | ||
|
|
0711028dc3 | ||
|
|
97ab66122e | ||
|
|
1100cef668 | ||
|
|
3c863aafde | ||
|
|
41d5cd428c | ||
|
|
5dd3821ecb | ||
|
|
c5752df15e | ||
|
|
88bcfa5fa3 | ||
|
|
5dae167443 | ||
|
|
47a8d50185 | ||
|
|
94b3830561 | ||
|
|
3dcaad62f9 | ||
|
|
62060462a9 | ||
|
|
d5b526b8fc | ||
|
|
10f5dc692d | ||
|
|
e46cede8d5 | ||
|
|
38aeaa657d | ||
|
|
cabbbdcaf3 | ||
|
|
192dfae94b | ||
|
|
c24a483880 | ||
|
|
aa7d82b9ac | ||
|
|
94ea539fab | ||
|
|
6bf2c75e02 | ||
|
|
d2b307f86f | ||
|
|
5b0dc04bd7 | ||
| 6c015e72d5 | |||
|
|
cd9fc46a1f | ||
|
|
9b0d8147db | ||
|
|
21ece58cc9 | ||
| 8e0b215140 | |||
| 3fa8400b72 | |||
|
|
07552e704e | ||
|
|
194ff3fcf7 | ||
|
|
f5dcd4d79f | ||
| 492bab5477 | |||
|
|
99d23e89fa | ||
|
|
16cf78521b | ||
| 0c9acb2bc9 | |||
|
|
2c7748e6a3 | ||
|
|
4b2edaa6ff | ||
|
|
dd2842138f | ||
|
|
942597d535 | ||
|
|
392fea7d23 | ||
|
|
d1da1c6eee | ||
|
|
b787b333fb | ||
|
|
27ca4a978f | ||
|
|
289231030a | ||
| 3b2a328182 | |||
|
|
127726d342 | ||
|
|
4bc38c0ff9 | ||
|
|
34f4f307f3 | ||
|
|
c30dcdb773 | ||
|
|
f6bb836ee0 | ||
|
|
7498ca6e4d | ||
|
|
66c7722728 | ||
| 4b7cb0b150 | |||
|
|
1358e3372f | ||
|
|
5c81b88ca5 | ||
|
|
a3000d0ba1 | ||
|
|
d4f98693d6 | ||
|
|
6365e994d2 | ||
|
|
377e9b3193 | ||
|
|
eac4eb1db8 | ||
|
|
d8602ddd18 | ||
| b84ad2ef6b | |||
| 60958538d8 | |||
|
|
ed2f64eff9 | ||
|
|
77a6dae94f | ||
|
|
30334dc393 | ||
|
|
2a2e14ae21 | ||
| 9cf2ff6f37 | |||
| b402857713 | |||
|
|
8182e1ee7a | ||
|
|
ae260f6feb | ||
|
|
7daece9b8f | ||
|
|
b95bc75a1e | ||
|
|
1dac9245f2 | ||
|
|
90936affb9 | ||
|
|
9ff069827a | ||
|
|
87e863e773 | ||
|
|
c764b710ea | ||
|
|
e7d4a83a1d | ||
|
|
dcb564bd0d | ||
| c8c12e4d9a | |||
|
|
e23d84cd09 | ||
|
|
8a26f700b5 | ||
| 621ce16615 | |||
|
|
5a66ce97ca | ||
|
|
fdae734452 | ||
| ebd4f7ca4e | |||
|
|
719e19e7f8 | ||
|
|
5220a65a92 | ||
|
|
6585e67273 | ||
|
|
6915a97432 | ||
| c96d9fc1a1 | |||
| b00979c1a8 | |||
| 112c5f2c1b | |||
|
|
46ac49576e | ||
|
|
eaac9898f4 | ||
|
|
e70580ac86 | ||
| afd2319d78 | |||
| 821908f060 | |||
|
|
d8397753ca | ||
|
|
6fa199da1d | ||
| 666931fa44 | |||
| cdc81f705a | |||
|
|
6f9791455d | ||
|
|
0f76b1fdae | ||
|
|
c44ed5446d | ||
|
|
fa430301bb | ||
| 23f541ff7d | |||
|
|
bc984a89e1 | ||
|
|
63059994ec | ||
|
|
949c2de28e | ||
|
|
c71d5454c6 | ||
| d665c0393c | |||
| 39e8e0ea6a | |||
|
|
0d827c5f32 | ||
|
|
ec38d8049b | ||
| 9d9dcfb9b6 | |||
|
|
66428159c1 | ||
| 77bf6cff62 | |||
| a97548c3ee | |||
|
|
06dc01f629 | ||
|
|
50215afb07 | ||
|
|
5592a6cfe1 | ||
|
|
dac0b3370f | ||
|
|
519d891743 | ||
| d4cc24239d | |||
| 25d379876b | |||
|
|
abc4e3ff70 | ||
|
|
a147512dcb | ||
|
|
b20b7adc99 | ||
| 3953bbe549 | |||
| 7458be43d7 | |||
|
|
8d6d8d5588 | ||
|
|
ef38079f58 | ||
|
|
9d86ab3a9f | ||
| 95313d8083 | |||
| 8549799175 | |||
|
|
21dff015b5 | ||
|
|
9fa9dfdfb6 | ||
|
|
ab19751146 | ||
|
|
5fa6664850 | ||
|
|
08d13a0df7 | ||
| d6fb825808 | |||
| 873d1b7a0a | |||
| d1e39be655 | |||
|
|
b91174eeee | ||
|
|
108b8f63ea | ||
|
|
3be8d9854a | ||
|
|
35fba57efa | ||
|
|
6148b46063 | ||
|
|
a59950e186 | ||
|
|
0fcea195de | ||
|
|
f2260c7a73 | ||
|
|
74e3cb8016 | ||
|
|
2f549e31e9 | ||
| 0a81315366 | |||
| 99b979d77f | |||
|
|
6eb26e70d5 | ||
|
|
7ff84e5ad7 | ||
|
|
87cde5e048 | ||
|
|
c3a9b9a7d6 | ||
|
|
4ca936e619 | ||
|
|
6e707cc7ed | ||
|
|
d22ea6b962 | ||
| 091eaa912e | |||
| e99b7adcd4 | |||
| 3783a1d61b | |||
| d0f3f3b938 | |||
|
|
b5b6f763e0 | ||
| cc05c58159 | |||
| 91340125ef | |||
| 484418e884 | |||
|
|
309aff9576 | ||
|
|
4c73ae6786 | ||
|
|
4f2599d053 | ||
|
|
371755f390 | ||
|
|
9ec583b17f | ||
|
|
9166d87afd | ||
|
|
1cd4d87a94 | ||
|
|
cf590b2248 | ||
|
|
0576bd303d | ||
|
|
334f470488 | ||
|
|
85282ff90c | ||
|
|
dbcf40ea84 | ||
|
|
8419b1aa17 | ||
|
|
80917ec222 | ||
|
|
965b758fba | ||
|
|
5de106876a | ||
|
|
2c6bef9e9e | ||
|
|
950354a2e7 | ||
|
|
2b671c32db | ||
|
|
ec7dd2a10d | ||
|
|
b8a8a094f4 | ||
|
|
fe249c5b2a | ||
|
|
1617e3ec62 | ||
|
|
f273c74693 | ||
|
|
783bab8580 | ||
|
|
9cda409dd3 | ||
|
|
103e80e318 |
6
.idea/.gitignore
generated
vendored
Normal file
6
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
|
||||
.idea/# GitHub Copilot persisted chat sessions
|
||||
/copilot/chatSessions
|
||||
13
.idea/compiler.xml
generated
Normal file
13
.idea/compiler.xml
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<annotationProcessing>
|
||||
<profile name="Maven default annotation processors profile" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<module name="NichtHaskell" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
7
.idea/encodings.xml
generated
Normal file
7
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
20
.idea/jarRepositories.xml
generated
Normal file
20
.idea/jarRepositories.xml
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<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" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
34
.idea/misc.xml
generated
Normal file
34
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ANTLRGenerationPreferences">
|
||||
<option name="perGrammarGenerationSettings">
|
||||
<list>
|
||||
<PerGrammarGenerationSettings>
|
||||
<option name="fileName" value="$PROJECT_DIR$/src/main/java/Decaf.g4" />
|
||||
<option name="autoGen" value="true" />
|
||||
<option name="outputDir" value="C:\Users\User\DHBW\Compiler\src\main\java" />
|
||||
<option name="libDir" value="" />
|
||||
<option name="encoding" value="" />
|
||||
<option name="pkg" value="gen" />
|
||||
<option name="language" value="" />
|
||||
<option name="generateVisitor" value="true" />
|
||||
</PerGrammarGenerationSettings>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="MavenProjectsManager">
|
||||
<option name="originalFiles">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/pom.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="PWA">
|
||||
<option name="enabled" value="true" />
|
||||
<option name="wasEnabledAtLeastOnce" value="true" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="openjdk-22" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/target" />
|
||||
</component>
|
||||
</project>
|
||||
2
Source/.idea/modules.xml → .idea/modules.xml
generated
2
Source/.idea/modules.xml → .idea/modules.xml
generated
@@ -2,7 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/Source.iml" filepath="$PROJECT_DIR$/.idea/Source.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/NichtHaskell.iml" filepath="$PROJECT_DIR$/NichtHaskell.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
2
Source/.idea/vcs.xml → .idea/vcs.xml
generated
2
Source/.idea/vcs.xml → .idea/vcs.xml
generated
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
Binary file not shown.
BIN
Documentation/DokumentationNichtHaskell.pdf
Normal file
BIN
Documentation/DokumentationNichtHaskell.pdf
Normal file
Binary file not shown.
BIN
Documentation/KlassendiagrammFields.jpg
Normal file
BIN
Documentation/KlassendiagrammFields.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 766 KiB |
BIN
Documentation/KlassendiagrammUML.jpg
Normal file
BIN
Documentation/KlassendiagrammUML.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 MiB |
BIN
Documentation/KlassendiagrammVereinfacht.pdf
Normal file
BIN
Documentation/KlassendiagrammVereinfacht.pdf
Normal file
Binary file not shown.
BIN
Documentation/PraesentationNichtHaskell.pdf
Normal file
BIN
Documentation/PraesentationNichtHaskell.pdf
Normal file
Binary file not shown.
20
Examples/Fakultaet.java
Normal file
20
Examples/Fakultaet.java
Normal file
@@ -0,0 +1,20 @@
|
||||
class Fakultaet {
|
||||
public int fak(int number) {
|
||||
if (number < 0) {
|
||||
return 1;
|
||||
}
|
||||
int factorial = 1;
|
||||
int i = 1;
|
||||
while(i <= number){
|
||||
factorial = factorial * i;
|
||||
i = i + 1;
|
||||
}
|
||||
|
||||
return factorial;
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
Fakultaet f = new Fakultaet();
|
||||
int result = f.fak(5);
|
||||
print(result);
|
||||
}
|
||||
}
|
||||
40
Examples/FieldAccessAndMethodCalls.java
Normal file
40
Examples/FieldAccessAndMethodCalls.java
Normal file
@@ -0,0 +1,40 @@
|
||||
class FieldAccessAndMethodCalls {
|
||||
public static void main(String[] args) {
|
||||
Class1 c1 = new Class1();
|
||||
int i = c1.c2.c3.m3(1).m2().m1();
|
||||
print(i);
|
||||
}
|
||||
}
|
||||
|
||||
class Class1{
|
||||
int i1;
|
||||
Class2 c2;
|
||||
public Class1() {
|
||||
this.c2 = new Class2();
|
||||
}
|
||||
public int m1(){
|
||||
return i1;
|
||||
}
|
||||
}
|
||||
|
||||
class Class2{
|
||||
int i2;
|
||||
Class3 c3;
|
||||
public Class2(){
|
||||
this.c3 = new Class3();
|
||||
}
|
||||
public Class1 m2(){
|
||||
Class1 c1 = new Class1();
|
||||
c1.i1 = i2;
|
||||
return c1;
|
||||
}
|
||||
}
|
||||
|
||||
class Class3{
|
||||
int i3;
|
||||
public Class2 m3(int i){
|
||||
Class2 c2 = new Class2();
|
||||
c2.i2 = i;
|
||||
return c2;
|
||||
}
|
||||
}
|
||||
166
Grammatik.txt
166
Grammatik.txt
@@ -1,166 +0,0 @@
|
||||
Grammatik:
|
||||
|
||||
1. Ausdrücke
|
||||
|
||||
Primary:
|
||||
Literal
|
||||
Variable
|
||||
IncDecExpression
|
||||
( Expression )
|
||||
MethodInvocation
|
||||
|
||||
Variable:
|
||||
Identifier { [ Expression ] }
|
||||
|
||||
Identifier:
|
||||
[ Identifier . ] Name
|
||||
|
||||
IncDecExpression:
|
||||
Variable IncDec
|
||||
IncDec Variable
|
||||
|
||||
IncDec:
|
||||
++ | --
|
||||
|
||||
Expression:
|
||||
UnaryExpression
|
||||
BinaryExpression
|
||||
AssignmentExpression
|
||||
MethodInvocation
|
||||
CreationExpression
|
||||
|
||||
UnaryExpression:
|
||||
Primary
|
||||
UnaryExpression
|
||||
UnaryOperator
|
||||
+ | - | ! | ...
|
||||
|
||||
BinaryExpression:
|
||||
Expression BinaryOperator Expression
|
||||
|
||||
BinaryOperator:
|
||||
== | + | - | * | / | & | && | | | || |
|
||||
|
||||
|
||||
AssignmentExpression:
|
||||
Variable = Expression
|
||||
|
||||
MethodInvocation:
|
||||
Method ( [ ActualArguments ] )
|
||||
|
||||
Method:
|
||||
Identifier
|
||||
|
||||
ActualArguments:
|
||||
Expression { , Expression }
|
||||
|
||||
CreationExpression:
|
||||
new ClassIdentifier ( [ ActualArguments ] )
|
||||
|
||||
|
||||
|
||||
2. Anweisungen
|
||||
|
||||
Statement:
|
||||
SimpleStatement
|
||||
CompositeStatement
|
||||
Label : Statement
|
||||
|
||||
SimpleStatement:
|
||||
EmptyStatement
|
||||
StatementExpression
|
||||
EmptyStatement ;
|
||||
ReturnStatement
|
||||
|
||||
StatementExpression:
|
||||
AssignmentExpression
|
||||
IncDecExpression
|
||||
MethodInvocation
|
||||
CreationExpression
|
||||
|
||||
ContinueStatement:
|
||||
continue [ Name ] ;
|
||||
|
||||
ReturnStatement.
|
||||
return [ Expression ] ;
|
||||
|
||||
|
||||
CompositeStatement:
|
||||
Block
|
||||
CaseStatement
|
||||
|
||||
Block:
|
||||
"{" { VariableDeclaration | Statement } "}"
|
||||
|
||||
VariableDeclaration:
|
||||
Type VariableDeclarator ;
|
||||
|
||||
VariableDeclarator:
|
||||
Name [ = Expression ]
|
||||
|
||||
Type:
|
||||
Name # konkrete Typen hinzufügen
|
||||
Identifier
|
||||
|
||||
CaseStatement: # Andere CaseStatements heraussuchen. Assign, MethodCall,
|
||||
ConditionalStatement
|
||||
WhileStatement
|
||||
|
||||
|
||||
ConditionalStatement:
|
||||
if ( Expression ) Statement [ else Statement ]
|
||||
|
||||
ConstantExpression:
|
||||
Expression
|
||||
|
||||
WhileStatement:
|
||||
while ( Expression ) Statement
|
||||
|
||||
Initialization:
|
||||
StatementExpression { , StatementExpression }
|
||||
VariableDeclaration
|
||||
|
||||
|
||||
3. Methoden
|
||||
|
||||
MethodDeclaration:
|
||||
MethodHeader Block
|
||||
|
||||
MethodHeader:
|
||||
{ Modifier } ResultType MethodDeclarator
|
||||
|
||||
Modifier:
|
||||
public | static | ...
|
||||
|
||||
ResultType:
|
||||
Type | void
|
||||
|
||||
MethodDeclarator:
|
||||
Identifier "(" [ FormalArguments ] ")"
|
||||
|
||||
FormalArguments:
|
||||
FormalArgument { , FormalArgument }
|
||||
|
||||
FormalArgument:
|
||||
Type Name
|
||||
|
||||
|
||||
|
||||
4. Klassen
|
||||
|
||||
Start:
|
||||
ClassDeclaration {ClassDeclaration}
|
||||
|
||||
ClassDeclaration:
|
||||
[ public ] class Name ClassBody
|
||||
|
||||
ClassBody:
|
||||
"{" { { Modifier } Declaration } "}"
|
||||
|
||||
Declaration:
|
||||
VariableDeclaration
|
||||
MethodDeclaration
|
||||
ConstructorDeclaration
|
||||
|
||||
ConstructorDeclaration:
|
||||
[ public ] Name ( [ FormalArguments ] ) Block
|
||||
@@ -1 +1,3 @@
|
||||
Please move your stuff from "Source" to "src".
|
||||
Dies ist das Repository des Mini-Java-Compiler-Bauprojekt der Gruppe NichtHaskell für das 4. Semester Informatik der Dualen Hochschule Baden-Württemberg in Stuttgart (Horb).
|
||||
|
||||
Alles weitere ist in der Dokumentation DokumentationNichtHaskell.pdf unter `/Documentation/DokumentationNichtHaskell.pdf` zu finden.
|
||||
8
Source/.idea/.gitignore
generated
vendored
8
Source/.idea/.gitignore
generated
vendored
@@ -1,8 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
11
Source/.idea/Source.iml
generated
11
Source/.idea/Source.iml
generated
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
Source/.idea/misc.xml
generated
6
Source/.idea/misc.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,32 +0,0 @@
|
||||
package TypeCheck;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class TypeCheckHelper {
|
||||
public String upperBound(String type1, String type2) throws Exception{
|
||||
boolean type1Primitiv = Objects.equals(type1, "bool") || Objects.equals(type1, "int") || Objects.equals(type1, "char");
|
||||
boolean type2Primitiv = Objects.equals(type2, "bool") || Objects.equals(type2, "int") || Objects.equals(type2, "char");
|
||||
|
||||
String result;
|
||||
if(type1Primitiv && type2Primitiv){
|
||||
if(Objects.equals(type1, type2)){
|
||||
result = type1;
|
||||
}
|
||||
throw new Exception("no upper bound");
|
||||
}else if(type1Primitiv || type2Primitiv){
|
||||
throw new Exception("no upper bound");
|
||||
}else{
|
||||
result = "class";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static boolean typeExists(String type, List<String> typeslist) {
|
||||
|
||||
if(type.equals("int") || type.equals("bool") || type.equals("char")){
|
||||
return true;
|
||||
}
|
||||
return typeslist.contains(type);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package TypeCheck;
|
||||
|
||||
public class TypeCheckResult {
|
||||
public String type;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package abstractSyntaxTree.Class;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Program;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class FieldDecl extends AbstractType implements IClass{
|
||||
|
||||
private HashMap<String, HashMap<String, String>> typeContext; // form class from program
|
||||
public String type; // from parser
|
||||
public String identifier; // from parser
|
||||
|
||||
public FieldDecl(HashMap<String, HashMap<String, String>> typeContext){
|
||||
this.typeContext = typeContext;
|
||||
}
|
||||
public TypeCheckResult typeCheck(List<FieldDecl> classFieldsIdentifier) throws Exception {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
if (classFieldsIdentifier.contains(this.identifier)){
|
||||
throw new Exception("field already defined");
|
||||
} else {
|
||||
classFieldsIdentifier.add(this);
|
||||
}
|
||||
//TypeCheckHelper.typeExists(type, ) // need all types of classes
|
||||
setTypeCheckResult(result);
|
||||
|
||||
return result;
|
||||
|
||||
//write field table
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package abstractSyntaxTree.Class;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IClass {
|
||||
// visit method for code generation
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package abstractSyntaxTree.Class;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Program;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class MethodDecl implements IClass {
|
||||
|
||||
// name
|
||||
|
||||
private HashMap<String, HashMap<String, HashMap<String, String>>> methodContext;
|
||||
private HashMap<String, HashMap<String, String>> typeContext;
|
||||
|
||||
//TODO: Move this into the typeCheck
|
||||
private HashMap<String, String> localVars; // (type, identifier) // add content here
|
||||
|
||||
public MethodDecl(HashMap<String, HashMap<String, HashMap<String, String>>> methodContext, HashMap<String, HashMap<String, String>> typeContext){
|
||||
this.methodContext = methodContext;
|
||||
this.typeContext = typeContext;
|
||||
}
|
||||
public TypeCheckResult typeCheck(List<MethodDecl> fieldsOrMethods) throws Exception {
|
||||
// write localvars
|
||||
|
||||
// jede methode als block statement aufrufen
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package abstractSyntaxTree.Datatype;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public class CharDatatype extends AbstractType implements IDatatype{
|
||||
char value;
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
result.type = "char";
|
||||
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
|
||||
// Possible use of BIPUSH and SIPUSH if the value is small enough
|
||||
//This saves space in the bytecode which is not very relevant at this point, but could be implemented anyway
|
||||
|
||||
mv.visitLdcInsn((int)value);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package abstractSyntaxTree.Datatype;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public interface IDatatype {
|
||||
// typeCheck method
|
||||
TypeCheckResult typeCheck() throws Exception;
|
||||
|
||||
// visit method for code generation
|
||||
|
||||
void codeGen(MethodVisitor mv) throws Exception;
|
||||
}
|
||||
|
||||
//TODO: Check if we need to differentiate between primitive types and reference types --> for example in "=="
|
||||
@@ -1,59 +0,0 @@
|
||||
package abstractSyntaxTree.Datatype;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Program;
|
||||
import jdk.jshell.spi.ExecutionControl;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class RefType extends AbstractType implements IDatatype {
|
||||
|
||||
String name;
|
||||
public List<FieldDecl> fieldDecls;
|
||||
public List<MethodDecl> methodDecls;
|
||||
private HashMap<String, HashMap<String, String>> typeContext; // (class, (type, identifier))
|
||||
private HashMap<String, HashMap<String, HashMap<String, String>>> methodContext; // (class, (returntype, (identifier, parameter)
|
||||
|
||||
private boolean hasMain;
|
||||
|
||||
public RefType(List<FieldDecl> fieldDecls,
|
||||
List<MethodDecl> methodDecls,
|
||||
HashMap<String, HashMap<String, String>> typeContext,
|
||||
HashMap<String, HashMap<String, HashMap<String, String>>> methodContext){
|
||||
this.fieldDecls = fieldDecls;
|
||||
this.methodDecls = methodDecls;
|
||||
this.typeContext = typeContext;
|
||||
this.methodContext = methodContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
for (FieldDecl fieldDecl : fieldDecls) {
|
||||
fieldDecl.typeCheck(fieldDecls);
|
||||
}
|
||||
|
||||
for (MethodDecl methodDecl : methodDecls) {
|
||||
methodDecl.typeCheck(methodDecls);
|
||||
}
|
||||
|
||||
result.type = "class";
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Method for code generation which iterates over all the field declarations
|
||||
// and method declarations and calls their CodeGen methods
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
throw new ExecutionControl.NotImplementedException("CodeGen not implemented for RefType");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.beans.Expression;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BinaryExpression extends AbstractType implements IExpression{
|
||||
|
||||
public String operator;
|
||||
public IExpression left;
|
||||
public IExpression right;
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckHelper helper = new TypeCheckHelper();
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
TypeCheckResult leftType = left.typeCheck();
|
||||
TypeCheckResult rightType = right.typeCheck();
|
||||
|
||||
switch (operator) {
|
||||
|
||||
case "&&":
|
||||
case "||" :{
|
||||
if (Objects.equals(helper.upperBound(leftType.type, rightType.type), "bool")){
|
||||
result.type = "bool";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "==":
|
||||
case "<":
|
||||
case ">":
|
||||
case "<=":
|
||||
case ">=":
|
||||
case "!=":
|
||||
result.type = helper.upperBound(leftType.type, rightType.type);
|
||||
break;
|
||||
|
||||
case "-":
|
||||
case "+":
|
||||
case "*":
|
||||
case "/":
|
||||
if (Objects.equals(helper.upperBound(leftType.type, rightType.type), "int")){
|
||||
result.type = "int";
|
||||
}
|
||||
break;
|
||||
|
||||
//case "&" ist für logisches und auf bit level
|
||||
//case "|" ist für logisches oder auf bit level
|
||||
}
|
||||
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
// Label for the jump instruction
|
||||
Label operationFalse = new Label(); //Operation is false
|
||||
Label operationTrue = new Label(); //Operation is true
|
||||
// Labels are placed at the end of this method
|
||||
Label expressionEnd = new Label(); //End of the whole expression
|
||||
|
||||
// Bytecode for the binary operation
|
||||
switch (operator) {
|
||||
case "&&":
|
||||
left.codeGen(mv);
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
|
||||
|
||||
right.codeGen(mv);
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // If right exp is false, jump to the end of the whole expression
|
||||
|
||||
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
|
||||
break;
|
||||
|
||||
case "||":
|
||||
left.codeGen(mv);
|
||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
|
||||
|
||||
right.codeGen(mv);
|
||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
|
||||
break;
|
||||
|
||||
case "==":
|
||||
// Keep in mind that only primitive types are allowed in this case (at this time)
|
||||
|
||||
left.codeGen(mv);
|
||||
right.codeGen(mv);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression
|
||||
break;
|
||||
|
||||
case "<":
|
||||
left.codeGen(mv);
|
||||
right.codeGen(mv);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
|
||||
break;
|
||||
|
||||
case ">":
|
||||
left.codeGen(mv);
|
||||
right.codeGen(mv);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
|
||||
break;
|
||||
|
||||
case "<=":
|
||||
left.codeGen(mv);
|
||||
right.codeGen(mv);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
|
||||
break;
|
||||
|
||||
case ">=":
|
||||
left.codeGen(mv);
|
||||
right.codeGen(mv);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
|
||||
break;
|
||||
|
||||
case "!=":
|
||||
left.codeGen(mv);
|
||||
right.codeGen(mv);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
|
||||
break;
|
||||
|
||||
case "+":
|
||||
left.codeGen(mv);
|
||||
right.codeGen(mv);
|
||||
mv.visitInsn(Opcodes.IADD);
|
||||
break;
|
||||
|
||||
case "-":
|
||||
left.codeGen(mv);
|
||||
right.codeGen(mv);
|
||||
mv.visitInsn(Opcodes.ISUB);
|
||||
break;
|
||||
|
||||
case "*":
|
||||
left.codeGen(mv);
|
||||
right.codeGen(mv);
|
||||
mv.visitInsn(Opcodes.IMUL);
|
||||
break;
|
||||
|
||||
case "/":
|
||||
left.codeGen(mv);
|
||||
right.codeGen(mv);
|
||||
mv.visitInsn(Opcodes.IDIV);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception("Unknown operator: " + operator);
|
||||
}
|
||||
|
||||
mv.visitLabel(operationFalse);
|
||||
mv.visitInsn(Opcodes.ICONST_0); // Push false on the stack
|
||||
mv.visitJumpInsn(Opcodes.GOTO, expressionEnd); // Jump to the end of the expression (skip the true push)
|
||||
|
||||
mv.visitLabel(operationTrue);
|
||||
mv.visitInsn(Opcodes.ICONST_1); // Push true on the stack
|
||||
|
||||
mv.visitLabel(expressionEnd);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public interface IExpression {
|
||||
// typeCheck method
|
||||
TypeCheckResult typeCheck() throws Exception;
|
||||
|
||||
// visit method for code generation
|
||||
void codeGen(MethodVisitor mv) throws Exception;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Datatype.RefType;
|
||||
import jdk.jshell.spi.ExecutionControl;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public class InstVarExpression implements IExpression{
|
||||
|
||||
//TODO: We have to decide upon more parameters and where they come from, for
|
||||
// example here we need the index of the field, the class reference and the field name
|
||||
private RefType classRef;
|
||||
private String fieldName;
|
||||
|
||||
/* public InstVarExpression(RefType classRef, String fieldName){
|
||||
this.classRef = classRef;
|
||||
this.fieldName = fieldName;
|
||||
}*/
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
throw new ExecutionControl.NotImplementedException("CodeGen not implemented for InstVarExpression");
|
||||
|
||||
//ALOAD the index of the var
|
||||
//GETFIELD the field
|
||||
//visitFieldInsn(Opcodes.GETFIELD, "class reference", "field name", type);
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Datatype.IDatatype;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class UnaryExpression extends AbstractType implements IExpression{
|
||||
public String operator;
|
||||
public IDatatype operand;
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
TypeCheckResult operandTypeCheckResult = operand.typeCheck();
|
||||
String operandType = operandTypeCheckResult.type;
|
||||
|
||||
switch (operator) {
|
||||
|
||||
case "!" :{
|
||||
if (Objects.equals(operandType, "bool")){
|
||||
result.type = "bool";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "-":
|
||||
case "+":
|
||||
if (Objects.equals(operandType, "int")){
|
||||
result.type = "int";
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
|
||||
operand.codeGen(mv);
|
||||
|
||||
switch (operator) {
|
||||
case "!":
|
||||
//XOR with 1 to get the negation
|
||||
mv.visitInsn(Opcodes.ICONST_1);
|
||||
mv.visitInsn(Opcodes.IXOR);
|
||||
break;
|
||||
case "-":
|
||||
mv.visitInsn(Opcodes.INEG);
|
||||
break;
|
||||
case "+":
|
||||
break;
|
||||
|
||||
default: throw new Exception("Unknown operator :" + operator);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class VarRefExpression implements IExpression{
|
||||
|
||||
//Parameters that are needed here
|
||||
private String varName;
|
||||
private Map<String, Integer> localVars;
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
throw new Exception("CodeGen not implemented for VarRefExpression");
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package abstractSyntaxTree;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Datatype.RefType;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class Program {
|
||||
public List<RefType> classes;
|
||||
|
||||
public HashMap<String, HashMap<String, String>> typeContext; // (class, (type, identifier))
|
||||
public HashMap<String, HashMap<String, HashMap<String, String>>> methodContext; // (class, (returntype, (identifier, parameter)))
|
||||
|
||||
public TypeCheckResult typeCheck() throws Exception{
|
||||
for(RefType oneClass : classes){
|
||||
HashMap<String, String> classVars = new HashMap<>();
|
||||
for (FieldDecl fielsDecl: oneClass.fieldDecls)
|
||||
classVars.put(fielsDecl.type, fielsDecl.identifier);
|
||||
oneClass.typeCheck();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void codeGen() throws Exception{
|
||||
for(RefType oneClass : classes){
|
||||
oneClass.codeGen();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class BlockStatement extends AbstractType implements IStatement{
|
||||
|
||||
//We will need a parameter which holds the symbol table
|
||||
HashMap<String, String > localVars;
|
||||
HashMap<String, String > typeIndentifierTable; // from program
|
||||
List<IStatement> statements;
|
||||
// do we need expression, statementexpression
|
||||
|
||||
public BlockStatement(List<IStatement> statements, HashMap<String, String> localVars, HashMap<String, String> typeIndentifierTable){
|
||||
|
||||
this.statements = statements;
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
if(statements.size() == 0){
|
||||
result.type = "void";
|
||||
}
|
||||
|
||||
TypeCheckResult blockType = null;
|
||||
for (IStatement statement : statements) {
|
||||
TypeCheckResult typeOfCurrentStatement = statement.typeCheck();
|
||||
|
||||
if (blockType == null) {
|
||||
blockType = typeOfCurrentStatement;
|
||||
} else if (!typeOfCurrentStatement.equals(blockType) && !blockType.equals("void")) {
|
||||
throw new IllegalArgumentException("different statement types");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
for (IStatement statement : statements) {
|
||||
statement.codeGen(mv); //TODO: I think we need to pass the symbol table here
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public class EmptyStatement extends AbstractType implements IStatement{
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = "void";
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
//An empty statement does not generate any code
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public interface IStatement {
|
||||
|
||||
|
||||
|
||||
TypeCheckResult typeCheck() throws Exception;
|
||||
|
||||
void codeGen(MethodVisitor mv) throws Exception;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class IfElseStatement extends AbstractType implements IStatement{
|
||||
IExpression condition;
|
||||
IStatement ifStatement;
|
||||
IStatement elseStatement;
|
||||
|
||||
public IfElseStatement(IExpression condition, IStatement ifStatement, IStatement elseStatement) {
|
||||
this.condition = condition;
|
||||
this.ifStatement = ifStatement;
|
||||
this.elseStatement = elseStatement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
TypeCheckResult conditionType = condition.typeCheck();
|
||||
|
||||
if (!conditionType.equals("bool")) {
|
||||
throw new IllegalArgumentException("should be boolean");
|
||||
}
|
||||
|
||||
TypeCheckResult ifStatementType = ifStatement.typeCheck();
|
||||
TypeCheckResult elseStatementType = elseStatement.typeCheck();
|
||||
|
||||
if (!ifStatementType.equals(elseStatementType)) {
|
||||
throw new IllegalArgumentException("if and else have different types");
|
||||
}
|
||||
|
||||
result.type = elseStatementType.type;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
|
||||
Label conditionFalse = new Label();
|
||||
Label statementEnd = new Label();
|
||||
|
||||
condition.codeGen(mv);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
|
||||
ifStatement.codeGen(mv); //If the condition is true, execute the ifBlock
|
||||
mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the if-else statement
|
||||
|
||||
mv.visitLabel(conditionFalse);
|
||||
elseStatement.codeGen(mv); //If the condition is false, execute the elseBlock
|
||||
|
||||
mv.visitLabel(statementEnd); //End of the if-else statement
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class IfStatement extends AbstractType implements IStatement{
|
||||
IExpression condition;
|
||||
|
||||
//Do we need a block statement here?
|
||||
IStatement ifStatement;
|
||||
|
||||
public IfStatement(IExpression condition, IStatement ifStatement) {
|
||||
this.condition = condition;
|
||||
this.ifStatement = ifStatement;
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
TypeCheckResult conditionType = condition.typeCheck();
|
||||
|
||||
if (!conditionType.equals("boolean")) {
|
||||
throw new IllegalArgumentException("should be boolean");
|
||||
}
|
||||
|
||||
TypeCheckResult ifStatementType = ifStatement.typeCheck();
|
||||
result.type = ifStatementType.type;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
|
||||
Label conditionFalse = new Label();
|
||||
|
||||
condition.codeGen(mv);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
|
||||
ifStatement.codeGen(mv);
|
||||
|
||||
mv.visitLabel(conditionFalse); // If the condition is false, the Statements in the ifBlock will not be executed
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class ReturnStatement extends AbstractType implements IStatement{
|
||||
IExpression expression;
|
||||
|
||||
public ReturnStatement(IExpression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
if (expression == null) {
|
||||
result.type = "void";
|
||||
} else {
|
||||
TypeCheckResult typedExpression = expression.typeCheck();
|
||||
result.type = typedExpression.type;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//TODO: We do not differentiate between primitive types and reference types
|
||||
// This is a problem at "BinaryExpression" and here because we need to know the type to return
|
||||
// At this point in time we can either return reference types or have an error message
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
|
||||
if (expression != null) {
|
||||
expression.codeGen(mv);
|
||||
//Get the Type of the expression
|
||||
String type = expression.typeCheck().type;
|
||||
|
||||
if (type.equals("int") || type.equals("bool") || type.equals("char")) {
|
||||
mv.visitInsn(Opcodes.IRETURN);
|
||||
} else {
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
|
||||
}
|
||||
} else {
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class WhileStatement extends AbstractType implements IStatement {
|
||||
IExpression condition;
|
||||
IStatement statement;
|
||||
|
||||
public WhileStatement(IExpression condition, IStatement statement) {
|
||||
this.condition = condition;
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
TypeCheckResult conditionType = condition.typeCheck();
|
||||
|
||||
if (!conditionType.equals("bool")) {
|
||||
throw new IllegalArgumentException("Expected boolean");
|
||||
}
|
||||
|
||||
TypeCheckResult statementType = statement.typeCheck();
|
||||
|
||||
result.type = statementType.type;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
Label conditionFalse = new Label();
|
||||
Label LoopStart = new Label();
|
||||
|
||||
mv.visitLabel(LoopStart);
|
||||
|
||||
condition.codeGen(mv);
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0)
|
||||
|
||||
statement.codeGen(mv);
|
||||
//TODO: If the block ends with a return statement, we might have to pop it from the stack
|
||||
// So the next iteration starts with a clean stack
|
||||
mv.visitJumpInsn(Opcodes.GOTO, LoopStart); // Jump to the start of the while loop
|
||||
|
||||
mv.visitLabel(conditionFalse);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Expression.VarRefExpression;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class AssignStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||
public String operator;
|
||||
public IExpression left;
|
||||
public IExpression right;
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckHelper helper = new TypeCheckHelper();
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
TypeCheckResult leftType = left.typeCheck();
|
||||
TypeCheckResult rightType = right.typeCheck();
|
||||
|
||||
String upperbound = helper.upperBound(leftType.type, rightType.type);
|
||||
if (Objects.equals(upperbound, leftType.type)) {
|
||||
result.type = leftType.type;
|
||||
}
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
left.CodeGen(mv);
|
||||
right.CodeGen(mv);
|
||||
|
||||
if (left instanceof VarRefExpression varRef) {
|
||||
//TODO: Implement the handling of a variable reference --> I need a list of local variables
|
||||
// for that to determine if the variable is a local or field variable
|
||||
} else if (left instanceof InstVarExpression instVar) {
|
||||
mv.visitInsn(Opcodes.DUP_X1);
|
||||
|
||||
// We now again need the owner (class reference), name (of the Field in the owner) and type of the field
|
||||
//mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.className, instVar.varName, instVar.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Datatype.RefType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MethodCallStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||
String methodName;
|
||||
List<IExpression> arguments;
|
||||
RefType classThatHasTheMethodIfNotThis;
|
||||
RefType thisClass;
|
||||
|
||||
public MethodCallStatementExpression(String methodName, List<IExpression> arguments) {
|
||||
this.methodName = methodName;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
RefType searchMethodHere;
|
||||
if(classThatHasTheMethodIfNotThis == null){
|
||||
searchMethodHere = thisClass;
|
||||
} else {
|
||||
searchMethodHere = classThatHasTheMethodIfNotThis;
|
||||
}
|
||||
|
||||
List<MethodDecl> methods = searchMethodHere.methodDecls;
|
||||
|
||||
if(!methods.contains(methodName)){
|
||||
throw new Exception("method not found");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
//Generate Bytecode for the receiver
|
||||
if(classThatHasTheMethodIfNotThis != null){
|
||||
classThatHasTheMethodIfNotThis.CodeGen(mv);
|
||||
} else {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
}
|
||||
|
||||
for (IExpression argument : arguments) {
|
||||
argument.CodeGen(mv);
|
||||
}
|
||||
|
||||
//We need the class reference and the return type of the method
|
||||
//mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, thisClass.name, methodName, return type);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public class NewStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void CodeGen(MethodVisitor mv) throws Exception {
|
||||
throw new Exception("CodeGen not implemented for NewStatementExpression");
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import java.util.List;
|
||||
|
||||
public class SuperStatementExpression extends MethodCallStatementExpression{
|
||||
public SuperStatementExpression(String methodName, List<IExpression> arguments) {
|
||||
super(methodName, arguments);
|
||||
}
|
||||
}
|
||||
BIN
jar/NichtHaskell.jar
Normal file
BIN
jar/NichtHaskell.jar
Normal file
Binary file not shown.
BIN
jar/NichtHaskellCompiler-jar-with-dependencies.jar
Normal file
BIN
jar/NichtHaskellCompiler-jar-with-dependencies.jar
Normal file
Binary file not shown.
67
pom.xml
Normal file
67
pom.xml
Normal file
@@ -0,0 +1,67 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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>Clippit.org</groupId>
|
||||
<artifactId>NichtHaskell</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<java.version>22</java.version>
|
||||
<maven.compiler.source>22</maven.compiler.source>
|
||||
<maven.compiler.target>22</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.7.1</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>Compiler</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<finalName>NichtHaskellCompiler</finalName>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ow2.asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
<version>9.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.antlr</groupId>
|
||||
<artifactId>antlr4-runtime</artifactId>
|
||||
<version>4.13.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
24
src/NichtHaskell1.iml
Normal file
24
src/NichtHaskell1.iml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/test/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test/resources" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.antlr:antlr4-runtime:4.13.1" level="project" />
|
||||
<orderEntry type="module" module-name="NichtHaskell" scope="TEST" />
|
||||
<orderEntry type="module-library" scope="TEST">
|
||||
<library name="JUnit4">
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.13.1/junit-4.13.1.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
</module>
|
||||
33
src/main/java/CodeGen/CodeGenHelper.java
Normal file
33
src/main/java/CodeGen/CodeGenHelper.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package CodeGen;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public class CodeGenHelper {
|
||||
|
||||
public static String getFieldDescriptor(String type) {
|
||||
switch (type) {
|
||||
case "int":
|
||||
return "I";
|
||||
case "boolean":
|
||||
return "Z";
|
||||
case "char":
|
||||
return "C";
|
||||
default:
|
||||
return "L" + type + ";";
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetLocalVarIndex(LinkedHashMap<String, String> localVars, String varToSearchFor) {
|
||||
int index = -1;
|
||||
int counter = 0;
|
||||
for (String key : localVars.keySet()) {
|
||||
if (key.equals(varToSearchFor)) {
|
||||
index = counter + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
}
|
||||
119
src/main/java/Compiler.java
Normal file
119
src/main/java/Compiler.java
Normal file
@@ -0,0 +1,119 @@
|
||||
import TypeCheck.TypeCheckException;
|
||||
import abstractSyntaxTree.Program;
|
||||
import astGenerator.ASTGenerator;
|
||||
import gen.DecafLexer;
|
||||
import gen.DecafParser;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.CharStreams;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.tree.ParseTree;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
public class Compiler {
|
||||
|
||||
public static void main(String[] args) throws Exception{
|
||||
|
||||
|
||||
if (args.length < 1) {
|
||||
System.out.println("Usage: java -jar Compiler.jar <file_path> [--suppress-details]");
|
||||
return;
|
||||
}
|
||||
|
||||
String filePath = args[0];
|
||||
|
||||
boolean suppressDetails = false;
|
||||
|
||||
if (args.length > 1 && args[1].equals("--suppress-details")) {
|
||||
suppressDetails = true;
|
||||
}
|
||||
|
||||
Path path = Paths.get(filePath);
|
||||
|
||||
if (!Files.exists(path)) {
|
||||
System.out.println("Your input file was not found: " + path);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!suppressDetails)
|
||||
System.out.println("Processing input: " + path);
|
||||
|
||||
String content = Files.readString(path);
|
||||
|
||||
if(!suppressDetails)
|
||||
System.out.println("The content of your input file is: \n" + content);
|
||||
|
||||
CharStream codeCharStream = CharStreams.fromString(content);
|
||||
DecafLexer lexer = new DecafLexer(codeCharStream);
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
|
||||
tokens.fill();
|
||||
|
||||
if(!suppressDetails) {
|
||||
|
||||
List<Token> tokenList = tokens.getTokens();
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (Token token : tokenList) {
|
||||
stringBuilder.append(token.getText()).append(" ");
|
||||
}
|
||||
String readableTokens = stringBuilder.toString().trim();
|
||||
|
||||
System.out.println("The tokens of your input are: \n" + readableTokens + "\n");
|
||||
}
|
||||
|
||||
|
||||
DecafParser parser = new DecafParser(tokens);
|
||||
|
||||
ParseTree tree = parser.program();
|
||||
|
||||
ASTGenerator generator = new ASTGenerator();
|
||||
Program abstractSyntaxTree =(Program) generator.visit(tree);
|
||||
|
||||
|
||||
|
||||
if(!suppressDetails) {
|
||||
System.out.println("Parsed " + abstractSyntaxTree.classes.size() + " classes: ");
|
||||
abstractSyntaxTree.classes.forEach(refType -> {
|
||||
System.out.println("\t" + refType.name);
|
||||
});
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
try {
|
||||
abstractSyntaxTree.typeCheck();
|
||||
}catch(TypeCheckException e){
|
||||
System.out.println("A TypeCheck error was found in you input. Your input was not compiled.");
|
||||
System.out.println(e);
|
||||
return;
|
||||
}catch (Exception e){
|
||||
System.out.println("A unexpected error occurred in TypeCheck.");
|
||||
System.out.println(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!suppressDetails)
|
||||
System.out.println("No TypeCheck errors found.");
|
||||
|
||||
abstractSyntaxTree.codeGen();//todo remove
|
||||
|
||||
try {
|
||||
abstractSyntaxTree.codeGen();
|
||||
}catch (Exception e){
|
||||
System.out.println("A error occurred during code generation. Your input was not compiled.");
|
||||
System.out.println(e);
|
||||
return;
|
||||
}
|
||||
|
||||
File outputJarFile = new File("output.jar");
|
||||
if (outputJarFile.exists())
|
||||
outputJarFile.delete();
|
||||
|
||||
System.out.println("Your input was compiled. You can find the output in your current working directory.");
|
||||
}
|
||||
}
|
||||
@@ -3,32 +3,33 @@ grammar Decaf;
|
||||
program: classdecl+;
|
||||
|
||||
//class identifier{...}
|
||||
classdecl: AccessModifierPublic? 'class' Identifier OpenCurlyBracket (constuctorDecl|fieldDecl|methodDecl)*(MainMethodDecl block)? ClosedCurlyBracket;
|
||||
constuctorDecl: AccessModifierPublic? Identifier OpenRoundBracket parameterList? ClosedRoundBracket block; //Method without
|
||||
classdecl: AccessModifierPublic? 'class' Identifier OpenCurlyBracket (constuctorDecl|localVarDecl|methodDecl)*(MainMethodDecl block)? ClosedCurlyBracket;
|
||||
constuctorDecl: AccessModifierPublic? Identifier OpenRoundBracket parameterList? ClosedRoundBracket block;
|
||||
|
||||
//Method and FieldVar
|
||||
methodDecl: AccessModifierPublic? (type | Void) Identifier OpenRoundBracket parameterList? ClosedRoundBracket block;
|
||||
fieldDecl: AccessModifierPublic? type Identifier Semicolon;
|
||||
|
||||
//Parameters
|
||||
parameterList: parameter(Comma parameter)*;
|
||||
parameter: type Identifier;
|
||||
|
||||
argumentList: expression? | expression (Comma expression)+;
|
||||
//property, object.a, 3+1, a = 3
|
||||
expression: subExpression | binaryExpr;
|
||||
//subExpression to dissolve left-recusion
|
||||
subExpression: This | assignableExpr | stmtExpr | OpenRoundBracket subExpression ClosedRoundBracket;
|
||||
assignableExpr: Identifier | instVar;
|
||||
instVar: subReceiver? receivingMethod* Identifier;
|
||||
|
||||
//.trim().toLength().toLowerCase().count ...
|
||||
methodCall: receiver? receivingMethod* Identifier OpenRoundBracket argumentList ClosedRoundBracket;
|
||||
argumentList: expression? | expression (Comma expression)+;
|
||||
|
||||
statement: returnStmt Semicolon | localVarDecl | block | whileStmt | ifElseStmt | print | stmtExpr Semicolon | emptyStatement;
|
||||
|
||||
stmtExpr: assign | newDecl | methodCall;
|
||||
|
||||
assignableExpr: Identifier | instVar;
|
||||
|
||||
subReceiver: ((This | newDecl | Identifier) Dot);
|
||||
receiver: ((This | instVar | newDecl | Identifier) Dot);
|
||||
receivingMethod: Identifier OpenRoundBracket argumentList ClosedRoundBracket Dot;
|
||||
|
||||
instVar: subReceiver+ receivingMethod* Identifier;
|
||||
|
||||
binaryExpr: calcExpr | nonCalcExpr| value | Not binaryExpr;
|
||||
|
||||
@@ -38,15 +39,11 @@ dotSubExpr: IntValue | Identifier | instVar | methodCall | OpenRoundBracket calc
|
||||
nonCalcExpr: subExpression nonCalcOperator expression;
|
||||
nonCalcOperator: LogicalOpertor | ComparisonOperator;
|
||||
|
||||
//Statement but also expression
|
||||
//a = expr, new Object(), method(param1)
|
||||
stmtExpr: assign | newDecl | methodCall;
|
||||
BooleanValue: 'true'|'false';
|
||||
NullValue: 'null';
|
||||
|
||||
//Statements
|
||||
//int a, {...}, while(a > 10){...}, if(...){...} else if{...} else{...}
|
||||
statement: returnStmt Semicolon | localVarDecl Semicolon | block | whileStmt | ifElseStmt | stmtExpr Semicolon;
|
||||
returnStmt: Return (expression)?;
|
||||
localVarDecl: type Identifier (Assign expression)?;
|
||||
localVarDecl: AccessModifierPublic? type Identifier (Assign expression)? Semicolon;
|
||||
block: OpenCurlyBracket statement* ClosedCurlyBracket;
|
||||
whileStmt: While OpenRoundBracket expression ClosedRoundBracket statement;
|
||||
ifElseStmt: ifStmt elseStmt?;
|
||||
@@ -54,7 +51,9 @@ ifStmt: If OpenRoundBracket expression ClosedRoundBracket statement;
|
||||
elseStmt: Else statement;
|
||||
assign: assignableExpr Assign expression;
|
||||
newDecl: New Identifier OpenRoundBracket argumentList ClosedRoundBracket;
|
||||
|
||||
receiver: ((This | instVar | newDecl | Identifier) Dot);
|
||||
receivingMethod: Identifier OpenRoundBracket argumentList ClosedRoundBracket Dot;
|
||||
emptyStatement : Semicolon;
|
||||
|
||||
type: Int | Boolean | Char | Identifier;
|
||||
value: IntValue | BooleanValue | CharValue | NullValue;
|
||||
@@ -63,7 +62,14 @@ value: IntValue | BooleanValue | CharValue | NullValue;
|
||||
AccessModifierPublic : 'public' ;
|
||||
MainMethodDecl : 'public static void main(String[] args)';
|
||||
|
||||
//Print Statement print(VariableA);
|
||||
print: 'print' OpenRoundBracket Identifier ClosedRoundBracket Semicolon;
|
||||
|
||||
//Types
|
||||
Void : 'void';
|
||||
Int : 'int';
|
||||
Boolean : 'boolean';
|
||||
Char : 'char';
|
||||
|
||||
//Operators
|
||||
DotOperator : Multipilkation | Division | Modulo;
|
||||
@@ -105,24 +111,23 @@ Else : 'else';
|
||||
Return : 'return';
|
||||
New : 'new';
|
||||
|
||||
|
||||
|
||||
//Values
|
||||
IntValue : ('+'|'-')?[0-9]+;
|
||||
CharValue: '\''~[\r\n]?'\'';
|
||||
|
||||
|
||||
//Identifier
|
||||
fragment Alpabetic : [a-zA-Z];
|
||||
fragment Numeric: [0-9];
|
||||
fragment ValidIdentSymbols : Alpabetic|Numeric|'$'|'_';
|
||||
Identifier: Alpabetic ValidIdentSymbols*;
|
||||
|
||||
//Types
|
||||
Void : 'void';
|
||||
Int : 'int';
|
||||
Boolean : 'bool';
|
||||
Char : 'char';
|
||||
|
||||
//Values
|
||||
IntValue : ('+'|'-')*[0-9]+;
|
||||
CharValue: '\''~[\r\n]?'\'';
|
||||
BooleanValue: 'true'|'false';
|
||||
NullValue: 'null';
|
||||
|
||||
//Whitespace? Right into the trash it gooeesss
|
||||
WS : [ \t\r\n] -> skip;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
65
src/main/java/TestClass.java
Normal file
65
src/main/java/TestClass.java
Normal file
@@ -0,0 +1,65 @@
|
||||
class FourClasses {
|
||||
|
||||
public int notmain(int i) {
|
||||
Test t = new Test(i);
|
||||
Test2 t2 = new Test2(t.y);
|
||||
return t2.test.test3.getX();
|
||||
}
|
||||
|
||||
public static void main(String[] args){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Test {
|
||||
public int x;
|
||||
public int y;
|
||||
public Test3 test3;
|
||||
|
||||
public Test(int i) {
|
||||
this.x = i;
|
||||
this.y = 10;
|
||||
this.test3 = new Test3(i * 2);
|
||||
}
|
||||
|
||||
public Test3 getTest3() {
|
||||
return this.test3;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
public Test test;
|
||||
|
||||
public Test2(int i) {
|
||||
this.test = new Test(i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
public int x;
|
||||
|
||||
public int y;
|
||||
|
||||
public Test3(int i) {
|
||||
this.x = i;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return this.y;
|
||||
}
|
||||
|
||||
public void setY(int y) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
}
|
||||
7
src/main/java/TypeCheck/TypeCheckException.java
Normal file
7
src/main/java/TypeCheck/TypeCheckException.java
Normal file
@@ -0,0 +1,7 @@
|
||||
package TypeCheck;
|
||||
|
||||
public class TypeCheckException extends Exception {
|
||||
public TypeCheckException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
34
src/main/java/TypeCheck/TypeCheckHelper.java
Normal file
34
src/main/java/TypeCheck/TypeCheckHelper.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package TypeCheck;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class TypeCheckHelper {
|
||||
public static String upperBound(String type1, String type2) throws TypeCheckException{
|
||||
boolean type1Primitiv = Objects.equals(type1, "boolean") || Objects.equals(type1, "int") || Objects.equals(type1, "char");
|
||||
boolean type2Primitiv = Objects.equals(type2, "boolean") || Objects.equals(type2, "int") || Objects.equals(type2, "char");
|
||||
|
||||
String result = "class";
|
||||
if(type1Primitiv && type2Primitiv){
|
||||
if(Objects.equals(type1, type2)){
|
||||
result = type1;
|
||||
}else{
|
||||
throw new TypeCheckException("There is no upper bound between " + type1 + " and " + type2 + ".");
|
||||
}
|
||||
}else if(type1Primitiv ^ type2Primitiv){
|
||||
throw new TypeCheckException("There is no upper bound between " + type1 + " and " + type2 + ".");
|
||||
}else{
|
||||
if(Objects.equals(type1, type2))
|
||||
result = type1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static boolean typeExists(String type, List<String> customTypeslist) {
|
||||
|
||||
if(type.equals("int") || type.equals("boolean") || type.equals("char")){
|
||||
return true;
|
||||
}
|
||||
return customTypeslist.contains(type);
|
||||
}
|
||||
|
||||
}
|
||||
27
src/main/java/TypeCheck/TypeCheckResult.java
Normal file
27
src/main/java/TypeCheck/TypeCheckResult.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package TypeCheck;
|
||||
|
||||
import abstractSyntaxTree.StatementExpression.ReceivingMethod;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class TypeCheckResult {
|
||||
|
||||
public TypeCheckResult(){}
|
||||
public TypeCheckResult(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String type;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
TypeCheckResult typeCheckResult = (TypeCheckResult) o;
|
||||
boolean result = (Objects.equals(type, typeCheckResult.type)
|
||||
);
|
||||
System.out.println("In TypeCheckResult: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
67
src/main/java/abstractSyntaxTree/Class/FieldDecl.java
Normal file
67
src/main/java/abstractSyntaxTree/Class/FieldDecl.java
Normal file
@@ -0,0 +1,67 @@
|
||||
package abstractSyntaxTree.Class;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Node;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class FieldDecl extends AbstractType implements Node {
|
||||
|
||||
public String type;
|
||||
public String identifier;
|
||||
public IExpression expression;
|
||||
|
||||
public FieldDecl(String type, String identifier, IExpression expression){
|
||||
this.type = type;
|
||||
this.identifier = identifier;
|
||||
this.expression = expression;
|
||||
}
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
|
||||
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
List<String> typesList= new ArrayList<>();
|
||||
|
||||
for (HashMap<String, String> innerMap : typeContext.values()) {
|
||||
for (String value : innerMap.values()) {
|
||||
typesList.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
TypeCheckHelper.typeExists(this.type, typesList);
|
||||
result.type = this.type;
|
||||
setTypeCheckResult(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void codeGen(ClassWriter cw) {
|
||||
String descriptor = CodeGenHelper.getFieldDescriptor(type);
|
||||
FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, identifier, descriptor, null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
FieldDecl fieldDecl = (FieldDecl) o;
|
||||
boolean result = Objects.equals(type, fieldDecl.type)
|
||||
&& Objects.equals(identifier, fieldDecl.identifier)
|
||||
&& Objects.equals(expression, fieldDecl.expression);
|
||||
|
||||
System.out.println("In FieldDecl: " + result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
230
src/main/java/abstractSyntaxTree/Class/MethodDecl.java
Normal file
230
src/main/java/abstractSyntaxTree/Class/MethodDecl.java
Normal file
@@ -0,0 +1,230 @@
|
||||
package abstractSyntaxTree.Class;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MethodDecl implements Node {
|
||||
|
||||
//Class Name
|
||||
public String classThatContainsMethod;
|
||||
|
||||
//Method Name
|
||||
public String name;
|
||||
public ParameterList parameters;
|
||||
public String returnType;
|
||||
public BlockStatement codeBlock;
|
||||
|
||||
public LinkedHashMap<String, String> localVars;
|
||||
|
||||
public MethodDecl(String classThatContainsMethod, String returnType, String name, ParameterList parameters, BlockStatement codeBlock){
|
||||
this.classThatContainsMethod = classThatContainsMethod;
|
||||
this.returnType = returnType;
|
||||
this.name = name;
|
||||
this.parameters = parameters;
|
||||
this.codeBlock = codeBlock;
|
||||
this.localVars = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
|
||||
List<Parameter> parametersList = parameters.parameterList;
|
||||
for(Parameter parameter : parametersList){
|
||||
localVars.put(parameter.identifier, parameter.type);
|
||||
}
|
||||
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
codeBlock.thisClass = classThatContainsMethod;
|
||||
String codeBlockType = codeBlock.typeCheck(methodContext, typeContext, localVars).type;
|
||||
if(Objects.equals(this.name, classThatContainsMethod))
|
||||
codeBlockType = null;
|
||||
|
||||
if(!Objects.equals(this.returnType, codeBlockType))
|
||||
throw new TypeCheckException("Method returns " + codeBlockType + ", but should return " + this.returnType + ". ");
|
||||
|
||||
result.type = codeBlock.returnType;
|
||||
return result;
|
||||
}
|
||||
|
||||
//Need to get the returnType of the method if it is an object
|
||||
// methodContext (class, (identifier, (returnType, parameter)))
|
||||
// typeContext (class, (identifier, type))
|
||||
public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, List<FieldDecl> fieldDecls) throws Exception {
|
||||
|
||||
localVars.put("this", classThatContainsMethod);
|
||||
for (Parameter param : parameters.parameterList) {
|
||||
localVars.put(param.identifier, param.type);
|
||||
}
|
||||
|
||||
// check if the method is a constructor
|
||||
if (classThatContainsMethod.equals(name) && returnType == null) {
|
||||
String descriptor = getMethodDescriptor(methodContext, typeContext);
|
||||
|
||||
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", descriptor, null, null);
|
||||
|
||||
//Call the superclass constructor
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||
|
||||
HashMap<String, String> classFields = typeContext.get(classThatContainsMethod);
|
||||
|
||||
//Set the fields of the class
|
||||
boolean fieldFound = false;
|
||||
for (Map.Entry<String, String> entry : classFields.entrySet()) {
|
||||
String fieldName = entry.getKey();
|
||||
for (FieldDecl field : fieldDecls) {
|
||||
if (field.identifier.equals(fieldName)) {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
if (field.expression != null) {
|
||||
field.expression.codeGen(mv, localVars, typeContext, methodContext);
|
||||
} else {
|
||||
// If the field is not initialized, we need to load a default value onto the stack
|
||||
switch (field.type) {
|
||||
case "int", "boolean", "char" -> mv.visitInsn(Opcodes.ICONST_0);
|
||||
default -> mv.visitInsn(Opcodes.ACONST_NULL);
|
||||
}
|
||||
}
|
||||
descriptor = CodeGenHelper.getFieldDescriptor(field.type);
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, classThatContainsMethod, fieldName, descriptor);
|
||||
fieldFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fieldFound){
|
||||
throw new Exception("Field " + fieldName + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
//Load the parameters onto the stack
|
||||
int localVarIndex = 1;
|
||||
for (Parameter param : parameters.parameterList) {
|
||||
String paramType = param.type;
|
||||
switch(paramType) {
|
||||
case "int", "boolean", "char" -> {
|
||||
mv.visitVarInsn(Opcodes.ILOAD, localVarIndex);
|
||||
mv.visitVarInsn(Opcodes.ISTORE, localVarIndex);
|
||||
}
|
||||
default -> {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, localVarIndex);
|
||||
mv.visitVarInsn(Opcodes.ASTORE, localVarIndex);
|
||||
}
|
||||
}
|
||||
localVarIndex++;
|
||||
}
|
||||
|
||||
mv.visitCode();
|
||||
codeBlock.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
|
||||
//automatically computed max stack and max locals
|
||||
mv.visitMaxs(0, 0);
|
||||
|
||||
} else if (name.equals("main")) {
|
||||
int access = Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC;
|
||||
|
||||
MethodVisitor mv = cw.visitMethod(access, name, "([Ljava/lang/String;)V", null, null);
|
||||
|
||||
mv.visitCode();
|
||||
codeBlock.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
|
||||
} else {
|
||||
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, name, getMethodDescriptor(methodContext, typeContext), null, null);
|
||||
|
||||
mv.visitCode();
|
||||
codeBlock.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
// We have to check the return type to get the return opcode
|
||||
// For methods which return an actual value, the return opcode is created in the method body to ensure the
|
||||
// correct return value is on the stack
|
||||
if (returnType.equals("void")) mv.visitInsn(Opcodes.RETURN);
|
||||
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private String getMethodDescriptor(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) {
|
||||
// get the method descriptor
|
||||
StringBuilder descriptor = new StringBuilder("(");
|
||||
|
||||
// Iterate over the parameters and add them to the descriptor
|
||||
for (Parameter param : parameters.parameterList) {
|
||||
switch (param.type) {
|
||||
case "int" -> descriptor.append("I");
|
||||
case "boolean" -> descriptor.append("Z");
|
||||
case "char" -> descriptor.append("C");
|
||||
case "void" -> descriptor.append("V");
|
||||
default -> {
|
||||
// object
|
||||
if (param.type != null) {
|
||||
String paramType = param.type;
|
||||
// If it is a class reference replace the "." with "/" and return it
|
||||
HashMap<String, String> classTypes = typeContext.get(classThatContainsMethod);
|
||||
if (classTypes != null) {
|
||||
if (classTypes.containsKey(paramType)) {
|
||||
paramType = classTypes.get(paramType);
|
||||
paramType.replaceAll("\\.", "/");
|
||||
}
|
||||
}
|
||||
descriptor.append("L").append(paramType).append(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
descriptor.append(")");
|
||||
|
||||
// Get the return type
|
||||
// If the return type is null, it is a constructor, and we need to append V
|
||||
if (returnType == null) {
|
||||
descriptor.append("V");
|
||||
} else {
|
||||
switch (returnType) {
|
||||
case "int" -> descriptor.append("I");
|
||||
case "boolean" -> descriptor.append("Z");
|
||||
case "char" -> descriptor.append("C");
|
||||
case "void" -> descriptor.append("V");
|
||||
default -> {
|
||||
// object
|
||||
// methodContext (class, (returnType, (identifier, parameter)))
|
||||
HashMap<String, HashMap<String, ParameterList>> classMethods = methodContext.get(classThatContainsMethod);
|
||||
HashMap<String, ParameterList> methodDetails = classMethods.get(name);
|
||||
|
||||
String fullReturnType = null;
|
||||
for (Map.Entry<String, ParameterList> entry : methodDetails.entrySet()) {
|
||||
fullReturnType = entry.getKey();
|
||||
}
|
||||
// If it is a class reference replace the "." with "/" and return it
|
||||
if (returnType.contains(".")) fullReturnType = fullReturnType.replaceAll("\\.", "/");
|
||||
|
||||
if (fullReturnType != null) descriptor.append("L").append(fullReturnType).append(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
return descriptor.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MethodDecl methodDecl = (MethodDecl) o;
|
||||
boolean result = (Objects.equals(name, methodDecl.name)
|
||||
&& Objects.equals(parameters, methodDecl.parameters)
|
||||
&& Objects.equals(returnType, methodDecl.returnType)
|
||||
&& Objects.equals(codeBlock, methodDecl.codeBlock));
|
||||
System.out.println("In MethodDecl: " + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
123
src/main/java/abstractSyntaxTree/Class/RefType.java
Normal file
123
src/main/java/abstractSyntaxTree/Class/RefType.java
Normal file
@@ -0,0 +1,123 @@
|
||||
package abstractSyntaxTree.Class;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Statement.BlockStatement;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class RefType extends AbstractType implements Node {
|
||||
|
||||
|
||||
public String name; // Class Name
|
||||
public List<FieldDecl> fieldDecls;
|
||||
public List<MethodDecl> methodDecls;
|
||||
public boolean hasMain;
|
||||
|
||||
public RefType(String name,
|
||||
List<FieldDecl> fieldDecls,
|
||||
List<MethodDecl> methodDecls,
|
||||
boolean hasMain
|
||||
){
|
||||
this.name = name;
|
||||
this.fieldDecls = fieldDecls;
|
||||
this.methodDecls = methodDecls;
|
||||
this.hasMain = hasMain;
|
||||
|
||||
}
|
||||
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext,
|
||||
HashMap<String, HashMap<String, String>> typeContext) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
// check if field with the same identifier is defined more than once
|
||||
List<String> discoveredFieldIdentifiers = new ArrayList<>();
|
||||
for (FieldDecl fieldDecl : fieldDecls) {
|
||||
if(discoveredFieldIdentifiers.contains(fieldDecl.identifier)){
|
||||
throw new TypeCheckException("A field with the identifier " + fieldDecl.identifier + " was defined more than once in the class " + this.name + ". ");
|
||||
}
|
||||
discoveredFieldIdentifiers.add(fieldDecl.identifier);
|
||||
}
|
||||
|
||||
// typecheck each field
|
||||
for (FieldDecl fieldDecl : fieldDecls) {
|
||||
fieldDecl.typeCheck(typeContext);
|
||||
}
|
||||
|
||||
|
||||
// check if any methods have the same name and return type (overloaded methods are not allowed here)
|
||||
HashMap<String, String> discoveredMethods = new HashMap<>(); // returntype, identifier
|
||||
for (MethodDecl methodDecl : methodDecls) {
|
||||
|
||||
if (discoveredMethods.containsKey(methodDecl.returnType)) {
|
||||
if(discoveredMethods.get(methodDecl.returnType).equals(methodDecl.name)){
|
||||
throw new TypeCheckException("A method with the name " + methodDecl.name + " and return type " + methodDecl.returnType + " was defined more than once in the same class.");
|
||||
}
|
||||
}
|
||||
discoveredMethods.put(methodDecl.returnType, methodDecl.name);
|
||||
}
|
||||
|
||||
// type check each method
|
||||
for (MethodDecl methodDecl : methodDecls) {
|
||||
methodDecl.typeCheck(methodContext, typeContext);
|
||||
}
|
||||
|
||||
result.type = this.name;
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Method for code generation which iterates over all the field declarations
|
||||
// and method declarations and calls their CodeGen methods
|
||||
|
||||
public void codeGen(ClassWriter cw, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext) throws Exception {
|
||||
|
||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, name, null,
|
||||
"java/lang/Object", null);
|
||||
|
||||
for (FieldDecl field : fieldDecls) {
|
||||
field.codeGen(cw);
|
||||
}
|
||||
|
||||
boolean hasCustomConstructor = false;
|
||||
for (MethodDecl method : methodDecls) {
|
||||
if (method.name.equals(name) && method.returnType == null) {
|
||||
hasCustomConstructor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasCustomConstructor) {
|
||||
MethodDecl standardConstructor = new MethodDecl(name, null, name, new ParameterList(new ArrayList<>()), new BlockStatement(new ArrayList<>(), "void"));
|
||||
standardConstructor.codeGen(cw, methodContext, typeContext, fieldDecls);
|
||||
}
|
||||
|
||||
for (MethodDecl method : methodDecls) {
|
||||
method.codeGen(cw, methodContext, typeContext, fieldDecls);
|
||||
}
|
||||
cw.visitEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
RefType refType = (RefType) o;
|
||||
boolean result = ( Objects.equals(name, refType.name)
|
||||
&& Objects.equals(fieldDecls, refType.fieldDecls)
|
||||
&& Objects.equals(methodDecls, refType.methodDecls)
|
||||
&& Objects.equals(hasMain, refType.hasMain));
|
||||
System.out.println("In RefType: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,13 +4,25 @@ import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class BoolDatatype extends AbstractType implements IDatatype{
|
||||
boolean value;
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BoolDatatype boolDatatype = (BoolDatatype) o;
|
||||
boolean result = Objects.equals(value, boolDatatype.value);
|
||||
System.out.println("In BoolDataType: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
result.type = "bool";
|
||||
result.type = "boolean";
|
||||
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
@@ -24,4 +36,11 @@ public class BoolDatatype extends AbstractType implements IDatatype{
|
||||
mv.visitInsn(Opcodes.ICONST_0); // 0 for false
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
48
src/main/java/abstractSyntaxTree/Datatype/CharDatatype.java
Normal file
48
src/main/java/abstractSyntaxTree/Datatype/CharDatatype.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package abstractSyntaxTree.Datatype;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class CharDatatype extends AbstractType implements IDatatype{
|
||||
char value;
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
result.type = "char";
|
||||
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
if (value <= 5) {
|
||||
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||
} else if (value <= Byte.MAX_VALUE) {
|
||||
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||
} else {
|
||||
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CharDatatype charDatatype = (CharDatatype) o;
|
||||
boolean result = Objects.equals(value, charDatatype.value);
|
||||
System.out.println("In CharDataType: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
13
src/main/java/abstractSyntaxTree/Datatype/IDatatype.java
Normal file
13
src/main/java/abstractSyntaxTree/Datatype/IDatatype.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package abstractSyntaxTree.Datatype;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
public interface IDatatype {
|
||||
TypeCheckResult typeCheck() throws TypeCheckException;
|
||||
|
||||
void codeGen(MethodVisitor mv) throws Exception;
|
||||
|
||||
TypeCheckResult getTypeCheckResult();
|
||||
}
|
||||
@@ -5,10 +5,12 @@ import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class IntDatatype extends AbstractType implements IDatatype{
|
||||
int value;
|
||||
@Override
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
public TypeCheckResult typeCheck() {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
result.type = "int";
|
||||
@@ -17,13 +19,8 @@ public class IntDatatype extends AbstractType implements IDatatype{
|
||||
return result;
|
||||
}
|
||||
|
||||
// visit method for code generation
|
||||
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv) throws Exception {
|
||||
|
||||
//Example of using BIPUSH and SIPUSH for optimizing bytecode size
|
||||
if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
|
||||
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||
else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
|
||||
@@ -31,4 +28,20 @@ public class IntDatatype extends AbstractType implements IDatatype{
|
||||
else
|
||||
mv.visitLdcInsn(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
IntDatatype intDatatype = (IntDatatype) o;
|
||||
boolean result = (Objects.equals(value, intDatatype.value));
|
||||
System.out.println("In IntDataType: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BinaryExpression extends AbstractType implements IExpression{
|
||||
|
||||
public String operator;
|
||||
public IExpression left;
|
||||
public IExpression right;
|
||||
public String thisClass;
|
||||
|
||||
public BinaryExpression(String operator, IExpression left, IExpression right) {
|
||||
this.operator = operator;
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
if(left instanceof LocalVarIdentifier localVarIdentifier)
|
||||
localVarIdentifier.thisClass = this.thisClass;
|
||||
if(right instanceof LocalVarIdentifier localVarIdentifier)
|
||||
localVarIdentifier.thisClass = this.thisClass;
|
||||
TypeCheckResult leftType = left.typeCheck(methodContext, typeContext, localVars);
|
||||
TypeCheckResult rightType = right.typeCheck(methodContext, typeContext, localVars);
|
||||
|
||||
switch (operator) {
|
||||
|
||||
case "&&":
|
||||
case "||" :{
|
||||
if (Objects.equals(TypeCheckHelper.upperBound(leftType.type, rightType.type), "boolean")){
|
||||
result.type = "boolean";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "==":
|
||||
case "<":
|
||||
case ">":
|
||||
case "<=":
|
||||
case ">=":
|
||||
case "!=":
|
||||
TypeCheckHelper.upperBound(leftType.type, rightType.type);
|
||||
result.type = "boolean";
|
||||
break;
|
||||
|
||||
case "-":
|
||||
case "+":
|
||||
case "*":
|
||||
case "/":
|
||||
if (Objects.equals(TypeCheckHelper.upperBound(leftType.type, rightType.type), "int")){
|
||||
result.type = "int";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
// Label for the jump instruction
|
||||
Label operationFalse = new Label(); //Operation is false
|
||||
Label operationTrue = new Label(); //Operation is true
|
||||
// Labels are placed at the end of this method
|
||||
Label expressionEnd = new Label(); //End of the whole expression
|
||||
|
||||
// Bytecode for the binary operation
|
||||
if (operator.equals("+") || operator.equals("-") || operator.equals("*") || operator.equals("/")) {
|
||||
switch (operator) {
|
||||
case "+" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitInsn(Opcodes.IADD);
|
||||
}
|
||||
case "-" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitInsn(Opcodes.ISUB);
|
||||
}
|
||||
case "*" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitInsn(Opcodes.IMUL);
|
||||
}
|
||||
case "/" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitInsn(Opcodes.IDIV);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (operator) {
|
||||
case "&&" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
|
||||
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
|
||||
}
|
||||
case "||" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
|
||||
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
|
||||
}
|
||||
case "==" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
switch (left.getTypeCheckResult().type) {
|
||||
case "int", "boolean", "char" -> mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue);
|
||||
|
||||
default -> mv.visitJumpInsn(Opcodes.IF_ACMPEQ, operationTrue);
|
||||
}
|
||||
}
|
||||
case "<" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
|
||||
}
|
||||
case ">" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
|
||||
}
|
||||
case "<=" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
|
||||
}
|
||||
case ">=" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
|
||||
}
|
||||
case "!=" -> {
|
||||
left.codeGen(mv, localVars, typeContext, methodContext);
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
|
||||
}
|
||||
default -> throw new TypeCheckException("The operator " + operator + " is not known.");
|
||||
}
|
||||
mv.visitLabel(operationFalse);
|
||||
mv.visitInsn(Opcodes.ICONST_0); // Push false on the stack
|
||||
mv.visitJumpInsn(Opcodes.GOTO, expressionEnd); // Jump to the end of the expression (skip the true push)
|
||||
|
||||
mv.visitLabel(operationTrue);
|
||||
mv.visitInsn(Opcodes.ICONST_1); // Push true on the stack
|
||||
|
||||
mv.visitLabel(expressionEnd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BinaryExpression binaryExpression = (BinaryExpression) o;
|
||||
boolean result = (Objects.equals(operator, binaryExpression.operator)
|
||||
&& Objects.equals(left, binaryExpression.left)
|
||||
&& Objects.equals(right, binaryExpression.right)
|
||||
&& Objects.equals(left.getTypeCheckResult(), binaryExpression.left.getTypeCheckResult())
|
||||
);
|
||||
System.out.println("In BinaryExpression: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BooleanConstantExpression extends AbstractType implements IExpression{
|
||||
public boolean value;
|
||||
|
||||
public BooleanConstantExpression(boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = "boolean";
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
if (value){
|
||||
mv.visitInsn(Opcodes.ICONST_1);
|
||||
} else {
|
||||
mv.visitInsn(Opcodes.ICONST_0);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BooleanConstantExpression boolDatatype = (BooleanConstantExpression) o;
|
||||
boolean result = Objects.equals(value, boolDatatype.value);
|
||||
System.out.println("In BooleanConstantExpression: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class CharConstantExpression extends AbstractType implements IExpression{
|
||||
public char value;
|
||||
|
||||
public CharConstantExpression(char value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = "char";
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
if (value <= 5) {
|
||||
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||
} else if (value <= Byte.MAX_VALUE) {
|
||||
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||
} else {
|
||||
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CharConstantExpression boolDatatype = (CharConstantExpression) o;
|
||||
boolean result = Objects.equals(value, boolDatatype.value);
|
||||
System.out.println("In CharConstantExpression: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
17
src/main/java/abstractSyntaxTree/Expression/IExpression.java
Normal file
17
src/main/java/abstractSyntaxTree/Expression/IExpression.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public interface IExpression extends Node {
|
||||
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException;
|
||||
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception;
|
||||
|
||||
TypeCheckResult getTypeCheckResult();
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.StatementExpression.ReceivingMethod;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class InstVarExpression extends AbstractType implements IExpression {
|
||||
|
||||
public String thisClass;
|
||||
public List<SubReceiver> receivers;
|
||||
public List<ReceivingMethod> receivingMethods;
|
||||
public String fieldName;
|
||||
|
||||
public InstVarExpression(List<SubReceiver> receivers, List<ReceivingMethod> receivingMethods, String fieldName) {
|
||||
this.receivers = receivers;
|
||||
this.receivingMethods = receivingMethods;
|
||||
this.fieldName = fieldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
String typeOfSubreceiver = "";
|
||||
if (receivers.get(0).identifier != null) {
|
||||
String subreceiver = receivers.get(0).identifier;
|
||||
typeOfSubreceiver = localVars.get(subreceiver);
|
||||
if (typeOfSubreceiver == null)
|
||||
typeContext.get(thisClass).get(subreceiver);
|
||||
|
||||
if (receivers.size() > 1) {
|
||||
for (int i = 1; i < receivers.size(); i++) {
|
||||
subreceiver = receivers.get(i).identifier;
|
||||
typeOfSubreceiver = typeContext.get(typeOfSubreceiver).get(subreceiver);
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
typeOfSubreceiver = thisClass;
|
||||
}
|
||||
|
||||
String varType = typeContext.get(typeOfSubreceiver).get(fieldName);
|
||||
if (varType == null) {
|
||||
throw new TypeCheckException("Field " + fieldName + " was not found in class " + thisClass + ".");
|
||||
}
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = varType;
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
// typeContext: (ClassName, (FieldName, FieldType))
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
// Load "this" onto the stack
|
||||
String typeOfReciever = "";
|
||||
String descriptor = "";
|
||||
String classOfField = "";
|
||||
|
||||
// Determine if the reference is this or not
|
||||
if (this.receivers.get(0).identifier != null) {
|
||||
|
||||
for (int i = 0; i < receivers.size(); i++) {
|
||||
|
||||
if (i == 0) {
|
||||
// Load the local variable onto the stack
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, this.receivers.get(i).identifier);
|
||||
|
||||
if (index == -1) {
|
||||
if (typeContext.get(thisClass).get(this.receivers.get(i).identifier) != null) {
|
||||
|
||||
classOfField = typeOfReciever;
|
||||
|
||||
typeOfReciever = typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier);
|
||||
|
||||
descriptor = getFieldDescriptor(typeOfReciever);
|
||||
|
||||
// Load the variable onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, receivers.get(i).identifier, descriptor);
|
||||
continue;
|
||||
|
||||
} else {
|
||||
throw new Exception("Variable " + this.receivers.get(i).identifier + " not found");
|
||||
}
|
||||
|
||||
} else {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||
|
||||
|
||||
// Get the class of the receiver
|
||||
typeOfReciever = localVars.get(this.receivers.get(i).identifier);
|
||||
}
|
||||
}
|
||||
// Not the first receiver
|
||||
else {
|
||||
|
||||
// Load the local variable onto the stack
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, this.receivers.get(i).identifier);
|
||||
|
||||
if (index == -1) {
|
||||
if (typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier) != null) {
|
||||
|
||||
classOfField = typeOfReciever;
|
||||
|
||||
typeOfReciever = typeContext.get(typeOfReciever).get(this.receivers.get(i).identifier);
|
||||
|
||||
descriptor = getFieldDescriptor(typeOfReciever);
|
||||
|
||||
// Load the variable onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, receivers.get(i).identifier, descriptor);
|
||||
continue;
|
||||
|
||||
} else {
|
||||
throw new Exception("Variable " + this.receivers.get(i).identifier + " not found");
|
||||
}
|
||||
} else {
|
||||
typeOfReciever = localVars.get(this.receivers.get(i).identifier);
|
||||
|
||||
descriptor = getFieldDescriptor(typeOfReciever);
|
||||
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfReciever, fieldName, descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Load the field in fieldName
|
||||
|
||||
// Load the local variable onto the stack
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, fieldName);
|
||||
|
||||
if (index == -1) {
|
||||
if (typeContext.get(typeOfReciever).get(fieldName) != null) {
|
||||
|
||||
classOfField = typeOfReciever;
|
||||
|
||||
typeOfReciever = typeContext.get(typeOfReciever).get(fieldName);
|
||||
|
||||
descriptor = getFieldDescriptor(typeOfReciever);
|
||||
|
||||
// Load the variable onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, classOfField, fieldName, descriptor);
|
||||
|
||||
} else {
|
||||
throw new Exception("Variable " + fieldName + " not found");
|
||||
}
|
||||
|
||||
} else {
|
||||
typeOfReciever = localVars.get(fieldName);
|
||||
|
||||
descriptor = getFieldDescriptor(typeOfReciever);
|
||||
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfReciever, fieldName, descriptor);
|
||||
}
|
||||
} else if (receivers.get(0).thisExpression) {
|
||||
// Load the local variable or instVar of this onto the stack
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, fieldName);
|
||||
|
||||
if (index == -1) {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
|
||||
} else {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||
}
|
||||
|
||||
String fieldType = typeContext.get(thisClass).get(fieldName);
|
||||
descriptor = getFieldDescriptor(fieldType);
|
||||
|
||||
//Load the field onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, fieldName, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
private String getFieldDescriptor(String fieldType) {
|
||||
StringBuilder descriptor = new StringBuilder();
|
||||
|
||||
|
||||
switch (fieldType) {
|
||||
case "int":
|
||||
descriptor.append("I");
|
||||
break;
|
||||
case "boolean":
|
||||
descriptor.append("Z");
|
||||
break;
|
||||
case "char":
|
||||
descriptor.append("C");
|
||||
break;
|
||||
default:
|
||||
String fullReturnType = fieldType;
|
||||
// If it is a class reference replace the "." with "/" and return it
|
||||
if (fieldType.contains(".")) fullReturnType = fullReturnType.replaceAll("\\.", "/");
|
||||
if (fullReturnType != null) descriptor.append("L").append(fullReturnType).append(";");
|
||||
break;
|
||||
}
|
||||
return descriptor.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
InstVarExpression instVarExpression = (InstVarExpression) o;
|
||||
boolean result = (Objects.equals(receivers, instVarExpression.receivers)
|
||||
&& Objects.equals(fieldName, instVarExpression.fieldName)
|
||||
&& Objects.equals(receivingMethods, instVarExpression.receivingMethods)
|
||||
&& Objects.equals(thisClass, instVarExpression.thisClass)
|
||||
);
|
||||
System.out.println("In InstVarExpression: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class IntConstantExpression extends AbstractType implements IExpression{
|
||||
public int value;
|
||||
|
||||
public IntConstantExpression(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = "int";
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
if (value >= -1 && value <= 5) {
|
||||
mv.visitInsn(Opcodes.ICONST_0 + value);
|
||||
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
|
||||
mv.visitIntInsn(Opcodes.BIPUSH, value);
|
||||
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
|
||||
mv.visitIntInsn(Opcodes.SIPUSH, value);
|
||||
} else {
|
||||
mv.visitLdcInsn(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
IntConstantExpression intConstantExpression = (IntConstantExpression) o;
|
||||
boolean result = (Objects.equals(value, intConstantExpression.value)
|
||||
);
|
||||
System.out.println("In intConstantExpression: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class LocalVarIdentifier extends AbstractType implements IExpression{
|
||||
|
||||
String identifier;
|
||||
public String thisClass;
|
||||
public LocalVarIdentifier(String identifier){
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
if (localVars.containsKey(identifier)) {
|
||||
result.type = localVars.get(identifier);
|
||||
} else {
|
||||
// check if instvar
|
||||
result.type = typeContext.get(thisClass).get(identifier);
|
||||
if(result.type != null){
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
throw new TypeCheckException("Local var " + identifier + " does not exist.");
|
||||
}
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
String type = null;
|
||||
|
||||
// if it's a local variable
|
||||
if (localVars.containsKey(identifier)) {
|
||||
type = localVars.get(identifier);
|
||||
// Find the index of the variable
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, identifier);
|
||||
|
||||
if (index == -1) {
|
||||
throw new Exception("Variable " + identifier + " not found");
|
||||
}
|
||||
|
||||
// Load the variable onto the stack
|
||||
switch (type) {
|
||||
case "int", "boolean", "char":
|
||||
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||
break;
|
||||
case "void":
|
||||
break;
|
||||
default:
|
||||
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||
break;
|
||||
}
|
||||
// If it's a field
|
||||
} else if (typeContext.get(thisClass).get(identifier) != null){
|
||||
type = typeContext.get(thisClass).get(identifier);
|
||||
|
||||
// Load "this" onto the stack
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
// Get the field from "this"
|
||||
String descriptor = CodeGenHelper.getFieldDescriptor(type);
|
||||
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, identifier, descriptor);
|
||||
} else
|
||||
throw new Exception("Variable " + identifier + " not found");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
LocalVarIdentifier localVarIdentifier = (LocalVarIdentifier) o;
|
||||
boolean result = (Objects.equals(identifier, localVarIdentifier.identifier)
|
||||
);
|
||||
System.out.println("In localVarIdentifier: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
36
src/main/java/abstractSyntaxTree/Expression/SubReceiver.java
Normal file
36
src/main/java/abstractSyntaxTree/Expression/SubReceiver.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class SubReceiver implements Node {
|
||||
public boolean thisExpression;
|
||||
public NewStatementExpression newStatementExpression;
|
||||
public String identifier;
|
||||
|
||||
public SubReceiver(boolean thisExpression) {
|
||||
this.thisExpression = thisExpression;
|
||||
}
|
||||
|
||||
public SubReceiver(NewStatementExpression newStatementExpression) {
|
||||
this.newStatementExpression = newStatementExpression;
|
||||
}
|
||||
|
||||
public SubReceiver(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
SubReceiver subReceiver = (SubReceiver) o;
|
||||
boolean result = (Objects.equals(thisExpression, subReceiver.thisExpression)
|
||||
);
|
||||
System.out.println("In SubReceiver: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package abstractSyntaxTree.Expression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class UnaryExpression extends AbstractType implements IExpression{
|
||||
public String operator;
|
||||
public IExpression operand;
|
||||
public UnaryExpression(String operator, IExpression operand){
|
||||
this.operator = operator;
|
||||
this.operand = operand;
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
TypeCheckResult operandTypeCheckResult = operand.typeCheck(methodContext, typeContext, localVars);
|
||||
String operandType = operandTypeCheckResult.type;
|
||||
|
||||
switch (operator) {
|
||||
|
||||
case "!" :{
|
||||
if (Objects.equals(operandType, "boolean")){
|
||||
result.type = "boolean";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "-":
|
||||
case "":
|
||||
case "+":{
|
||||
if (Objects.equals(operandType, "int")){
|
||||
result.type = "int";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
|
||||
operand.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
switch (operator) {
|
||||
case "!":
|
||||
//XOR with 1 to get the negation
|
||||
mv.visitInsn(Opcodes.ICONST_1);
|
||||
mv.visitInsn(Opcodes.IXOR);
|
||||
break;
|
||||
case "-":
|
||||
mv.visitInsn(Opcodes.INEG);
|
||||
break;
|
||||
case "+":
|
||||
break;
|
||||
|
||||
default: throw new Exception("Unknown operator :" + operator);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
UnaryExpression unaryExpression = (UnaryExpression) o;
|
||||
boolean result = (Objects.equals(operator, unaryExpression.operator)
|
||||
&& Objects.equals(operand, unaryExpression.operand)
|
||||
);
|
||||
System.out.println("In UnaryExpression: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
4
src/main/java/abstractSyntaxTree/Node.java
Normal file
4
src/main/java/abstractSyntaxTree/Node.java
Normal file
@@ -0,0 +1,4 @@
|
||||
package abstractSyntaxTree;
|
||||
|
||||
public interface Node {
|
||||
}
|
||||
29
src/main/java/abstractSyntaxTree/Parameter/Parameter.java
Normal file
29
src/main/java/abstractSyntaxTree/Parameter/Parameter.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package abstractSyntaxTree.Parameter;
|
||||
|
||||
import abstractSyntaxTree.Expression.UnaryExpression;
|
||||
import abstractSyntaxTree.Node;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Parameter implements Node {
|
||||
public String type;
|
||||
public String identifier;
|
||||
|
||||
public Parameter(String type, String identifier) {
|
||||
this.type = type;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Parameter parameter = (Parameter) o;
|
||||
boolean result = (Objects.equals(type, parameter.type)
|
||||
&& Objects.equals(identifier, parameter.identifier)
|
||||
);
|
||||
System.out.println("In Parameter: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package abstractSyntaxTree.Parameter;
|
||||
|
||||
import abstractSyntaxTree.Node;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ParameterList implements Node {
|
||||
public List<Parameter> parameterList;
|
||||
|
||||
public ParameterList(List<Parameter> parameterList) {
|
||||
this.parameterList = parameterList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ParameterList parameterListObj = (ParameterList) o;
|
||||
boolean result = (Objects.equals(parameterList, parameterListObj.parameterList)
|
||||
);
|
||||
System.out.println("In ParameterList: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
180
src/main/java/abstractSyntaxTree/Program.java
Normal file
180
src/main/java/abstractSyntaxTree/Program.java
Normal file
@@ -0,0 +1,180 @@
|
||||
package abstractSyntaxTree;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.*;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
public class Program implements Node {
|
||||
public List<RefType> classes;
|
||||
public HashMap<String, HashMap<String, String>> typeContext; // (class, (type, identifier))
|
||||
public HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext; // (class, (returntype, (identifier, parameter)))
|
||||
|
||||
public Program(List<RefType> classes){
|
||||
this.classes = classes;
|
||||
}
|
||||
|
||||
public TypeCheckResult typeCheckWithoutMain() throws TypeCheckException {
|
||||
this.typeContext = new HashMap<>();
|
||||
this.methodContext = new HashMap<>();
|
||||
|
||||
for(RefType oneClass : classes){
|
||||
|
||||
// build type context
|
||||
HashMap<String, String> classVars = new HashMap<>();
|
||||
for (FieldDecl fieldDecl: oneClass.fieldDecls){
|
||||
classVars.put(fieldDecl.identifier, fieldDecl.type);
|
||||
}
|
||||
typeContext.put(oneClass.name, classVars);
|
||||
|
||||
// build method context
|
||||
|
||||
HashMap<String, HashMap<String, ParameterList>> identifierAndMethod = new HashMap<>();
|
||||
for (MethodDecl methodDecl : oneClass.methodDecls){
|
||||
if(methodDecl.returnType == null) continue;
|
||||
HashMap<String, ParameterList> returnTypeAndParameter = new HashMap<>();
|
||||
returnTypeAndParameter.put(methodDecl.returnType, methodDecl.parameters);
|
||||
identifierAndMethod.put(methodDecl.name, returnTypeAndParameter);
|
||||
}
|
||||
methodContext.put(oneClass.name, identifierAndMethod);
|
||||
}
|
||||
|
||||
int mainCounter = 0;
|
||||
// check if main exists
|
||||
for(RefType oneClass : classes){
|
||||
if(oneClass.hasMain)
|
||||
mainCounter++;
|
||||
}
|
||||
if(mainCounter != 1) {
|
||||
//throw new TypeCheckException("There is not 1 Main method.");
|
||||
}
|
||||
|
||||
// typecheck each class
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
for(RefType oneClass : classes){
|
||||
oneClass.typeCheck(methodContext, typeContext);
|
||||
}
|
||||
result.type = "program";
|
||||
return result;
|
||||
}
|
||||
|
||||
public TypeCheckResult typeCheck() throws TypeCheckException {
|
||||
this.typeContext = new HashMap<>();
|
||||
this.methodContext = new HashMap<>();
|
||||
|
||||
for(RefType oneClass : classes){
|
||||
|
||||
// build type context
|
||||
HashMap<String, String> classVars = new HashMap<>();
|
||||
for (FieldDecl fieldDecl: oneClass.fieldDecls){
|
||||
classVars.put(fieldDecl.identifier, fieldDecl.type);
|
||||
}
|
||||
typeContext.put(oneClass.name, classVars);
|
||||
|
||||
// build method context
|
||||
HashMap<String, HashMap<String, ParameterList>> identifierAndMethod = new HashMap<>();
|
||||
for (MethodDecl methodDecl : oneClass.methodDecls){
|
||||
if(methodDecl.returnType == null) continue;
|
||||
HashMap<String, ParameterList> returnTypeAndParameter = new HashMap<>();
|
||||
returnTypeAndParameter.put(methodDecl.returnType, methodDecl.parameters);
|
||||
identifierAndMethod.put(methodDecl.name, returnTypeAndParameter);
|
||||
}
|
||||
methodContext.put(oneClass.name, identifierAndMethod);
|
||||
}
|
||||
|
||||
// check if main exists
|
||||
int mainCounter = 0;
|
||||
for(RefType oneClass : classes){
|
||||
if(oneClass.hasMain)
|
||||
mainCounter++;
|
||||
}
|
||||
if(mainCounter != 1)
|
||||
throw new TypeCheckException("There is not 1 Main method.");
|
||||
|
||||
// typecheck each class
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
for(RefType oneClass : classes){
|
||||
oneClass.typeCheck(methodContext, typeContext);
|
||||
}
|
||||
result.type = "program";
|
||||
return result;
|
||||
}
|
||||
|
||||
public void codeGen() throws Exception {
|
||||
// Store the names of the generated class files
|
||||
List<String> classFileNames = new ArrayList<>();
|
||||
|
||||
try {
|
||||
for (RefType oneClass : classes) {
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, oneClass.name, null, "java/lang/Object", null);
|
||||
|
||||
oneClass.codeGen(cw, methodContext, typeContext);
|
||||
|
||||
cw.visitEnd();
|
||||
byte[] bytecode = cw.toByteArray();
|
||||
|
||||
String classFileName = oneClass.name + ".class";
|
||||
classFileNames.add(classFileName);
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(classFileName)) {
|
||||
fos.write(bytecode);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Now create the JAR file
|
||||
try (FileOutputStream fos = new FileOutputStream("output.jar");
|
||||
JarOutputStream jos = new JarOutputStream(fos)) {
|
||||
|
||||
for (String classFileName : classFileNames) {
|
||||
addFileToJar(jos, classFileName);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void addFileToJar(JarOutputStream jos, String fileName) throws IOException {
|
||||
File file = new File(fileName);
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
JarEntry entry = new JarEntry(fileName);
|
||||
jos.putNextEntry(entry);
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = fis.read(buffer)) != -1) {
|
||||
jos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
jos.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Program program = (Program) o;
|
||||
System.out.println("In program: " + Objects.equals(classes, program.classes));
|
||||
return (Objects.equals(classes, program.classes));
|
||||
}
|
||||
}
|
||||
150
src/main/java/abstractSyntaxTree/Statement/BlockStatement.java
Normal file
150
src/main/java/abstractSyntaxTree/Statement/BlockStatement.java
Normal file
@@ -0,0 +1,150 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.StatementExpression.AssignStatementExpression;
|
||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BlockStatement extends AbstractType implements IStatement {
|
||||
HashMap<String, String> localVars;
|
||||
public String returnType;
|
||||
public List<IStatement> statements;
|
||||
public String thisClass;
|
||||
|
||||
public BlockStatement(List<IStatement> statements, String returnType) {
|
||||
this.statements = statements;
|
||||
this.returnType = returnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext,
|
||||
HashMap<String, HashMap<String, String>> typeContext,
|
||||
HashMap<String, String> localVars) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
this.localVars = localVars;
|
||||
if (statements.isEmpty()) {
|
||||
result.type = "void";
|
||||
}
|
||||
|
||||
for (IStatement statement : statements) {
|
||||
|
||||
if(statement instanceof IfStatement ifStatement){
|
||||
ifStatement.thisClass = this.thisClass;
|
||||
}
|
||||
if(statement instanceof IfElseStatement ifElseStatement){
|
||||
ifElseStatement.thisClass = this.thisClass;
|
||||
}
|
||||
if(statement instanceof WhileStatement whileStatement){
|
||||
whileStatement.thisClass = this.thisClass;
|
||||
}
|
||||
if(statement instanceof MethodCallStatementExpression methodCall){
|
||||
methodCall.thisClass = thisClass;
|
||||
}
|
||||
if(statement instanceof AssignStatementExpression assignStatementExpression){
|
||||
assignStatementExpression.thisClass = thisClass;
|
||||
}
|
||||
if(statement instanceof LocalVarDecl localVarDecl){
|
||||
localVarDecl.thisClass = thisClass;
|
||||
}
|
||||
if (statement instanceof PrintStatement printStatement) {
|
||||
printStatement.thisClass = thisClass;
|
||||
}
|
||||
if (statement instanceof ReturnStatement returnStatement) {
|
||||
returnStatement.thisClass = thisClass;
|
||||
}
|
||||
if (statement instanceof NewStatementExpression newStatementExpression) {
|
||||
newStatementExpression.thisClass = thisClass;
|
||||
}
|
||||
|
||||
TypeCheckResult typeOfCurrentStatement = statement.typeCheck(methodContext, typeContext, localVars);
|
||||
if(statement instanceof MethodCallStatementExpression methodCall){
|
||||
typeOfCurrentStatement.type = "void";
|
||||
}
|
||||
if(statement instanceof LocalVarDecl localVarDecl){
|
||||
localVars.put(localVarDecl.identifier, localVarDecl.type);
|
||||
}
|
||||
|
||||
if (typeOfCurrentStatement.type.contains(",")) {
|
||||
// else if has 2 returns, all code paths must return a value.
|
||||
String[] substrings = typeOfCurrentStatement.type.split(",");
|
||||
|
||||
String firstType = substrings[0];
|
||||
String secondType = substrings[1];
|
||||
|
||||
|
||||
if (!firstType.equals(this.returnType) || !firstType.equals(this.returnType)) {
|
||||
if (!firstType.equals("void") && this.returnType != null) {
|
||||
throw new TypeCheckException("The if-Path returns the wrong type.");
|
||||
}
|
||||
if (!secondType.equals("void") && this.returnType != null) {
|
||||
throw new TypeCheckException("The else-path returns the wrong type.");
|
||||
}
|
||||
boolean firstIsVoid = firstType.equals("void");
|
||||
|
||||
if (!firstIsVoid) {
|
||||
typeOfCurrentStatement.type = firstType;
|
||||
} else {
|
||||
typeOfCurrentStatement.type = secondType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(typeOfCurrentStatement.type.equals("void"))
|
||||
continue;
|
||||
|
||||
// set return of block if not known yet
|
||||
if(this.returnType == null|| this.returnType == "not")
|
||||
this.returnType = typeOfCurrentStatement.type;
|
||||
|
||||
if (!typeOfCurrentStatement.type.equals(this.returnType))
|
||||
throw new TypeCheckException("At least some statements of the block returns the wrong type or missing return statement.");
|
||||
}
|
||||
if(this.returnType == null)
|
||||
this.returnType = "void";
|
||||
|
||||
result.type = this.returnType;
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
// Create a new HashMap for the local variables of the block
|
||||
// It has every variable of the parent block
|
||||
// This Map is discarded at the end of the block
|
||||
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
|
||||
|
||||
for (IStatement statement : statements) {
|
||||
statement.codeGen(mv, blockLocalVars, typeContext, methodContext);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BlockStatement blockStatement = (BlockStatement) o;
|
||||
boolean result = Objects.equals(returnType, blockStatement.returnType)
|
||||
&& Objects.equals(statements, blockStatement.statements
|
||||
/*&& (Objects.equals(localVars, blockStatement.localVars)*/
|
||||
);
|
||||
System.out.println("In BlockStatement: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
|
||||
public class EmptyStatement extends AbstractType implements IStatement{
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = "void";
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
//An empty statement does not generate any code
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
19
src/main/java/abstractSyntaxTree/Statement/IStatement.java
Normal file
19
src/main/java/abstractSyntaxTree/Statement/IStatement.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
public interface IStatement extends Node {
|
||||
|
||||
TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException;
|
||||
|
||||
void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception;
|
||||
TypeCheckResult getTypeCheckResult();
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class IfElseStatement extends AbstractType implements IStatement{
|
||||
public IExpression condition;
|
||||
IStatement ifStatement;
|
||||
IStatement elseStatement;
|
||||
public String thisClass;
|
||||
|
||||
public IfElseStatement(IExpression condition, IStatement ifStatement, IStatement elseStatement) {
|
||||
this.condition = condition;
|
||||
this.ifStatement = ifStatement;
|
||||
this.elseStatement = elseStatement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
if(ifStatement instanceof BlockStatement blockStatement){
|
||||
blockStatement.thisClass = thisClass;
|
||||
}
|
||||
if(elseStatement instanceof BlockStatement blockStatement){
|
||||
blockStatement.thisClass = thisClass;
|
||||
}
|
||||
|
||||
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
|
||||
|
||||
if (!conditionType.type.equals("boolean")) {
|
||||
throw new TypeCheckException("The condition of a if statement is " + conditionType.type + ", but should be boolean.");
|
||||
}
|
||||
|
||||
TypeCheckResult ifStatementType = ifStatement.typeCheck(methodContext, typeContext, localVars);
|
||||
TypeCheckResult elseStatementType = elseStatement.typeCheck(methodContext, typeContext, localVars);
|
||||
|
||||
if (!ifStatementType.type.equals(elseStatementType.type)) {
|
||||
if(ifStatementType.type != "void" && elseStatementType.type != "void")
|
||||
throw new TypeCheckException("If- and else-path return different not-void types.");
|
||||
}
|
||||
|
||||
result.type = ifStatementType.type + "," + elseStatementType.type;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
|
||||
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
|
||||
|
||||
Label conditionFalse = new Label();
|
||||
Label statementEnd = new Label();
|
||||
|
||||
condition.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
|
||||
ifStatement.codeGen(mv, blockLocalVars, typeContext, methodContext); //If the condition is true, execute the ifBlock
|
||||
|
||||
mv.visitJumpInsn(Opcodes.GOTO, statementEnd); //Jump to the end of the else statement
|
||||
|
||||
mv.visitLabel(conditionFalse);
|
||||
elseStatement.codeGen(mv, blockLocalVars, typeContext, methodContext); //If the condition is false, execute the elseBlock
|
||||
|
||||
mv.visitLabel(statementEnd); //End of the if-else statement
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
IfElseStatement ifElseStatement = (IfElseStatement) o;
|
||||
boolean result = (Objects.equals(condition, ifElseStatement.condition)
|
||||
&& Objects.equals(ifStatement, ifElseStatement.ifStatement)
|
||||
&& Objects.equals(elseStatement, ifElseStatement.elseStatement)
|
||||
);
|
||||
System.out.println("In PrintStatement: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
78
src/main/java/abstractSyntaxTree/Statement/IfStatement.java
Normal file
78
src/main/java/abstractSyntaxTree/Statement/IfStatement.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class IfStatement extends AbstractType implements IStatement{
|
||||
public IExpression condition;
|
||||
IStatement ifStatement;
|
||||
public String thisClass;
|
||||
|
||||
public IfStatement(IExpression condition, IStatement ifStatement) {
|
||||
this.condition = condition;
|
||||
this.ifStatement = ifStatement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
|
||||
|
||||
if (!conditionType.type.equals("boolean")) {
|
||||
throw new TypeCheckException("Condition of If-Statement is " + conditionType.type + ", but should be boolean.");
|
||||
}
|
||||
|
||||
if(ifStatement instanceof BlockStatement blockStatement){
|
||||
blockStatement.thisClass = thisClass;
|
||||
}
|
||||
TypeCheckResult ifStatementType = ifStatement.typeCheck(methodContext, typeContext, localVars);
|
||||
result.type = ifStatementType.type;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
|
||||
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
|
||||
|
||||
Label conditionFalse = new Label();
|
||||
|
||||
condition.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); //Checks if the condition is false (0)
|
||||
ifStatement.codeGen(mv, blockLocalVars, typeContext, methodContext);
|
||||
|
||||
mv.visitLabel(conditionFalse); // If the condition is false, the Statements in the ifBlock will not be executed
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
IfStatement ifStatementObj = (IfStatement) o;
|
||||
boolean result = (Objects.equals(condition, ifStatementObj.condition)
|
||||
&& Objects.equals(ifStatement, ifStatementObj.ifStatement)
|
||||
);
|
||||
System.out.println("In IfStatement: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
114
src/main/java/abstractSyntaxTree/Statement/LocalVarDecl.java
Normal file
114
src/main/java/abstractSyntaxTree/Statement/LocalVarDecl.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||
import abstractSyntaxTree.StatementExpression.NewStatementExpression;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class LocalVarDecl extends AbstractType implements IStatement{
|
||||
String type;
|
||||
String identifier;
|
||||
IExpression expression;
|
||||
public String thisClass;
|
||||
public LocalVarDecl(String type, String identifier, IExpression expression) {
|
||||
this.type = type;
|
||||
this.identifier = identifier;
|
||||
this.expression = expression;
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
|
||||
// left
|
||||
TypeCheckHelper.typeExists(this.type, new ArrayList<>(methodContext.keySet()));
|
||||
localVars.put(this.identifier, this.type);
|
||||
|
||||
// right part if existing
|
||||
if(expression != null){
|
||||
if(expression instanceof MethodCallStatementExpression){
|
||||
MethodCallStatementExpression methodCall = (MethodCallStatementExpression) expression;
|
||||
methodCall.thisClass = this.thisClass;
|
||||
}
|
||||
if(expression instanceof LocalVarIdentifier localVarIdentifier){
|
||||
localVarIdentifier.thisClass = thisClass;
|
||||
}
|
||||
if (expression instanceof NewStatementExpression newStatementExpression){
|
||||
newStatementExpression.thisClass = thisClass;
|
||||
}
|
||||
|
||||
expression.typeCheck(methodContext, typeContext, localVars);
|
||||
}
|
||||
|
||||
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = "void";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
localVars.put(identifier, type);
|
||||
|
||||
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, identifier);
|
||||
|
||||
if (index == -1){
|
||||
throw new Exception("Variable " + identifier + " not found");
|
||||
}
|
||||
|
||||
if (expression != null) {
|
||||
expression.codeGen(mv, localVars, typeContext,methodContext);
|
||||
|
||||
// Store the result in the local variable
|
||||
switch (type){
|
||||
case "int", "char", "boolean":
|
||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||
break;
|
||||
default:
|
||||
mv.visitVarInsn(Opcodes.ASTORE, index);
|
||||
}
|
||||
} else {
|
||||
|
||||
// Set a default value for the variable --> fewer problems
|
||||
switch (type) {
|
||||
case "int", "boolean", "char":
|
||||
mv.visitInsn(Opcodes.ICONST_0);
|
||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||
break;
|
||||
case "void":
|
||||
break;
|
||||
default:
|
||||
mv.visitInsn(Opcodes.ACONST_NULL);
|
||||
mv.visitVarInsn(Opcodes.ASTORE, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
LocalVarDecl localVarDecl = (LocalVarDecl) o;
|
||||
boolean result = (Objects.equals(type, localVarDecl.type)
|
||||
&& Objects.equals(identifier, localVarDecl.identifier)
|
||||
);
|
||||
System.out.println("In LocalVarDecl: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class PrintStatement extends AbstractType implements IStatement {
|
||||
String variableName;
|
||||
public String thisClass;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PrintStatement printStatement = (PrintStatement) o;
|
||||
boolean result = (Objects.equals(variableName, printStatement.variableName)
|
||||
);
|
||||
System.out.println("In PrintStatement: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public PrintStatement(String variableName) {
|
||||
this.variableName = variableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
String typeOfVar = localVars.get(variableName);
|
||||
if (typeOfVar == null) {
|
||||
typeOfVar = typeContext.get(thisClass).get(variableName);
|
||||
}
|
||||
if (!Objects.equals(typeOfVar, "int"))
|
||||
throw new TypeCheckException("The variable to be printed is " + typeOfVar + " but should be int.");
|
||||
result.type = "void";
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
// Load System.out onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
|
||||
|
||||
// Load the value of the variable onto the stack
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, variableName);
|
||||
|
||||
// If not a localVar, maybe a class field of this class
|
||||
if (index == -1){
|
||||
String typeOfField = typeContext.get(thisClass).get(variableName);
|
||||
if (typeOfField == null){
|
||||
throw new Exception("Variable " + variableName + " not found in local variables or class fields.");
|
||||
}
|
||||
mv.visitFieldInsn(Opcodes.GETSTATIC, thisClass, variableName, "I");
|
||||
}
|
||||
|
||||
mv.visitVarInsn(Opcodes.ILOAD, index);
|
||||
|
||||
// Call the println method
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V", false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.StatementExpression.MethodCallStatementExpression;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ReturnStatement extends AbstractType implements IStatement{
|
||||
IExpression expression; // Needs typeCheckResult
|
||||
public String thisClass;
|
||||
|
||||
public ReturnStatement(IExpression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
if (expression == null) {
|
||||
result.type = "void";
|
||||
} else {
|
||||
if(expression instanceof MethodCallStatementExpression methodCallStatementExpression)
|
||||
methodCallStatementExpression.thisClass = this.thisClass;
|
||||
else if(expression instanceof InstVarExpression instVarExpression)
|
||||
instVarExpression.thisClass = this.thisClass;
|
||||
else if(expression instanceof LocalVarIdentifier localVarIdentifier)
|
||||
localVarIdentifier.thisClass = this.thisClass;
|
||||
TypeCheckResult typedExpression = expression.typeCheck(methodContext, typeContext, localVars);
|
||||
result.type = typedExpression.type;
|
||||
}
|
||||
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
|
||||
if (expression != null) {
|
||||
expression.codeGen(mv, localVars, typeContext, methodContext);
|
||||
//Get the Type of the expression
|
||||
String type = expression.getTypeCheckResult().type;
|
||||
|
||||
if (type.equals("int") || type.equals("boolean") || type.equals("char")) {
|
||||
mv.visitInsn(Opcodes.IRETURN);
|
||||
} else {
|
||||
mv.visitInsn(Opcodes.ARETURN);
|
||||
}
|
||||
} else {
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ReturnStatement returnStatement = (ReturnStatement) o;
|
||||
boolean result = (Objects.equals(expression, returnStatement.expression)
|
||||
&& Objects.equals(expression.getTypeCheckResult(), returnStatement.expression.getTypeCheckResult())
|
||||
);
|
||||
System.out.println("In ReturnStatement: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package abstractSyntaxTree.Statement;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import TypeCheck.AbstractType;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class WhileStatement extends AbstractType implements IStatement {
|
||||
IExpression condition;
|
||||
IStatement statement;
|
||||
public String thisClass;
|
||||
|
||||
public WhileStatement(IExpression condition, IStatement statement) {
|
||||
this.condition = condition;
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
// check condition
|
||||
TypeCheckResult conditionType = condition.typeCheck(methodContext, typeContext, localVars);
|
||||
if (!conditionType.type.equals("boolean")) {
|
||||
throw new TypeCheckException("Condition of while-statement is of type " + conditionType.type + " but should be boolean.");
|
||||
}
|
||||
|
||||
// check code block
|
||||
TypeCheckResult statementType = statement.typeCheck(methodContext, typeContext, localVars);
|
||||
|
||||
// set result
|
||||
result.type = statementType.type;
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
|
||||
LinkedHashMap<String, String> blockLocalVars = new LinkedHashMap<>(localVars);
|
||||
|
||||
Label conditionFalse = new Label();
|
||||
Label LoopStart = new Label();
|
||||
|
||||
mv.visitLabel(LoopStart);
|
||||
|
||||
condition.codeGen(mv, localVars, typeContext, methodContext);
|
||||
mv.visitJumpInsn(Opcodes.IFEQ, conditionFalse); // Checks if the condition is false (0)
|
||||
|
||||
statement.codeGen(mv, blockLocalVars, typeContext, methodContext);
|
||||
|
||||
mv.visitJumpInsn(Opcodes.GOTO, LoopStart); // Jump to the start of the while loop
|
||||
|
||||
mv.visitLabel(conditionFalse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
WhileStatement whileStatement = (WhileStatement) o;
|
||||
boolean result = (Objects.equals(condition, whileStatement.condition)
|
||||
&& Objects.equals(statement, whileStatement.statement)
|
||||
);
|
||||
System.out.println("In PrintStatement: " + result);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
import CodeGen.CodeGenHelper;
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.BinaryExpression;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Objects;
|
||||
|
||||
public class AssignStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||
public String operator;
|
||||
public IExpression left;
|
||||
public IExpression right;
|
||||
private InstVarExpression instVar;
|
||||
public String thisClass;
|
||||
|
||||
public AssignStatementExpression(String operator, IExpression leftExpression, IExpression rightExpression){
|
||||
this.operator = operator;
|
||||
this.left = leftExpression;
|
||||
this.right = rightExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
TypeCheckResult leftType;
|
||||
|
||||
if (left instanceof LocalVarIdentifier localVarIdentifier) {
|
||||
localVarIdentifier.thisClass = thisClass;
|
||||
leftType = new TypeCheckResult();
|
||||
String identifier = localVarIdentifier.getIdentifier();
|
||||
leftType.type = localVars.get(identifier);
|
||||
|
||||
// local var may be actually instVar of this
|
||||
if(leftType.type == null){
|
||||
leftType.type = typeContext.get(thisClass).get(identifier);
|
||||
}
|
||||
}else {
|
||||
if(left instanceof InstVarExpression instVarExpression)
|
||||
instVarExpression.thisClass = this.thisClass;
|
||||
leftType = left.typeCheck(methodContext, typeContext, localVars);
|
||||
}
|
||||
if(right instanceof MethodCallStatementExpression methodCallStatementExpression)
|
||||
methodCallStatementExpression.thisClass = this.thisClass;
|
||||
if(right instanceof LocalVarIdentifier localVarIdentifierRight)
|
||||
localVarIdentifierRight.thisClass = this.thisClass;
|
||||
if(right instanceof BinaryExpression binaryExpression)
|
||||
binaryExpression.thisClass = this.thisClass;
|
||||
|
||||
TypeCheckResult rightType = right.typeCheck(methodContext, typeContext, localVars);
|
||||
|
||||
String upperbound = TypeCheckHelper.upperBound(leftType.type, rightType.type);
|
||||
if(Objects.equals(leftType.type, "boolean"))
|
||||
leftType.type = "boolean";
|
||||
if (!Objects.equals(upperbound, leftType.type)) {
|
||||
throw new TypeCheckException("The upper bound of assignment is not the left type.");
|
||||
}
|
||||
result.type = "void";
|
||||
setTypeCheckResult(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public TypeCheckResult typeCheck() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
|
||||
if (left instanceof LocalVarIdentifier) {
|
||||
LocalVarIdentifier localVar = (LocalVarIdentifier) left;
|
||||
String varName = localVar.getIdentifier();
|
||||
|
||||
//Get the index of the local variable
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, varName);
|
||||
|
||||
if (index == -1) {
|
||||
String fieldType = typeContext.get(thisClass).get(varName);
|
||||
if (fieldType != null) {
|
||||
// Load "this" onto the stack
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
// Call the codeGen on the right expression which will push the value of the right expression onto the stack
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
// Get the field descriptor
|
||||
String descriptor = getFieldDescriptor(fieldType, typeContext, varName, thisClass);
|
||||
// Store the value in the field
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, thisClass, varName, descriptor);
|
||||
return;
|
||||
} else {
|
||||
throw new Exception("Variable " + varName + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
String type = localVars.get(localVar.getIdentifier());
|
||||
// Call the codeGen on the right expression which will push the value of the right expression onto the stack
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
switch (type) {
|
||||
case "int", "char", "boolean":
|
||||
mv.visitVarInsn(Opcodes.ISTORE, index);
|
||||
break;
|
||||
default:
|
||||
mv.visitVarInsn(Opcodes.ASTORE, index);
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (left instanceof InstVarExpression) {
|
||||
instVar = (InstVarExpression) left;
|
||||
|
||||
boolean isLocal = false;
|
||||
|
||||
// Load the reference onto the stack
|
||||
// Determine if the reference is this or another object
|
||||
if (instVar.receivers.get(0).identifier != null) {
|
||||
// Load the local variable (another object) onto the stack
|
||||
int index = CodeGenHelper.GetLocalVarIndex(localVars, instVar.receivers.get(0).identifier);
|
||||
|
||||
if (index == -1) {
|
||||
throw new Exception("Variable " + instVar.receivers.get(0).identifier + " not found");
|
||||
}
|
||||
mv.visitVarInsn(Opcodes.ALOAD, index);
|
||||
isLocal = true;
|
||||
} else {
|
||||
// Load "this" onto the stack
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
|
||||
}
|
||||
|
||||
//Now that the base ref is on the stack, I need to get the next field(s) and store the value in the last field
|
||||
|
||||
String typeOfPrevious = "";
|
||||
String currentType = "";
|
||||
if (instVar.receivers.size() > 0) {
|
||||
for (int i = 0; i < instVar.receivers.size(); i++) {
|
||||
|
||||
if (i == 0) {
|
||||
|
||||
//Check if the chain is longer than 1
|
||||
// If it is not, then we can directly store the value in the field
|
||||
// If not we have to load the reference of the field on the stack
|
||||
if (instVar.receivers.size() < 2) {
|
||||
// Chain is only 1 long, so we can call PUTFIELD directly
|
||||
|
||||
//Load the value of the right expression on the stack
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
if (isLocal) {
|
||||
typeOfPrevious = localVars.get(instVar.receivers.get(i).identifier);
|
||||
} else {
|
||||
typeOfPrevious = typeContext.get(thisClass).get(instVar.receivers.get(i).identifier);
|
||||
if (typeOfPrevious == null) {
|
||||
typeOfPrevious = thisClass;
|
||||
}
|
||||
}
|
||||
|
||||
currentType = typeContext.get(typeOfPrevious).get(instVar.fieldName);
|
||||
|
||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, typeOfPrevious);
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, typeOfPrevious, instVar.fieldName, descriptor);
|
||||
continue;
|
||||
} else {
|
||||
|
||||
if (isLocal) {
|
||||
currentType = localVars.get(instVar.receivers.get(i).identifier);
|
||||
} else {
|
||||
currentType = typeContext.get(thisClass).get(instVar.receivers.get(i).identifier);
|
||||
}
|
||||
|
||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.receivers.get(i).identifier, thisClass);
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, instVar.receivers.get(i).identifier, descriptor);
|
||||
typeOfPrevious = currentType;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//Now we have to implement the logic for the following fields in the chain as the above code
|
||||
// only handles the first field in the chain
|
||||
|
||||
currentType = typeContext.get(typeOfPrevious).get(instVar.receivers.get(i).identifier);
|
||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.receivers.get(i).identifier, typeOfPrevious);
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, typeOfPrevious, instVar.receivers.get(i).identifier, descriptor);
|
||||
typeOfPrevious = currentType;
|
||||
}
|
||||
|
||||
// Now we have the reference of the last field in the chain on the stack
|
||||
if (instVar.receivers.size() > 1) {
|
||||
// We can store the value of the right expression in this field
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
currentType = typeContext.get(typeOfPrevious).get(instVar.fieldName);
|
||||
String descriptor = getFieldDescriptor(currentType, typeContext, instVar.fieldName, typeOfPrevious);
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, typeOfPrevious, instVar.fieldName, descriptor);
|
||||
}
|
||||
|
||||
} else {
|
||||
// When a field is accessed directly and without a "this."
|
||||
|
||||
//Load the value of the right expression on the stack
|
||||
right.codeGen(mv, localVars, typeContext, methodContext);
|
||||
|
||||
// Get the field information
|
||||
String fieldType = typeContext.get(instVar.thisClass).get(instVar.fieldName);
|
||||
|
||||
// Get the field descriptor
|
||||
String descriptor = getFieldDescriptor(fieldType, typeContext, instVar.fieldName, instVar.thisClass);
|
||||
|
||||
// Store the value in the field
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, instVar.thisClass, instVar.fieldName, descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getFieldDescriptor(String type, HashMap<String, HashMap<String, String>> typeContext, String varName, String classToSearchFieldIn) {
|
||||
StringBuilder descriptor = new StringBuilder();
|
||||
switch (type) {
|
||||
case "int":
|
||||
return "I";
|
||||
case "boolean":
|
||||
return "Z";
|
||||
case "char":
|
||||
return "C";
|
||||
default: {
|
||||
String fullReturnType = typeContext.get(classToSearchFieldIn).get(varName);
|
||||
|
||||
// If it is a class reference replace the "." with "/" and return it
|
||||
if (type.contains(".")) fullReturnType = fullReturnType.replaceAll("\\.", "/");
|
||||
if (fullReturnType != null) descriptor.append("L").append(fullReturnType).append(";");
|
||||
return descriptor.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
AssignStatementExpression assignStatementExpression = (AssignStatementExpression) o;
|
||||
return (Objects.equals(operator, assignStatementExpression.operator)
|
||||
&& Objects.equals(left, assignStatementExpression.left)
|
||||
&& Objects.equals(right, assignStatementExpression.right)
|
||||
);
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import jdk.jshell.spi.ExecutionControl;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MethodCallStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||
String methodName;
|
||||
List<IExpression> arguments;
|
||||
Receiver receiver;
|
||||
List<ReceivingMethod> receivingMethods;
|
||||
public String thisClass;
|
||||
|
||||
public MethodCallStatementExpression(String methodName, Receiver receiver, List<ReceivingMethod> receivingMethods, List<IExpression> arguments) {
|
||||
this.methodName = methodName;
|
||||
this.receiver = receiver;
|
||||
this.receivingMethods = receivingMethods;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
|
||||
String classToSearchMethodIn = thisClass;
|
||||
|
||||
if (this.receiver != null) {
|
||||
if (!receiver.thisExpression) {
|
||||
classToSearchMethodIn = localVars.get(receiver.identifier);
|
||||
if (classToSearchMethodIn == null)
|
||||
classToSearchMethodIn = thisClass;
|
||||
}
|
||||
}
|
||||
|
||||
String currentType = "";
|
||||
|
||||
// receiver is instVar
|
||||
if (receiver != null) {
|
||||
if (receiver.instVarExpression != null) {
|
||||
receiver.instVarExpression.thisClass = this.thisClass;
|
||||
String typeOfSubreceiver = receiver.instVarExpression.typeCheck(methodContext, typeContext, localVars).type;
|
||||
|
||||
currentType = typeOfSubreceiver;
|
||||
} else {
|
||||
currentType = classToSearchMethodIn;
|
||||
}
|
||||
} else {
|
||||
currentType = thisClass;
|
||||
}
|
||||
|
||||
for (int i = 0; i < receivingMethods.size(); i++) {
|
||||
currentType = (String) methodContext.get(currentType).get(receivingMethods.get(i).methodName).keySet().toArray()[0];
|
||||
if (currentType == null)
|
||||
throw new TypeCheckException("The method " + methodName + " was not found in " + classToSearchMethodIn + ".");
|
||||
receivingMethods.get(i).thisClass = this.thisClass;
|
||||
receivingMethods.get(i).checkParameters(methodContext, typeContext, localVars);
|
||||
}
|
||||
currentType = (String) methodContext.get(currentType).get(methodName).keySet().toArray()[0];
|
||||
|
||||
for (IExpression argument : arguments) {
|
||||
argument.typeCheck(methodContext, typeContext, localVars);
|
||||
}
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
result.type = currentType;
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
//Errors occur due to the change in parameter in the RefType class
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
String owner;
|
||||
|
||||
// Load the object onto the stack
|
||||
if (receiver != null) {
|
||||
if (receiver.thisExpression) {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
owner = thisClass;
|
||||
} else if (receiver.instVarExpression != null) {
|
||||
receiver.instVarExpression.codeGen(mv, localVars, typeContext, methodContext);
|
||||
owner = receiver.instVarExpression.getTypeCheckResult().type;
|
||||
} else if (receiver.newStatementExpression != null) {
|
||||
receiver.newStatementExpression.codeGen(mv, localVars, typeContext, methodContext);
|
||||
owner = receiver.newStatementExpression.getTypeCheckResult().type;
|
||||
} else if (receiver.identifier != null) {
|
||||
String type = localVars.get(receiver.identifier);
|
||||
if (type == null) {
|
||||
// If it is not a local variable, assume it is a field of the current class
|
||||
type = typeContext.get(thisClass).get(receiver.identifier);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0); // Load "this" onto the stack
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, thisClass, receiver.identifier, "L" + type + ";"); // Load the field onto the stack
|
||||
} else {
|
||||
// It's a local variable
|
||||
int index = localVars.keySet().stream().toList().indexOf(receiver.identifier) + 1; // +1 because the first local variable is at index 1, 0 is used for "this"
|
||||
int opcode = type.equals("int") ? Opcodes.ILOAD : Opcodes.ALOAD;
|
||||
mv.visitVarInsn(opcode, index); // Load local variable onto the stack
|
||||
}
|
||||
owner = type;
|
||||
} else {
|
||||
throw new ExecutionControl.NotImplementedException("Receiver type not supported.");
|
||||
}
|
||||
} else {
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
owner = thisClass;
|
||||
|
||||
}
|
||||
String returnOfPreviousMethod = null;
|
||||
// Invoke the method for each receiving method in the chain
|
||||
for (ReceivingMethod receivingMethod : receivingMethods) {
|
||||
// Get the owner class for the current method in the chain
|
||||
if (returnOfPreviousMethod != null) {
|
||||
// If the return of the previous method is not null, use it as the owner class for the current method in the chain
|
||||
owner = returnOfPreviousMethod;
|
||||
}
|
||||
|
||||
// Generate the code for each argument expression for the current method
|
||||
for (IExpression argument : receivingMethod.arguments) {
|
||||
argument.codeGen(mv, localVars, typeContext, methodContext);
|
||||
}
|
||||
|
||||
// Invoke the current method
|
||||
String descriptor = getMethodDescriptor(receivingMethod.methodName, localVars, methodContext, receivingMethod.arguments, returnOfPreviousMethod, owner);
|
||||
returnOfPreviousMethod = methodContext.get(owner).get(receivingMethod.methodName).keySet().toArray()[0].toString();
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, receivingMethod.methodName, descriptor, false);
|
||||
}
|
||||
|
||||
// Invoke the final method
|
||||
|
||||
// Generate the code for each argument expression
|
||||
for (IExpression argument : arguments) {
|
||||
argument.codeGen(mv, localVars, typeContext, methodContext);
|
||||
}
|
||||
|
||||
if (returnOfPreviousMethod != null) {
|
||||
owner = returnOfPreviousMethod;
|
||||
}
|
||||
|
||||
String descriptor = getMethodDescriptor(methodName, localVars, methodContext, arguments, returnOfPreviousMethod, owner);
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, methodName, descriptor, false);
|
||||
|
||||
}
|
||||
|
||||
private String getMethodDescriptor(String methodName, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, List<IExpression> arguments, String returnOfPreviousMethod, String owner) {
|
||||
StringBuilder descriptor = new StringBuilder("(");
|
||||
|
||||
for (IExpression argument : arguments) {
|
||||
TypeCheckResult result = argument.getTypeCheckResult();
|
||||
String type = result.type;
|
||||
|
||||
switch (type) {
|
||||
case "int":
|
||||
descriptor.append("I");
|
||||
break;
|
||||
case "boolean":
|
||||
descriptor.append("Z");
|
||||
break;
|
||||
case "char":
|
||||
descriptor.append("C");
|
||||
break;
|
||||
case "void":
|
||||
descriptor.append("V");
|
||||
break;
|
||||
default:
|
||||
// If it is a class reference replace the "." with "/" and return it
|
||||
if (type.contains(".")) type = type.replaceAll("\\.", "/");
|
||||
descriptor.append("L").append(type).append(";");
|
||||
break;
|
||||
}
|
||||
}
|
||||
descriptor.append(")");
|
||||
|
||||
String classToSearchMethodIn;
|
||||
//Return Type
|
||||
if (receiver != null) {
|
||||
if (receiver.identifier != null) {
|
||||
classToSearchMethodIn = localVars.get(receiver.identifier);
|
||||
if (classToSearchMethodIn == null) {
|
||||
classToSearchMethodIn = returnOfPreviousMethod;
|
||||
}
|
||||
if (classToSearchMethodIn == null) {
|
||||
classToSearchMethodIn = thisClass;
|
||||
}
|
||||
} else {
|
||||
if (receiver.instVarExpression != null && returnOfPreviousMethod != null) {
|
||||
classToSearchMethodIn = returnOfPreviousMethod;
|
||||
} else {
|
||||
classToSearchMethodIn = owner;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
classToSearchMethodIn = thisClass;
|
||||
}
|
||||
|
||||
|
||||
String returnType = methodContext.get(classToSearchMethodIn).get(methodName).keySet().toArray()[0].toString();
|
||||
|
||||
switch (returnType) {
|
||||
case "int":
|
||||
descriptor.append("I");
|
||||
break;
|
||||
case "boolean":
|
||||
descriptor.append("Z");
|
||||
break;
|
||||
case "char":
|
||||
descriptor.append("C");
|
||||
break;
|
||||
case "void":
|
||||
descriptor.append("V");
|
||||
break;
|
||||
default:
|
||||
// If it is a class reference replace the "." with "/" and return it
|
||||
if (returnType.contains(".")) returnType = returnType.replaceAll("\\.", "/");
|
||||
descriptor.append("L").append(returnType).append(";");
|
||||
break;
|
||||
}
|
||||
return descriptor.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MethodCallStatementExpression methodCallStatementExpression = (MethodCallStatementExpression) o;
|
||||
boolean typeCheckResults = testTypeChecks(this, methodCallStatementExpression);
|
||||
|
||||
boolean result = (Objects.equals(methodName, methodCallStatementExpression.methodName)
|
||||
&& Objects.equals(arguments, methodCallStatementExpression.arguments)
|
||||
&& Objects.equals(thisClass, methodCallStatementExpression.thisClass));
|
||||
return result && typeCheckResults;
|
||||
|
||||
}
|
||||
|
||||
public boolean testTypeChecks(MethodCallStatementExpression class1, MethodCallStatementExpression class2) {
|
||||
|
||||
boolean resultArguments = true;
|
||||
|
||||
for (int i = 0; i < class1.arguments.size(); i++){
|
||||
resultArguments = resultArguments && Objects.equals(class1.arguments.get(i).getTypeCheckResult(), class2.arguments.get(i).getTypeCheckResult());
|
||||
}
|
||||
|
||||
boolean exception1 = false;
|
||||
boolean exception2 = false;
|
||||
|
||||
try {
|
||||
class1.receiver.instVarExpression.getTypeCheckResult();
|
||||
} catch (NullPointerException e) {
|
||||
exception1 = true;
|
||||
}
|
||||
|
||||
try {
|
||||
class2.receiver.instVarExpression.getTypeCheckResult();
|
||||
} catch (NullPointerException e) {
|
||||
exception2 = true;
|
||||
}
|
||||
|
||||
if(exception1 != exception2) {
|
||||
System.out.println("Only one of the InstVarTypeChecks is null in MethodCallStatementExpression");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!exception1) {
|
||||
boolean resultInstVar = Objects.equals(receiver.instVarExpression.getTypeCheckResult(), class2.receiver.instVarExpression.getTypeCheckResult());
|
||||
if(!resultInstVar) {
|
||||
System.out.println("TypeCheckResult of receiver.instVarExpression.getTypeCheckResult() in MethodCallStatementExpression do not match");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
try {
|
||||
class1.receiver.newStatementExpression.getTypeCheckResult();
|
||||
} catch (NullPointerException e) {
|
||||
exception1 = true;
|
||||
}
|
||||
|
||||
try {
|
||||
class2.receiver.newStatementExpression.getTypeCheckResult();
|
||||
} catch (NullPointerException e) {
|
||||
exception2 = true;
|
||||
}
|
||||
|
||||
if(exception1 != exception2) {
|
||||
System.out.println("Only one of the newStatementExpression Typechecks is null in MethodCallStatementExpression");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!exception1) {
|
||||
boolean resultNewStatementExpression = Objects.equals(receiver.newStatementExpression.getTypeCheckResult().type, class2.receiver.newStatementExpression.getTypeCheckResult().type);
|
||||
if(!resultNewStatementExpression) {
|
||||
System.out.println("TypeCheckResult of receiver.newStatementExpression.getTypeCheckResult().type in MethodCallStatementExpression do not match");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
import TypeCheck.AbstractType;
|
||||
import TypeCheck.TypeCheckException;
|
||||
import TypeCheck.TypeCheckHelper;
|
||||
import TypeCheck.TypeCheckResult;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Statement.IStatement;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class NewStatementExpression extends AbstractType implements IExpression, IStatement {
|
||||
|
||||
public String thisClass;
|
||||
private String className;
|
||||
private List<IExpression> arguments;
|
||||
|
||||
public NewStatementExpression(String className, List<IExpression> arguments) {
|
||||
this.className = className;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
NewStatementExpression newStatementExpression = (NewStatementExpression) o;
|
||||
boolean resultTypeCheckArguments = true;
|
||||
for (int i = 0; i < newStatementExpression.arguments.size(); i++){
|
||||
resultTypeCheckArguments = resultTypeCheckArguments && Objects.equals(this.arguments.get(i).getTypeCheckResult(), newStatementExpression.arguments.get(i).getTypeCheckResult());
|
||||
}
|
||||
boolean result = (Objects.equals(className, newStatementExpression.className)
|
||||
&& Objects.equals(arguments, newStatementExpression.arguments)
|
||||
);
|
||||
System.out.println("In newStatementExpression: " + result);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeCheckResult typeCheck(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
if(!TypeCheckHelper.typeExists(className, new ArrayList<>(typeContext.keySet()))){
|
||||
throw new TypeCheckException("An instance of " + className + " is created, but the type does not exist.");
|
||||
}
|
||||
for (IExpression argument : arguments) {
|
||||
if (argument instanceof InstVarExpression instVarExpression) {
|
||||
instVarExpression.thisClass = this.thisClass;
|
||||
}
|
||||
argument.typeCheck(methodContext, typeContext, localVars);
|
||||
}
|
||||
|
||||
TypeCheckResult result = new TypeCheckResult();
|
||||
|
||||
result.type = className;
|
||||
setTypeCheckResult(result);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void codeGen(MethodVisitor mv, LinkedHashMap<String, String> localVars, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext) throws Exception {
|
||||
//Create new instance of the class
|
||||
mv.visitTypeInsn(Opcodes.NEW, className);
|
||||
|
||||
//Duplicate the reference, so I can use it after the INVOKE consumes one
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
|
||||
for (IExpression argument : arguments) {
|
||||
argument.codeGen(mv, localVars, typeContext, methodContext);
|
||||
}
|
||||
String descriptor = getConstructorDescriptor();
|
||||
|
||||
//Call the constructor
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, "<init>", descriptor, false);
|
||||
|
||||
// One instance of the class remains now on the stack
|
||||
// Which will then be used in an assignment or method call
|
||||
}
|
||||
|
||||
private String getConstructorDescriptor() {
|
||||
StringBuilder descriptor = new StringBuilder("(");
|
||||
|
||||
|
||||
for (IExpression parameter : arguments) {
|
||||
TypeCheckResult result = parameter.getTypeCheckResult();
|
||||
String type = result.type;
|
||||
|
||||
switch (type) {
|
||||
case "int":
|
||||
descriptor.append("I");
|
||||
break;
|
||||
case "boolean":
|
||||
descriptor.append("Z");
|
||||
break;
|
||||
case "char":
|
||||
descriptor.append("C");
|
||||
break;
|
||||
case "void":
|
||||
descriptor.append("V");
|
||||
break;
|
||||
default:
|
||||
// If it is a class reference replace the "." with "/" and return it
|
||||
if (type.contains(".")) type = type.replaceAll("\\.", "/");
|
||||
descriptor.append("L").append(type).append(";");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
descriptor.append(")V"); // Constructors always return void
|
||||
return descriptor.toString();
|
||||
}
|
||||
@Override
|
||||
public TypeCheckResult getTypeCheckResult() {
|
||||
return super.getTypeCheckResult();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
|
||||
import abstractSyntaxTree.Expression.InstVarExpression;
|
||||
import abstractSyntaxTree.Node;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Receiver implements Node {
|
||||
boolean thisExpression;
|
||||
InstVarExpression instVarExpression;
|
||||
NewStatementExpression newStatementExpression;
|
||||
String identifier;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Receiver receiver = (Receiver) o;
|
||||
boolean result = (Objects.equals(thisExpression, receiver.thisExpression)
|
||||
&& Objects.equals(instVarExpression, receiver.instVarExpression)
|
||||
&& Objects.equals(newStatementExpression, receiver.newStatementExpression)
|
||||
&& Objects.equals(identifier, receiver.identifier)
|
||||
);
|
||||
System.out.println("In receiver: " + result);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
public Receiver(boolean thisExpression) {
|
||||
this.thisExpression = thisExpression;
|
||||
}
|
||||
|
||||
public Receiver(InstVarExpression instVarExpression) {
|
||||
this.instVarExpression = instVarExpression;
|
||||
}
|
||||
|
||||
public Receiver(NewStatementExpression newStatementExpression) {
|
||||
this.newStatementExpression = newStatementExpression;
|
||||
}
|
||||
|
||||
public Receiver(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package abstractSyntaxTree.StatementExpression;
|
||||
|
||||
import TypeCheck.TypeCheckException;
|
||||
import abstractSyntaxTree.Expression.IExpression;
|
||||
import abstractSyntaxTree.Expression.LocalVarIdentifier;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ReceivingMethod implements Node {
|
||||
public String methodName;
|
||||
public List<IExpression> arguments;
|
||||
public String thisClass;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
ReceivingMethod receivingMethod = (ReceivingMethod) o;
|
||||
boolean result = (Objects.equals(methodName, receivingMethod.methodName)
|
||||
&& Objects.equals(arguments, receivingMethod.arguments)
|
||||
);
|
||||
System.out.println("In ReceivingMethod: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ReceivingMethod(String methodName, List<IExpression> arguments) {
|
||||
this.methodName = methodName;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
void checkParameters(HashMap<String, HashMap<String, HashMap<String, ParameterList>>> methodContext, HashMap<String, HashMap<String, String>> typeContext, HashMap<String, String> localVars) throws TypeCheckException {
|
||||
for (IExpression parameter : arguments){
|
||||
if(parameter instanceof LocalVarIdentifier localVarIdentifier){
|
||||
localVarIdentifier.thisClass = thisClass;
|
||||
}
|
||||
parameter.typeCheck(methodContext, typeContext, localVars);
|
||||
}
|
||||
}
|
||||
}
|
||||
411
src/main/java/astGenerator/ASTGenerator.java
Normal file
411
src/main/java/astGenerator/ASTGenerator.java
Normal file
@@ -0,0 +1,411 @@
|
||||
package astGenerator;
|
||||
|
||||
import abstractSyntaxTree.Class.FieldDecl;
|
||||
import abstractSyntaxTree.Class.MethodDecl;
|
||||
import abstractSyntaxTree.Class.RefType;
|
||||
import abstractSyntaxTree.Expression.*;
|
||||
import abstractSyntaxTree.Node;
|
||||
import abstractSyntaxTree.Parameter.Parameter;
|
||||
import abstractSyntaxTree.Parameter.ParameterList;
|
||||
import abstractSyntaxTree.Program;
|
||||
import abstractSyntaxTree.Statement.*;
|
||||
import abstractSyntaxTree.StatementExpression.*;
|
||||
import gen.DecafBaseVisitor;
|
||||
import gen.DecafParser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ASTGenerator extends DecafBaseVisitor<Node> {
|
||||
@Override
|
||||
public Node visitProgram(DecafParser.ProgramContext ctx) {
|
||||
List<RefType> classes = new ArrayList<>();
|
||||
for (DecafParser.ClassdeclContext classDecl : ctx.classdecl()) {
|
||||
classes.add((RefType) visit(classDecl));
|
||||
}
|
||||
return new Program(classes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitClassdecl(DecafParser.ClassdeclContext ctx) {
|
||||
String name = ctx.Identifier().getText();
|
||||
List<FieldDecl> fieldDecls = new ArrayList<>();
|
||||
List<MethodDecl> methodDecls = new ArrayList<>();
|
||||
boolean hasMain;
|
||||
if (ctx.MainMethodDecl() != null) {
|
||||
hasMain = true;
|
||||
MethodDecl mainMethod = new MethodDecl(name, "void", "main", new ParameterList(new ArrayList<>()), (BlockStatement) visitBlock(ctx.block()));
|
||||
methodDecls.add(mainMethod);
|
||||
} else {
|
||||
hasMain = false;
|
||||
}
|
||||
for (DecafParser.LocalVarDeclContext fieldDecl : ctx.localVarDecl()) {
|
||||
fieldDecls.add((FieldDecl) generateFieldDecl(fieldDecl));
|
||||
}
|
||||
for (DecafParser.ConstuctorDeclContext constDecl : ctx.constuctorDecl()) {
|
||||
MethodDecl constructor = ((MethodDecl) visit(constDecl));
|
||||
constructor.classThatContainsMethod = name;
|
||||
methodDecls.add(constructor);
|
||||
}
|
||||
for (DecafParser.MethodDeclContext methodDecl : ctx.methodDecl()) {
|
||||
MethodDecl method = (MethodDecl) visit(methodDecl);
|
||||
method.classThatContainsMethod = name;
|
||||
methodDecls.add(method);
|
||||
}
|
||||
return new RefType(name, fieldDecls, methodDecls, hasMain);
|
||||
}
|
||||
|
||||
public Node generateFieldDecl(DecafParser.LocalVarDeclContext ctx) {
|
||||
if (ctx.expression() != null) {
|
||||
IExpression expression = (IExpression) visit(ctx.expression());
|
||||
return new FieldDecl(ctx.type().getText(), ctx.Identifier().getText(), expression);
|
||||
} else {
|
||||
return new FieldDecl(ctx.type().getText(), ctx.Identifier().getText(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitLocalVarDecl(DecafParser.LocalVarDeclContext ctx) {
|
||||
if (ctx.expression() != null) {
|
||||
IExpression expression = (IExpression) visit(ctx.expression());
|
||||
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), expression);
|
||||
} else {
|
||||
return new LocalVarDecl(ctx.type().getText(), ctx.Identifier().getText(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitConstuctorDecl(DecafParser.ConstuctorDeclContext ctx) {
|
||||
String name = ctx.Identifier().getText();
|
||||
ParameterList parameterList = new ParameterList(new ArrayList<>());
|
||||
if (ctx.parameterList() != null) {
|
||||
parameterList = (ParameterList) visit(ctx.parameterList());
|
||||
}
|
||||
BlockStatement block = (BlockStatement) visitBlock(ctx.block());
|
||||
return new MethodDecl("", null, name, parameterList, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitMethodDecl(DecafParser.MethodDeclContext ctx) {
|
||||
String type;
|
||||
String name = ctx.Identifier().getText();
|
||||
BlockStatement block = (BlockStatement) visitBlock(ctx.block());
|
||||
ParameterList parameterList = new ParameterList(new ArrayList<>());
|
||||
if (ctx.parameterList() != null) {
|
||||
parameterList = (ParameterList) visit(ctx.parameterList());
|
||||
}
|
||||
if (ctx.Void() != null) {
|
||||
type = "void";
|
||||
} else {
|
||||
type = ctx.type().getText();
|
||||
}
|
||||
return new MethodDecl("", type, name, parameterList, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitParameter(DecafParser.ParameterContext ctx) {
|
||||
return new Parameter(ctx.type().getText(), ctx.Identifier().getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitParameterList(DecafParser.ParameterListContext ctx) {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
for (DecafParser.ParameterContext parameter : ctx.parameter()) {
|
||||
parameters.add((Parameter) visit(parameter));
|
||||
}
|
||||
return new ParameterList(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitStatement(DecafParser.StatementContext ctx) {
|
||||
if (ctx.returnStmt() != null) {
|
||||
return visitReturnStmt(ctx.returnStmt());
|
||||
} else if (ctx.ifElseStmt() != null) {
|
||||
return visitIfElseStmt(ctx.ifElseStmt());
|
||||
} else if (ctx.whileStmt() != null) {
|
||||
return visitWhileStmt(ctx.whileStmt());
|
||||
} else if (ctx.block() != null) {
|
||||
return visitBlock(ctx.block());
|
||||
} else if (ctx.stmtExpr() != null) {
|
||||
return visitStmtExpr(ctx.stmtExpr());
|
||||
} else if (ctx.emptyStatement() != null) {
|
||||
return visitEmptyStatement(ctx.emptyStatement());
|
||||
} else if (ctx.localVarDecl() != null) {
|
||||
return visitLocalVarDecl(ctx.localVarDecl());
|
||||
} else if (ctx.print() != null) {
|
||||
return visitPrint(ctx.print());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitReturnStmt(DecafParser.ReturnStmtContext ctx) {
|
||||
if (ctx.expression() != null) {
|
||||
Node expression = visitExpression(ctx.expression());
|
||||
return new ReturnStatement((IExpression) expression);
|
||||
} else {
|
||||
return new ReturnStatement(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitBlock(DecafParser.BlockContext ctx) {
|
||||
List<IStatement> stmts = new ArrayList<>();
|
||||
for (DecafParser.StatementContext stmt : ctx.statement()) {
|
||||
Node statement = visitStatement(stmt);
|
||||
stmts.add((IStatement) statement);
|
||||
}
|
||||
String returnType = getReturnType(stmts);
|
||||
return new BlockStatement(stmts, returnType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitIfElseStmt(DecafParser.IfElseStmtContext ctx) {
|
||||
if (ctx.elseStmt() != null) {
|
||||
Node expression = visitExpression(ctx.ifStmt().expression());
|
||||
Node ifStatement = visitStatement(ctx.ifStmt().statement());
|
||||
Node elseStatement = visitStatement(ctx.elseStmt().statement());
|
||||
return new IfElseStatement((IExpression) expression, (IStatement) ifStatement, (IStatement) elseStatement);
|
||||
} else {
|
||||
return visitIfStmt(ctx.ifStmt());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitIfStmt(DecafParser.IfStmtContext ctx) {
|
||||
Node expression = visitExpression(ctx.expression());
|
||||
Node statement = visitStatement(ctx.statement());
|
||||
return new IfStatement((IExpression) expression, (IStatement) statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitWhileStmt(DecafParser.WhileStmtContext ctx) {
|
||||
Node expression = visitExpression(ctx.expression());
|
||||
Node statement = visitStatement(ctx.statement());
|
||||
return new WhileStatement((IExpression) expression, (IStatement) statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitEmptyStatement(DecafParser.EmptyStatementContext ctx) {
|
||||
return new EmptyStatement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitStmtExpr(DecafParser.StmtExprContext ctx) {
|
||||
if (ctx.assign() != null) {
|
||||
return visitAssign(ctx.assign());
|
||||
} else if (ctx.methodCall() != null) {
|
||||
return visitMethodCall(ctx.methodCall());
|
||||
} else if (ctx.newDecl() != null) {
|
||||
return visitNewDecl(ctx.newDecl());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitPrint(DecafParser.PrintContext ctx) {
|
||||
return new PrintStatement(ctx.Identifier().getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitAssign(DecafParser.AssignContext ctx) {
|
||||
Node right = visitExpression(ctx.expression());
|
||||
Node left = visitAssignableExpr(ctx.assignableExpr());
|
||||
return new AssignStatementExpression(ctx.Assign().getText(), (IExpression) left, (IExpression) right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitMethodCall(DecafParser.MethodCallContext ctx) {
|
||||
String methodName = ctx.Identifier().getText();
|
||||
List<IExpression> arguments = generateExpressions(ctx.argumentList());
|
||||
List<ReceivingMethod> receivingMethods = new ArrayList<>();
|
||||
for (DecafParser.ReceivingMethodContext receivingMethod : ctx.receivingMethod()) {
|
||||
receivingMethods.add((ReceivingMethod) visit(receivingMethod));
|
||||
}
|
||||
if (ctx.receiver() != null) {
|
||||
Receiver receiver = (Receiver) visit(ctx.receiver());
|
||||
return new MethodCallStatementExpression(methodName, receiver, receivingMethods, arguments);
|
||||
} else {
|
||||
return new MethodCallStatementExpression(methodName, null, receivingMethods, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitReceivingMethod(DecafParser.ReceivingMethodContext ctx) {
|
||||
return new ReceivingMethod(ctx.Identifier().getText(), generateExpressions(ctx.argumentList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitReceiver(DecafParser.ReceiverContext ctx) {
|
||||
if (ctx.This() != null) {
|
||||
return new Receiver(true);
|
||||
} else if (ctx.instVar() != null) {
|
||||
return new Receiver((InstVarExpression) visit(ctx.instVar()));
|
||||
} else if (ctx.newDecl() != null) {
|
||||
return new Receiver((NewStatementExpression) visit(ctx.newDecl()));
|
||||
} else if (ctx.Identifier() != null) {
|
||||
return new Receiver(ctx.Identifier().getText());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitSubReceiver(DecafParser.SubReceiverContext ctx) {
|
||||
if (ctx.This() != null) {
|
||||
return new SubReceiver(true);
|
||||
} else if (ctx.newDecl() != null) {
|
||||
return new SubReceiver((NewStatementExpression) visit(ctx.newDecl()));
|
||||
} else if (ctx.Identifier() != null) {
|
||||
return new SubReceiver(ctx.Identifier().getText());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitNewDecl(DecafParser.NewDeclContext ctx) {
|
||||
String name = ctx.Identifier().getText();
|
||||
List<IExpression> expressions = generateExpressions(ctx.argumentList());
|
||||
return new NewStatementExpression(name, expressions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitExpression(DecafParser.ExpressionContext ctx) {
|
||||
if (ctx.subExpression() != null) {
|
||||
return visitSubExpression(ctx.subExpression());
|
||||
} else if (ctx.binaryExpr() != null) {
|
||||
return visitBinaryExpr(ctx.binaryExpr());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitBinaryExpr(DecafParser.BinaryExprContext ctx) {
|
||||
if (ctx.calcExpr() != null) {
|
||||
return visitCalcExpr(ctx.calcExpr());
|
||||
} else if (ctx.nonCalcExpr() != null) {
|
||||
return visitNonCalcExpr(ctx.nonCalcExpr());
|
||||
} else if (ctx.value() != null) {
|
||||
return visitValue(ctx.value());
|
||||
} else if (ctx.binaryExpr() != null) {
|
||||
IExpression expression = (IExpression) visit(ctx.binaryExpr());
|
||||
return new UnaryExpression("!", expression);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitCalcExpr(DecafParser.CalcExprContext ctx) {
|
||||
if (ctx.calcExpr() != null) {
|
||||
Node left = visitCalcExpr(ctx.calcExpr());
|
||||
Node right = visitDotExpr(ctx.dotExpr());
|
||||
return new BinaryExpression(ctx.LineOperator().getText(), (IExpression) left, (IExpression) right);
|
||||
} else {
|
||||
return visitDotExpr(ctx.dotExpr());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitDotExpr(DecafParser.DotExprContext ctx) {
|
||||
if (ctx.dotExpr() != null) {
|
||||
Node left = visitDotExpr(ctx.dotExpr());
|
||||
Node right = visitDotSubExpr(ctx.dotSubExpr());
|
||||
return new BinaryExpression(ctx.DotOperator().getText(), (IExpression) left, (IExpression) right);
|
||||
} else {
|
||||
return visitDotSubExpr(ctx.dotSubExpr());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitDotSubExpr(DecafParser.DotSubExprContext ctx) {
|
||||
if (ctx.IntValue() != null) {
|
||||
int value = Integer.parseInt(ctx.IntValue().getText());
|
||||
return new IntConstantExpression(value);
|
||||
} else if (ctx.Identifier() != null) {
|
||||
String identifier = ctx.Identifier().getText();
|
||||
return new LocalVarIdentifier(identifier);
|
||||
} else if (ctx.instVar() != null) {
|
||||
return visitInstVar(ctx.instVar());
|
||||
} else if (ctx.methodCall() != null) {
|
||||
return visitMethodCall(ctx.methodCall());
|
||||
} else if (ctx.calcExpr() != null) {
|
||||
return visitCalcExpr(ctx.calcExpr());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitNonCalcExpr(DecafParser.NonCalcExprContext ctx) {
|
||||
String operator;
|
||||
if (ctx.nonCalcOperator().LogicalOpertor() != null) {
|
||||
operator = ctx.nonCalcOperator().LogicalOpertor().getText();
|
||||
} else {
|
||||
operator = ctx.nonCalcOperator().ComparisonOperator().getText();
|
||||
}
|
||||
Node left = visitSubExpression(ctx.subExpression());
|
||||
Node right = visitExpression(ctx.expression());
|
||||
return new BinaryExpression(operator, (IExpression) left, (IExpression) right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitSubExpression(DecafParser.SubExpressionContext ctx) {
|
||||
if (ctx.assignableExpr() != null) {
|
||||
return visitAssignableExpr(ctx.assignableExpr());
|
||||
} else if (ctx.stmtExpr() != null) {
|
||||
return visitStmtExpr(ctx.stmtExpr());
|
||||
} else if (ctx.subExpression() != null) {
|
||||
return visitSubExpression(ctx.subExpression());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitAssignableExpr(DecafParser.AssignableExprContext ctx) {
|
||||
if (ctx.Identifier() != null) {
|
||||
return new LocalVarIdentifier(ctx.Identifier().getText());
|
||||
} else if (ctx.instVar() != null) {
|
||||
return visitInstVar(ctx.instVar());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitInstVar(DecafParser.InstVarContext ctx) {
|
||||
List<SubReceiver> receivers = new ArrayList<>();
|
||||
List<ReceivingMethod> receivingMethods = new ArrayList<>();
|
||||
String fieldName = ctx.Identifier().getText();
|
||||
for (DecafParser.SubReceiverContext subReceiver : ctx.subReceiver()) {
|
||||
receivers.add((SubReceiver) visit(subReceiver));
|
||||
}
|
||||
for (DecafParser.ReceivingMethodContext receivingMethod : ctx.receivingMethod()) {
|
||||
receivingMethods.add((ReceivingMethod) visit(receivingMethod));
|
||||
}
|
||||
return new InstVarExpression(receivers, receivingMethods, fieldName);
|
||||
}
|
||||
|
||||
public List<IExpression> generateExpressions(DecafParser.ArgumentListContext ctx) {
|
||||
List<IExpression> expressions = new ArrayList<>();
|
||||
for (DecafParser.ExpressionContext expressionContext : ctx.expression()) {
|
||||
expressions.add((IExpression) visitExpression(expressionContext));
|
||||
}
|
||||
return expressions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitValue(DecafParser.ValueContext ctx) {
|
||||
if (ctx.IntValue() != null) {
|
||||
return new IntConstantExpression(Integer.parseInt(ctx.IntValue().getText()));
|
||||
} else if (ctx.BooleanValue() != null) {
|
||||
return new BooleanConstantExpression(Boolean.parseBoolean(ctx.BooleanValue().getText()));
|
||||
} else if (ctx.CharValue() != null) {
|
||||
String value = ctx.CharValue().toString();
|
||||
return new CharConstantExpression(value.charAt(1));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getReturnType(List<IStatement> statements) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
139
src/main/java/gen/Decaf.interp
Normal file
139
src/main/java/gen/Decaf.interp
Normal file
File diff suppressed because one or more lines are too long
83
src/main/java/gen/Decaf.tokens
Normal file
83
src/main/java/gen/Decaf.tokens
Normal file
@@ -0,0 +1,83 @@
|
||||
T__0=1
|
||||
BooleanValue=2
|
||||
NullValue=3
|
||||
AccessModifierPublic=4
|
||||
MainMethodDecl=5
|
||||
Void=6
|
||||
Int=7
|
||||
Boolean=8
|
||||
Char=9
|
||||
DotOperator=10
|
||||
LineOperator=11
|
||||
ComparisonOperator=12
|
||||
LogicalOpertor=13
|
||||
Assign=14
|
||||
Minus=15
|
||||
Plus=16
|
||||
Multipilkation=17
|
||||
Division=18
|
||||
Modulo=19
|
||||
Greater=20
|
||||
Less=21
|
||||
GreaterEqual=22
|
||||
LessEqual=23
|
||||
Equal=24
|
||||
NotEqual=25
|
||||
Not=26
|
||||
And=27
|
||||
Or=28
|
||||
Dot=29
|
||||
OpenRoundBracket=30
|
||||
ClosedRoundBracket=31
|
||||
OpenCurlyBracket=32
|
||||
ClosedCurlyBracket=33
|
||||
Semicolon=34
|
||||
Comma=35
|
||||
Class=36
|
||||
This=37
|
||||
While=38
|
||||
If=39
|
||||
Else=40
|
||||
Return=41
|
||||
New=42
|
||||
IntValue=43
|
||||
CharValue=44
|
||||
Identifier=45
|
||||
WS=46
|
||||
'print'=1
|
||||
'null'=3
|
||||
'public'=4
|
||||
'public static void main(String[] args)'=5
|
||||
'void'=6
|
||||
'int'=7
|
||||
'boolean'=8
|
||||
'char'=9
|
||||
'='=14
|
||||
'-'=15
|
||||
'+'=16
|
||||
'*'=17
|
||||
'/'=18
|
||||
'%'=19
|
||||
'>'=20
|
||||
'<'=21
|
||||
'>='=22
|
||||
'<='=23
|
||||
'=='=24
|
||||
'!='=25
|
||||
'!'=26
|
||||
'&&'=27
|
||||
'||'=28
|
||||
'.'=29
|
||||
'('=30
|
||||
')'=31
|
||||
'{'=32
|
||||
'}'=33
|
||||
';'=34
|
||||
','=35
|
||||
'class'=36
|
||||
'this'=37
|
||||
'while'=38
|
||||
'if'=39
|
||||
'else'=40
|
||||
'return'=41
|
||||
'new'=42
|
||||
472
src/main/java/gen/DecafBaseListener.java
Normal file
472
src/main/java/gen/DecafBaseListener.java
Normal file
@@ -0,0 +1,472 @@
|
||||
// Generated from C:/Users/User/DHBW/Compiler/src/main/java/Decaf.g4 by ANTLR 4.13.1
|
||||
package gen;
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.tree.ErrorNode;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
|
||||
/**
|
||||
* This class provides an empty implementation of {@link DecafListener},
|
||||
* which can be extended to create a listener which only needs to handle a subset
|
||||
* of the available methods.
|
||||
*/
|
||||
@SuppressWarnings("CheckReturnValue")
|
||||
public class DecafBaseListener implements DecafListener {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterProgram(DecafParser.ProgramContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitProgram(DecafParser.ProgramContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterClassdecl(DecafParser.ClassdeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitClassdecl(DecafParser.ClassdeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterConstuctorDecl(DecafParser.ConstuctorDeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitConstuctorDecl(DecafParser.ConstuctorDeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterMethodDecl(DecafParser.MethodDeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitMethodDecl(DecafParser.MethodDeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterParameterList(DecafParser.ParameterListContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitParameterList(DecafParser.ParameterListContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterParameter(DecafParser.ParameterContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitParameter(DecafParser.ParameterContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterArgumentList(DecafParser.ArgumentListContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitArgumentList(DecafParser.ArgumentListContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterExpression(DecafParser.ExpressionContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExpression(DecafParser.ExpressionContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterSubExpression(DecafParser.SubExpressionContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitSubExpression(DecafParser.SubExpressionContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterMethodCall(DecafParser.MethodCallContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitMethodCall(DecafParser.MethodCallContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterStatement(DecafParser.StatementContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitStatement(DecafParser.StatementContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterStmtExpr(DecafParser.StmtExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitStmtExpr(DecafParser.StmtExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterAssignableExpr(DecafParser.AssignableExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitAssignableExpr(DecafParser.AssignableExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterSubReceiver(DecafParser.SubReceiverContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitSubReceiver(DecafParser.SubReceiverContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterInstVar(DecafParser.InstVarContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitInstVar(DecafParser.InstVarContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBinaryExpr(DecafParser.BinaryExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBinaryExpr(DecafParser.BinaryExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterCalcExpr(DecafParser.CalcExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitCalcExpr(DecafParser.CalcExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterDotExpr(DecafParser.DotExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitDotExpr(DecafParser.DotExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterDotSubExpr(DecafParser.DotSubExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitDotSubExpr(DecafParser.DotSubExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterNonCalcExpr(DecafParser.NonCalcExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitNonCalcExpr(DecafParser.NonCalcExprContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterNonCalcOperator(DecafParser.NonCalcOperatorContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitNonCalcOperator(DecafParser.NonCalcOperatorContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterReturnStmt(DecafParser.ReturnStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitReturnStmt(DecafParser.ReturnStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterLocalVarDecl(DecafParser.LocalVarDeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitLocalVarDecl(DecafParser.LocalVarDeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBlock(DecafParser.BlockContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBlock(DecafParser.BlockContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterWhileStmt(DecafParser.WhileStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitWhileStmt(DecafParser.WhileStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterIfElseStmt(DecafParser.IfElseStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitIfElseStmt(DecafParser.IfElseStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterIfStmt(DecafParser.IfStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitIfStmt(DecafParser.IfStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterElseStmt(DecafParser.ElseStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitElseStmt(DecafParser.ElseStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterAssign(DecafParser.AssignContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitAssign(DecafParser.AssignContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterNewDecl(DecafParser.NewDeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitNewDecl(DecafParser.NewDeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterReceiver(DecafParser.ReceiverContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitReceiver(DecafParser.ReceiverContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterReceivingMethod(DecafParser.ReceivingMethodContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitReceivingMethod(DecafParser.ReceivingMethodContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterEmptyStatement(DecafParser.EmptyStatementContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitEmptyStatement(DecafParser.EmptyStatementContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterType(DecafParser.TypeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitType(DecafParser.TypeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterValue(DecafParser.ValueContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitValue(DecafParser.ValueContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterPrint(DecafParser.PrintContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitPrint(DecafParser.PrintContext ctx) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterEveryRule(ParserRuleContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitEveryRule(ParserRuleContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void visitTerminal(TerminalNode node) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void visitErrorNode(ErrorNode node) { }
|
||||
}
|
||||
267
src/main/java/gen/DecafBaseVisitor.java
Normal file
267
src/main/java/gen/DecafBaseVisitor.java
Normal file
@@ -0,0 +1,267 @@
|
||||
// Generated from C:/Users/User/DHBW/Compiler/src/main/java/Decaf.g4 by ANTLR 4.13.1
|
||||
package gen;
|
||||
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
|
||||
|
||||
/**
|
||||
* This class provides an empty implementation of {@link DecafVisitor},
|
||||
* which can be extended to create a visitor which only needs to handle a subset
|
||||
* of the available methods.
|
||||
*
|
||||
* @param <T> The return type of the visit operation. Use {@link Void} for
|
||||
* operations with no return type.
|
||||
*/
|
||||
@SuppressWarnings("CheckReturnValue")
|
||||
public class DecafBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements DecafVisitor<T> {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitProgram(DecafParser.ProgramContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitClassdecl(DecafParser.ClassdeclContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitConstuctorDecl(DecafParser.ConstuctorDeclContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitMethodDecl(DecafParser.MethodDeclContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitParameterList(DecafParser.ParameterListContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitParameter(DecafParser.ParameterContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitArgumentList(DecafParser.ArgumentListContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitExpression(DecafParser.ExpressionContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitSubExpression(DecafParser.SubExpressionContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitMethodCall(DecafParser.MethodCallContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitStatement(DecafParser.StatementContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitStmtExpr(DecafParser.StmtExprContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitAssignableExpr(DecafParser.AssignableExprContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitSubReceiver(DecafParser.SubReceiverContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitInstVar(DecafParser.InstVarContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitBinaryExpr(DecafParser.BinaryExprContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitCalcExpr(DecafParser.CalcExprContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitDotExpr(DecafParser.DotExprContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitDotSubExpr(DecafParser.DotSubExprContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitNonCalcExpr(DecafParser.NonCalcExprContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitNonCalcOperator(DecafParser.NonCalcOperatorContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitReturnStmt(DecafParser.ReturnStmtContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitLocalVarDecl(DecafParser.LocalVarDeclContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitBlock(DecafParser.BlockContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitWhileStmt(DecafParser.WhileStmtContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitIfElseStmt(DecafParser.IfElseStmtContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitIfStmt(DecafParser.IfStmtContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitElseStmt(DecafParser.ElseStmtContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitAssign(DecafParser.AssignContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitNewDecl(DecafParser.NewDeclContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitReceiver(DecafParser.ReceiverContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitReceivingMethod(DecafParser.ReceivingMethodContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitEmptyStatement(DecafParser.EmptyStatementContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitType(DecafParser.TypeContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitValue(DecafParser.ValueContext ctx) { return visitChildren(ctx); }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation returns the result of calling
|
||||
* {@link #visitChildren} on {@code ctx}.</p>
|
||||
*/
|
||||
@Override public T visitPrint(DecafParser.PrintContext ctx) { return visitChildren(ctx); }
|
||||
}
|
||||
158
src/main/java/gen/DecafLexer.interp
Normal file
158
src/main/java/gen/DecafLexer.interp
Normal file
File diff suppressed because one or more lines are too long
345
src/main/java/gen/DecafLexer.java
Normal file
345
src/main/java/gen/DecafLexer.java
Normal file
@@ -0,0 +1,345 @@
|
||||
// Generated from C:/Users/User/DHBW/Compiler/src/main/java/Decaf.g4 by ANTLR 4.13.1
|
||||
package gen;
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.TokenStream;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.atn.*;
|
||||
import org.antlr.v4.runtime.dfa.DFA;
|
||||
import org.antlr.v4.runtime.misc.*;
|
||||
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue", "this-escape"})
|
||||
public class DecafLexer extends Lexer {
|
||||
static { RuntimeMetaData.checkVersion("4.13.1", RuntimeMetaData.VERSION); }
|
||||
|
||||
protected static final DFA[] _decisionToDFA;
|
||||
protected static final PredictionContextCache _sharedContextCache =
|
||||
new PredictionContextCache();
|
||||
public static final int
|
||||
T__0=1, BooleanValue=2, NullValue=3, AccessModifierPublic=4, MainMethodDecl=5,
|
||||
Void=6, Int=7, Boolean=8, Char=9, DotOperator=10, LineOperator=11, ComparisonOperator=12,
|
||||
LogicalOpertor=13, Assign=14, Minus=15, Plus=16, Multipilkation=17, Division=18,
|
||||
Modulo=19, Greater=20, Less=21, GreaterEqual=22, LessEqual=23, Equal=24,
|
||||
NotEqual=25, Not=26, And=27, Or=28, Dot=29, OpenRoundBracket=30, ClosedRoundBracket=31,
|
||||
OpenCurlyBracket=32, ClosedCurlyBracket=33, Semicolon=34, Comma=35, Class=36,
|
||||
This=37, While=38, If=39, Else=40, Return=41, New=42, IntValue=43, CharValue=44,
|
||||
Identifier=45, WS=46;
|
||||
public static String[] channelNames = {
|
||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
|
||||
};
|
||||
|
||||
public static String[] modeNames = {
|
||||
"DEFAULT_MODE"
|
||||
};
|
||||
|
||||
private static String[] makeRuleNames() {
|
||||
return new String[] {
|
||||
"T__0", "BooleanValue", "NullValue", "AccessModifierPublic", "MainMethodDecl",
|
||||
"Void", "Int", "Boolean", "Char", "DotOperator", "LineOperator", "ComparisonOperator",
|
||||
"LogicalOpertor", "Assign", "Minus", "Plus", "Multipilkation", "Division",
|
||||
"Modulo", "Greater", "Less", "GreaterEqual", "LessEqual", "Equal", "NotEqual",
|
||||
"Not", "And", "Or", "Dot", "OpenRoundBracket", "ClosedRoundBracket",
|
||||
"OpenCurlyBracket", "ClosedCurlyBracket", "Semicolon", "Comma", "Class",
|
||||
"This", "While", "If", "Else", "Return", "New", "IntValue", "CharValue",
|
||||
"Alpabetic", "Numeric", "ValidIdentSymbols", "Identifier", "WS"
|
||||
};
|
||||
}
|
||||
public static final String[] ruleNames = makeRuleNames();
|
||||
|
||||
private static String[] makeLiteralNames() {
|
||||
return new String[] {
|
||||
null, "'print'", null, "'null'", "'public'", "'public static void main(String[] args)'",
|
||||
"'void'", "'int'", "'boolean'", "'char'", null, null, null, null, "'='",
|
||||
"'-'", "'+'", "'*'", "'/'", "'%'", "'>'", "'<'", "'>='", "'<='", "'=='",
|
||||
"'!='", "'!'", "'&&'", "'||'", "'.'", "'('", "')'", "'{'", "'}'", "';'",
|
||||
"','", "'class'", "'this'", "'while'", "'if'", "'else'", "'return'",
|
||||
"'new'"
|
||||
};
|
||||
}
|
||||
private static final String[] _LITERAL_NAMES = makeLiteralNames();
|
||||
private static String[] makeSymbolicNames() {
|
||||
return new String[] {
|
||||
null, null, "BooleanValue", "NullValue", "AccessModifierPublic", "MainMethodDecl",
|
||||
"Void", "Int", "Boolean", "Char", "DotOperator", "LineOperator", "ComparisonOperator",
|
||||
"LogicalOpertor", "Assign", "Minus", "Plus", "Multipilkation", "Division",
|
||||
"Modulo", "Greater", "Less", "GreaterEqual", "LessEqual", "Equal", "NotEqual",
|
||||
"Not", "And", "Or", "Dot", "OpenRoundBracket", "ClosedRoundBracket",
|
||||
"OpenCurlyBracket", "ClosedCurlyBracket", "Semicolon", "Comma", "Class",
|
||||
"This", "While", "If", "Else", "Return", "New", "IntValue", "CharValue",
|
||||
"Identifier", "WS"
|
||||
};
|
||||
}
|
||||
private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
|
||||
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #VOCABULARY} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String[] tokenNames;
|
||||
static {
|
||||
tokenNames = new String[_SYMBOLIC_NAMES.length];
|
||||
for (int i = 0; i < tokenNames.length; i++) {
|
||||
tokenNames[i] = VOCABULARY.getLiteralName(i);
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = VOCABULARY.getSymbolicName(i);
|
||||
}
|
||||
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = "<INVALID>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String[] getTokenNames() {
|
||||
return tokenNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public Vocabulary getVocabulary() {
|
||||
return VOCABULARY;
|
||||
}
|
||||
|
||||
|
||||
public DecafLexer(CharStream input) {
|
||||
super(input);
|
||||
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGrammarFileName() { return "Decaf.g4"; }
|
||||
|
||||
@Override
|
||||
public String[] getRuleNames() { return ruleNames; }
|
||||
|
||||
@Override
|
||||
public String getSerializedATN() { return _serializedATN; }
|
||||
|
||||
@Override
|
||||
public String[] getChannelNames() { return channelNames; }
|
||||
|
||||
@Override
|
||||
public String[] getModeNames() { return modeNames; }
|
||||
|
||||
@Override
|
||||
public ATN getATN() { return _ATN; }
|
||||
|
||||
public static final String _serializedATN =
|
||||
"\u0004\u0000.\u014d\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002\u0001"+
|
||||
"\u0007\u0001\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004"+
|
||||
"\u0007\u0004\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007"+
|
||||
"\u0007\u0007\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b"+
|
||||
"\u0007\u000b\u0002\f\u0007\f\u0002\r\u0007\r\u0002\u000e\u0007\u000e\u0002"+
|
||||
"\u000f\u0007\u000f\u0002\u0010\u0007\u0010\u0002\u0011\u0007\u0011\u0002"+
|
||||
"\u0012\u0007\u0012\u0002\u0013\u0007\u0013\u0002\u0014\u0007\u0014\u0002"+
|
||||
"\u0015\u0007\u0015\u0002\u0016\u0007\u0016\u0002\u0017\u0007\u0017\u0002"+
|
||||
"\u0018\u0007\u0018\u0002\u0019\u0007\u0019\u0002\u001a\u0007\u001a\u0002"+
|
||||
"\u001b\u0007\u001b\u0002\u001c\u0007\u001c\u0002\u001d\u0007\u001d\u0002"+
|
||||
"\u001e\u0007\u001e\u0002\u001f\u0007\u001f\u0002 \u0007 \u0002!\u0007"+
|
||||
"!\u0002\"\u0007\"\u0002#\u0007#\u0002$\u0007$\u0002%\u0007%\u0002&\u0007"+
|
||||
"&\u0002\'\u0007\'\u0002(\u0007(\u0002)\u0007)\u0002*\u0007*\u0002+\u0007"+
|
||||
"+\u0002,\u0007,\u0002-\u0007-\u0002.\u0007.\u0002/\u0007/\u00020\u0007"+
|
||||
"0\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0000"+
|
||||
"\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+
|
||||
"\u0001\u0001\u0001\u0001\u0001\u0001\u0003\u0001s\b\u0001\u0001\u0002"+
|
||||
"\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0003\u0001\u0003"+
|
||||
"\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004"+
|
||||
"\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005"+
|
||||
"\u0001\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0007"+
|
||||
"\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007"+
|
||||
"\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\t\u0001\t\u0001"+
|
||||
"\t\u0003\t\u00c1\b\t\u0001\n\u0001\n\u0003\n\u00c5\b\n\u0001\u000b\u0001"+
|
||||
"\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0001\u000b\u0003\u000b\u00cd"+
|
||||
"\b\u000b\u0001\f\u0001\f\u0003\f\u00d1\b\f\u0001\r\u0001\r\u0001\u000e"+
|
||||
"\u0001\u000e\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0001\u0011"+
|
||||
"\u0001\u0011\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013\u0001\u0014"+
|
||||
"\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0016\u0001\u0016"+
|
||||
"\u0001\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0018\u0001\u0018"+
|
||||
"\u0001\u0018\u0001\u0019\u0001\u0019\u0001\u001a\u0001\u001a\u0001\u001a"+
|
||||
"\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001\u001d"+
|
||||
"\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f\u0001 \u0001"+
|
||||
" \u0001!\u0001!\u0001\"\u0001\"\u0001#\u0001#\u0001#\u0001#\u0001#\u0001"+
|
||||
"#\u0001$\u0001$\u0001$\u0001$\u0001$\u0001%\u0001%\u0001%\u0001%\u0001"+
|
||||
"%\u0001%\u0001&\u0001&\u0001&\u0001\'\u0001\'\u0001\'\u0001\'\u0001\'"+
|
||||
"\u0001(\u0001(\u0001(\u0001(\u0001(\u0001(\u0001(\u0001)\u0001)\u0001"+
|
||||
")\u0001)\u0001*\u0005*\u012a\b*\n*\f*\u012d\t*\u0001*\u0004*\u0130\b*"+
|
||||
"\u000b*\f*\u0131\u0001+\u0001+\u0003+\u0136\b+\u0001+\u0001+\u0001,\u0001"+
|
||||
",\u0001-\u0001-\u0001.\u0001.\u0001.\u0003.\u0141\b.\u0001/\u0001/\u0005"+
|
||||
"/\u0145\b/\n/\f/\u0148\t/\u00010\u00010\u00010\u00010\u0000\u00001\u0001"+
|
||||
"\u0001\u0003\u0002\u0005\u0003\u0007\u0004\t\u0005\u000b\u0006\r\u0007"+
|
||||
"\u000f\b\u0011\t\u0013\n\u0015\u000b\u0017\f\u0019\r\u001b\u000e\u001d"+
|
||||
"\u000f\u001f\u0010!\u0011#\u0012%\u0013\'\u0014)\u0015+\u0016-\u0017/"+
|
||||
"\u00181\u00193\u001a5\u001b7\u001c9\u001d;\u001e=\u001f? A!C\"E#G$I%K"+
|
||||
"&M\'O(Q)S*U+W,Y\u0000[\u0000]\u0000_-a.\u0001\u0000\u0006\u0002\u0000"+
|
||||
"++--\u0001\u000009\u0002\u0000\n\n\r\r\u0002\u0000AZaz\u0002\u0000$$_"+
|
||||
"_\u0003\u0000\t\n\r\r \u0159\u0000\u0001\u0001\u0000\u0000\u0000\u0000"+
|
||||
"\u0003\u0001\u0000\u0000\u0000\u0000\u0005\u0001\u0000\u0000\u0000\u0000"+
|
||||
"\u0007\u0001\u0000\u0000\u0000\u0000\t\u0001\u0000\u0000\u0000\u0000\u000b"+
|
||||
"\u0001\u0000\u0000\u0000\u0000\r\u0001\u0000\u0000\u0000\u0000\u000f\u0001"+
|
||||
"\u0000\u0000\u0000\u0000\u0011\u0001\u0000\u0000\u0000\u0000\u0013\u0001"+
|
||||
"\u0000\u0000\u0000\u0000\u0015\u0001\u0000\u0000\u0000\u0000\u0017\u0001"+
|
||||
"\u0000\u0000\u0000\u0000\u0019\u0001\u0000\u0000\u0000\u0000\u001b\u0001"+
|
||||
"\u0000\u0000\u0000\u0000\u001d\u0001\u0000\u0000\u0000\u0000\u001f\u0001"+
|
||||
"\u0000\u0000\u0000\u0000!\u0001\u0000\u0000\u0000\u0000#\u0001\u0000\u0000"+
|
||||
"\u0000\u0000%\u0001\u0000\u0000\u0000\u0000\'\u0001\u0000\u0000\u0000"+
|
||||
"\u0000)\u0001\u0000\u0000\u0000\u0000+\u0001\u0000\u0000\u0000\u0000-"+
|
||||
"\u0001\u0000\u0000\u0000\u0000/\u0001\u0000\u0000\u0000\u00001\u0001\u0000"+
|
||||
"\u0000\u0000\u00003\u0001\u0000\u0000\u0000\u00005\u0001\u0000\u0000\u0000"+
|
||||
"\u00007\u0001\u0000\u0000\u0000\u00009\u0001\u0000\u0000\u0000\u0000;"+
|
||||
"\u0001\u0000\u0000\u0000\u0000=\u0001\u0000\u0000\u0000\u0000?\u0001\u0000"+
|
||||
"\u0000\u0000\u0000A\u0001\u0000\u0000\u0000\u0000C\u0001\u0000\u0000\u0000"+
|
||||
"\u0000E\u0001\u0000\u0000\u0000\u0000G\u0001\u0000\u0000\u0000\u0000I"+
|
||||
"\u0001\u0000\u0000\u0000\u0000K\u0001\u0000\u0000\u0000\u0000M\u0001\u0000"+
|
||||
"\u0000\u0000\u0000O\u0001\u0000\u0000\u0000\u0000Q\u0001\u0000\u0000\u0000"+
|
||||
"\u0000S\u0001\u0000\u0000\u0000\u0000U\u0001\u0000\u0000\u0000\u0000W"+
|
||||
"\u0001\u0000\u0000\u0000\u0000_\u0001\u0000\u0000\u0000\u0000a\u0001\u0000"+
|
||||
"\u0000\u0000\u0001c\u0001\u0000\u0000\u0000\u0003r\u0001\u0000\u0000\u0000"+
|
||||
"\u0005t\u0001\u0000\u0000\u0000\u0007y\u0001\u0000\u0000\u0000\t\u0080"+
|
||||
"\u0001\u0000\u0000\u0000\u000b\u00a7\u0001\u0000\u0000\u0000\r\u00ac\u0001"+
|
||||
"\u0000\u0000\u0000\u000f\u00b0\u0001\u0000\u0000\u0000\u0011\u00b8\u0001"+
|
||||
"\u0000\u0000\u0000\u0013\u00c0\u0001\u0000\u0000\u0000\u0015\u00c4\u0001"+
|
||||
"\u0000\u0000\u0000\u0017\u00cc\u0001\u0000\u0000\u0000\u0019\u00d0\u0001"+
|
||||
"\u0000\u0000\u0000\u001b\u00d2\u0001\u0000\u0000\u0000\u001d\u00d4\u0001"+
|
||||
"\u0000\u0000\u0000\u001f\u00d6\u0001\u0000\u0000\u0000!\u00d8\u0001\u0000"+
|
||||
"\u0000\u0000#\u00da\u0001\u0000\u0000\u0000%\u00dc\u0001\u0000\u0000\u0000"+
|
||||
"\'\u00de\u0001\u0000\u0000\u0000)\u00e0\u0001\u0000\u0000\u0000+\u00e2"+
|
||||
"\u0001\u0000\u0000\u0000-\u00e5\u0001\u0000\u0000\u0000/\u00e8\u0001\u0000"+
|
||||
"\u0000\u00001\u00eb\u0001\u0000\u0000\u00003\u00ee\u0001\u0000\u0000\u0000"+
|
||||
"5\u00f0\u0001\u0000\u0000\u00007\u00f3\u0001\u0000\u0000\u00009\u00f6"+
|
||||
"\u0001\u0000\u0000\u0000;\u00f8\u0001\u0000\u0000\u0000=\u00fa\u0001\u0000"+
|
||||
"\u0000\u0000?\u00fc\u0001\u0000\u0000\u0000A\u00fe\u0001\u0000\u0000\u0000"+
|
||||
"C\u0100\u0001\u0000\u0000\u0000E\u0102\u0001\u0000\u0000\u0000G\u0104"+
|
||||
"\u0001\u0000\u0000\u0000I\u010a\u0001\u0000\u0000\u0000K\u010f\u0001\u0000"+
|
||||
"\u0000\u0000M\u0115\u0001\u0000\u0000\u0000O\u0118\u0001\u0000\u0000\u0000"+
|
||||
"Q\u011d\u0001\u0000\u0000\u0000S\u0124\u0001\u0000\u0000\u0000U\u012b"+
|
||||
"\u0001\u0000\u0000\u0000W\u0133\u0001\u0000\u0000\u0000Y\u0139\u0001\u0000"+
|
||||
"\u0000\u0000[\u013b\u0001\u0000\u0000\u0000]\u0140\u0001\u0000\u0000\u0000"+
|
||||
"_\u0142\u0001\u0000\u0000\u0000a\u0149\u0001\u0000\u0000\u0000cd\u0005"+
|
||||
"p\u0000\u0000de\u0005r\u0000\u0000ef\u0005i\u0000\u0000fg\u0005n\u0000"+
|
||||
"\u0000gh\u0005t\u0000\u0000h\u0002\u0001\u0000\u0000\u0000ij\u0005t\u0000"+
|
||||
"\u0000jk\u0005r\u0000\u0000kl\u0005u\u0000\u0000ls\u0005e\u0000\u0000"+
|
||||
"mn\u0005f\u0000\u0000no\u0005a\u0000\u0000op\u0005l\u0000\u0000pq\u0005"+
|
||||
"s\u0000\u0000qs\u0005e\u0000\u0000ri\u0001\u0000\u0000\u0000rm\u0001\u0000"+
|
||||
"\u0000\u0000s\u0004\u0001\u0000\u0000\u0000tu\u0005n\u0000\u0000uv\u0005"+
|
||||
"u\u0000\u0000vw\u0005l\u0000\u0000wx\u0005l\u0000\u0000x\u0006\u0001\u0000"+
|
||||
"\u0000\u0000yz\u0005p\u0000\u0000z{\u0005u\u0000\u0000{|\u0005b\u0000"+
|
||||
"\u0000|}\u0005l\u0000\u0000}~\u0005i\u0000\u0000~\u007f\u0005c\u0000\u0000"+
|
||||
"\u007f\b\u0001\u0000\u0000\u0000\u0080\u0081\u0005p\u0000\u0000\u0081"+
|
||||
"\u0082\u0005u\u0000\u0000\u0082\u0083\u0005b\u0000\u0000\u0083\u0084\u0005"+
|
||||
"l\u0000\u0000\u0084\u0085\u0005i\u0000\u0000\u0085\u0086\u0005c\u0000"+
|
||||
"\u0000\u0086\u0087\u0005 \u0000\u0000\u0087\u0088\u0005s\u0000\u0000\u0088"+
|
||||
"\u0089\u0005t\u0000\u0000\u0089\u008a\u0005a\u0000\u0000\u008a\u008b\u0005"+
|
||||
"t\u0000\u0000\u008b\u008c\u0005i\u0000\u0000\u008c\u008d\u0005c\u0000"+
|
||||
"\u0000\u008d\u008e\u0005 \u0000\u0000\u008e\u008f\u0005v\u0000\u0000\u008f"+
|
||||
"\u0090\u0005o\u0000\u0000\u0090\u0091\u0005i\u0000\u0000\u0091\u0092\u0005"+
|
||||
"d\u0000\u0000\u0092\u0093\u0005 \u0000\u0000\u0093\u0094\u0005m\u0000"+
|
||||
"\u0000\u0094\u0095\u0005a\u0000\u0000\u0095\u0096\u0005i\u0000\u0000\u0096"+
|
||||
"\u0097\u0005n\u0000\u0000\u0097\u0098\u0005(\u0000\u0000\u0098\u0099\u0005"+
|
||||
"S\u0000\u0000\u0099\u009a\u0005t\u0000\u0000\u009a\u009b\u0005r\u0000"+
|
||||
"\u0000\u009b\u009c\u0005i\u0000\u0000\u009c\u009d\u0005n\u0000\u0000\u009d"+
|
||||
"\u009e\u0005g\u0000\u0000\u009e\u009f\u0005[\u0000\u0000\u009f\u00a0\u0005"+
|
||||
"]\u0000\u0000\u00a0\u00a1\u0005 \u0000\u0000\u00a1\u00a2\u0005a\u0000"+
|
||||
"\u0000\u00a2\u00a3\u0005r\u0000\u0000\u00a3\u00a4\u0005g\u0000\u0000\u00a4"+
|
||||
"\u00a5\u0005s\u0000\u0000\u00a5\u00a6\u0005)\u0000\u0000\u00a6\n\u0001"+
|
||||
"\u0000\u0000\u0000\u00a7\u00a8\u0005v\u0000\u0000\u00a8\u00a9\u0005o\u0000"+
|
||||
"\u0000\u00a9\u00aa\u0005i\u0000\u0000\u00aa\u00ab\u0005d\u0000\u0000\u00ab"+
|
||||
"\f\u0001\u0000\u0000\u0000\u00ac\u00ad\u0005i\u0000\u0000\u00ad\u00ae"+
|
||||
"\u0005n\u0000\u0000\u00ae\u00af\u0005t\u0000\u0000\u00af\u000e\u0001\u0000"+
|
||||
"\u0000\u0000\u00b0\u00b1\u0005b\u0000\u0000\u00b1\u00b2\u0005o\u0000\u0000"+
|
||||
"\u00b2\u00b3\u0005o\u0000\u0000\u00b3\u00b4\u0005l\u0000\u0000\u00b4\u00b5"+
|
||||
"\u0005e\u0000\u0000\u00b5\u00b6\u0005a\u0000\u0000\u00b6\u00b7\u0005n"+
|
||||
"\u0000\u0000\u00b7\u0010\u0001\u0000\u0000\u0000\u00b8\u00b9\u0005c\u0000"+
|
||||
"\u0000\u00b9\u00ba\u0005h\u0000\u0000\u00ba\u00bb\u0005a\u0000\u0000\u00bb"+
|
||||
"\u00bc\u0005r\u0000\u0000\u00bc\u0012\u0001\u0000\u0000\u0000\u00bd\u00c1"+
|
||||
"\u0003!\u0010\u0000\u00be\u00c1\u0003#\u0011\u0000\u00bf\u00c1\u0003%"+
|
||||
"\u0012\u0000\u00c0\u00bd\u0001\u0000\u0000\u0000\u00c0\u00be\u0001\u0000"+
|
||||
"\u0000\u0000\u00c0\u00bf\u0001\u0000\u0000\u0000\u00c1\u0014\u0001\u0000"+
|
||||
"\u0000\u0000\u00c2\u00c5\u0003\u001f\u000f\u0000\u00c3\u00c5\u0003\u001d"+
|
||||
"\u000e\u0000\u00c4\u00c2\u0001\u0000\u0000\u0000\u00c4\u00c3\u0001\u0000"+
|
||||
"\u0000\u0000\u00c5\u0016\u0001\u0000\u0000\u0000\u00c6\u00cd\u0003\'\u0013"+
|
||||
"\u0000\u00c7\u00cd\u0003)\u0014\u0000\u00c8\u00cd\u0003+\u0015\u0000\u00c9"+
|
||||
"\u00cd\u0003-\u0016\u0000\u00ca\u00cd\u0003/\u0017\u0000\u00cb\u00cd\u0003"+
|
||||
"1\u0018\u0000\u00cc\u00c6\u0001\u0000\u0000\u0000\u00cc\u00c7\u0001\u0000"+
|
||||
"\u0000\u0000\u00cc\u00c8\u0001\u0000\u0000\u0000\u00cc\u00c9\u0001\u0000"+
|
||||
"\u0000\u0000\u00cc\u00ca\u0001\u0000\u0000\u0000\u00cc\u00cb\u0001\u0000"+
|
||||
"\u0000\u0000\u00cd\u0018\u0001\u0000\u0000\u0000\u00ce\u00d1\u00035\u001a"+
|
||||
"\u0000\u00cf\u00d1\u00037\u001b\u0000\u00d0\u00ce\u0001\u0000\u0000\u0000"+
|
||||
"\u00d0\u00cf\u0001\u0000\u0000\u0000\u00d1\u001a\u0001\u0000\u0000\u0000"+
|
||||
"\u00d2\u00d3\u0005=\u0000\u0000\u00d3\u001c\u0001\u0000\u0000\u0000\u00d4"+
|
||||
"\u00d5\u0005-\u0000\u0000\u00d5\u001e\u0001\u0000\u0000\u0000\u00d6\u00d7"+
|
||||
"\u0005+\u0000\u0000\u00d7 \u0001\u0000\u0000\u0000\u00d8\u00d9\u0005*"+
|
||||
"\u0000\u0000\u00d9\"\u0001\u0000\u0000\u0000\u00da\u00db\u0005/\u0000"+
|
||||
"\u0000\u00db$\u0001\u0000\u0000\u0000\u00dc\u00dd\u0005%\u0000\u0000\u00dd"+
|
||||
"&\u0001\u0000\u0000\u0000\u00de\u00df\u0005>\u0000\u0000\u00df(\u0001"+
|
||||
"\u0000\u0000\u0000\u00e0\u00e1\u0005<\u0000\u0000\u00e1*\u0001\u0000\u0000"+
|
||||
"\u0000\u00e2\u00e3\u0005>\u0000\u0000\u00e3\u00e4\u0005=\u0000\u0000\u00e4"+
|
||||
",\u0001\u0000\u0000\u0000\u00e5\u00e6\u0005<\u0000\u0000\u00e6\u00e7\u0005"+
|
||||
"=\u0000\u0000\u00e7.\u0001\u0000\u0000\u0000\u00e8\u00e9\u0005=\u0000"+
|
||||
"\u0000\u00e9\u00ea\u0005=\u0000\u0000\u00ea0\u0001\u0000\u0000\u0000\u00eb"+
|
||||
"\u00ec\u0005!\u0000\u0000\u00ec\u00ed\u0005=\u0000\u0000\u00ed2\u0001"+
|
||||
"\u0000\u0000\u0000\u00ee\u00ef\u0005!\u0000\u0000\u00ef4\u0001\u0000\u0000"+
|
||||
"\u0000\u00f0\u00f1\u0005&\u0000\u0000\u00f1\u00f2\u0005&\u0000\u0000\u00f2"+
|
||||
"6\u0001\u0000\u0000\u0000\u00f3\u00f4\u0005|\u0000\u0000\u00f4\u00f5\u0005"+
|
||||
"|\u0000\u0000\u00f58\u0001\u0000\u0000\u0000\u00f6\u00f7\u0005.\u0000"+
|
||||
"\u0000\u00f7:\u0001\u0000\u0000\u0000\u00f8\u00f9\u0005(\u0000\u0000\u00f9"+
|
||||
"<\u0001\u0000\u0000\u0000\u00fa\u00fb\u0005)\u0000\u0000\u00fb>\u0001"+
|
||||
"\u0000\u0000\u0000\u00fc\u00fd\u0005{\u0000\u0000\u00fd@\u0001\u0000\u0000"+
|
||||
"\u0000\u00fe\u00ff\u0005}\u0000\u0000\u00ffB\u0001\u0000\u0000\u0000\u0100"+
|
||||
"\u0101\u0005;\u0000\u0000\u0101D\u0001\u0000\u0000\u0000\u0102\u0103\u0005"+
|
||||
",\u0000\u0000\u0103F\u0001\u0000\u0000\u0000\u0104\u0105\u0005c\u0000"+
|
||||
"\u0000\u0105\u0106\u0005l\u0000\u0000\u0106\u0107\u0005a\u0000\u0000\u0107"+
|
||||
"\u0108\u0005s\u0000\u0000\u0108\u0109\u0005s\u0000\u0000\u0109H\u0001"+
|
||||
"\u0000\u0000\u0000\u010a\u010b\u0005t\u0000\u0000\u010b\u010c\u0005h\u0000"+
|
||||
"\u0000\u010c\u010d\u0005i\u0000\u0000\u010d\u010e\u0005s\u0000\u0000\u010e"+
|
||||
"J\u0001\u0000\u0000\u0000\u010f\u0110\u0005w\u0000\u0000\u0110\u0111\u0005"+
|
||||
"h\u0000\u0000\u0111\u0112\u0005i\u0000\u0000\u0112\u0113\u0005l\u0000"+
|
||||
"\u0000\u0113\u0114\u0005e\u0000\u0000\u0114L\u0001\u0000\u0000\u0000\u0115"+
|
||||
"\u0116\u0005i\u0000\u0000\u0116\u0117\u0005f\u0000\u0000\u0117N\u0001"+
|
||||
"\u0000\u0000\u0000\u0118\u0119\u0005e\u0000\u0000\u0119\u011a\u0005l\u0000"+
|
||||
"\u0000\u011a\u011b\u0005s\u0000\u0000\u011b\u011c\u0005e\u0000\u0000\u011c"+
|
||||
"P\u0001\u0000\u0000\u0000\u011d\u011e\u0005r\u0000\u0000\u011e\u011f\u0005"+
|
||||
"e\u0000\u0000\u011f\u0120\u0005t\u0000\u0000\u0120\u0121\u0005u\u0000"+
|
||||
"\u0000\u0121\u0122\u0005r\u0000\u0000\u0122\u0123\u0005n\u0000\u0000\u0123"+
|
||||
"R\u0001\u0000\u0000\u0000\u0124\u0125\u0005n\u0000\u0000\u0125\u0126\u0005"+
|
||||
"e\u0000\u0000\u0126\u0127\u0005w\u0000\u0000\u0127T\u0001\u0000\u0000"+
|
||||
"\u0000\u0128\u012a\u0007\u0000\u0000\u0000\u0129\u0128\u0001\u0000\u0000"+
|
||||
"\u0000\u012a\u012d\u0001\u0000\u0000\u0000\u012b\u0129\u0001\u0000\u0000"+
|
||||
"\u0000\u012b\u012c\u0001\u0000\u0000\u0000\u012c\u012f\u0001\u0000\u0000"+
|
||||
"\u0000\u012d\u012b\u0001\u0000\u0000\u0000\u012e\u0130\u0007\u0001\u0000"+
|
||||
"\u0000\u012f\u012e\u0001\u0000\u0000\u0000\u0130\u0131\u0001\u0000\u0000"+
|
||||
"\u0000\u0131\u012f\u0001\u0000\u0000\u0000\u0131\u0132\u0001\u0000\u0000"+
|
||||
"\u0000\u0132V\u0001\u0000\u0000\u0000\u0133\u0135\u0005\'\u0000\u0000"+
|
||||
"\u0134\u0136\b\u0002\u0000\u0000\u0135\u0134\u0001\u0000\u0000\u0000\u0135"+
|
||||
"\u0136\u0001\u0000\u0000\u0000\u0136\u0137\u0001\u0000\u0000\u0000\u0137"+
|
||||
"\u0138\u0005\'\u0000\u0000\u0138X\u0001\u0000\u0000\u0000\u0139\u013a"+
|
||||
"\u0007\u0003\u0000\u0000\u013aZ\u0001\u0000\u0000\u0000\u013b\u013c\u0007"+
|
||||
"\u0001\u0000\u0000\u013c\\\u0001\u0000\u0000\u0000\u013d\u0141\u0003Y"+
|
||||
",\u0000\u013e\u0141\u0003[-\u0000\u013f\u0141\u0007\u0004\u0000\u0000"+
|
||||
"\u0140\u013d\u0001\u0000\u0000\u0000\u0140\u013e\u0001\u0000\u0000\u0000"+
|
||||
"\u0140\u013f\u0001\u0000\u0000\u0000\u0141^\u0001\u0000\u0000\u0000\u0142"+
|
||||
"\u0146\u0003Y,\u0000\u0143\u0145\u0003].\u0000\u0144\u0143\u0001\u0000"+
|
||||
"\u0000\u0000\u0145\u0148\u0001\u0000\u0000\u0000\u0146\u0144\u0001\u0000"+
|
||||
"\u0000\u0000\u0146\u0147\u0001\u0000\u0000\u0000\u0147`\u0001\u0000\u0000"+
|
||||
"\u0000\u0148\u0146\u0001\u0000\u0000\u0000\u0149\u014a\u0007\u0005\u0000"+
|
||||
"\u0000\u014a\u014b\u0001\u0000\u0000\u0000\u014b\u014c\u00060\u0000\u0000"+
|
||||
"\u014cb\u0001\u0000\u0000\u0000\u000b\u0000r\u00c0\u00c4\u00cc\u00d0\u012b"+
|
||||
"\u0131\u0135\u0140\u0146\u0001\u0006\u0000\u0000";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
|
||||
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
|
||||
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
83
src/main/java/gen/DecafLexer.tokens
Normal file
83
src/main/java/gen/DecafLexer.tokens
Normal file
@@ -0,0 +1,83 @@
|
||||
T__0=1
|
||||
BooleanValue=2
|
||||
NullValue=3
|
||||
AccessModifierPublic=4
|
||||
MainMethodDecl=5
|
||||
Void=6
|
||||
Int=7
|
||||
Boolean=8
|
||||
Char=9
|
||||
DotOperator=10
|
||||
LineOperator=11
|
||||
ComparisonOperator=12
|
||||
LogicalOpertor=13
|
||||
Assign=14
|
||||
Minus=15
|
||||
Plus=16
|
||||
Multipilkation=17
|
||||
Division=18
|
||||
Modulo=19
|
||||
Greater=20
|
||||
Less=21
|
||||
GreaterEqual=22
|
||||
LessEqual=23
|
||||
Equal=24
|
||||
NotEqual=25
|
||||
Not=26
|
||||
And=27
|
||||
Or=28
|
||||
Dot=29
|
||||
OpenRoundBracket=30
|
||||
ClosedRoundBracket=31
|
||||
OpenCurlyBracket=32
|
||||
ClosedCurlyBracket=33
|
||||
Semicolon=34
|
||||
Comma=35
|
||||
Class=36
|
||||
This=37
|
||||
While=38
|
||||
If=39
|
||||
Else=40
|
||||
Return=41
|
||||
New=42
|
||||
IntValue=43
|
||||
CharValue=44
|
||||
Identifier=45
|
||||
WS=46
|
||||
'print'=1
|
||||
'null'=3
|
||||
'public'=4
|
||||
'public static void main(String[] args)'=5
|
||||
'void'=6
|
||||
'int'=7
|
||||
'boolean'=8
|
||||
'char'=9
|
||||
'='=14
|
||||
'-'=15
|
||||
'+'=16
|
||||
'*'=17
|
||||
'/'=18
|
||||
'%'=19
|
||||
'>'=20
|
||||
'<'=21
|
||||
'>='=22
|
||||
'<='=23
|
||||
'=='=24
|
||||
'!='=25
|
||||
'!'=26
|
||||
'&&'=27
|
||||
'||'=28
|
||||
'.'=29
|
||||
'('=30
|
||||
')'=31
|
||||
'{'=32
|
||||
'}'=33
|
||||
';'=34
|
||||
','=35
|
||||
'class'=36
|
||||
'this'=37
|
||||
'while'=38
|
||||
'if'=39
|
||||
'else'=40
|
||||
'return'=41
|
||||
'new'=42
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user