Compare commits

...

254 Commits

Author SHA1 Message Date
Krauß, Josefine
22d925810f removing redundant file 2024-07-05 15:36:01 +02:00
Krauß, Josefine
b4f59ce5c3 adding presentation 2024-07-05 15:33:55 +02:00
Krauß, Josefine
5239e608bc Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell 2024-07-05 15:32:43 +02:00
Krauß, Josefine
079668b9f8 adding presentation 2024-07-05 15:32:14 +02:00
Jochen Seyfried
58f6dc74e4 Merge remote-tracking branch 'origin/master' 2024-07-05 12:38:12 +02:00
Jochen Seyfried
88ce2a985c Updated Class diagrams 2024-07-05 12:37:44 +02:00
KingJulian
a2fa6f55d4 Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell 2024-07-05 12:36:49 +02:00
KingJulian
8d4e8a9269 Moved DivTest 2024-07-05 12:36:10 +02:00
c2c0c0b442 Dateien nach "/" hochladen
Without Methods
2024-07-05 10:29:41 +00:00
KingJulian
ec400479bb Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell 2024-07-05 12:29:41 +02:00
167b8e80b5 Dateien nach "/" hochladen
Klassendiagramm
2024-07-05 09:54:06 +00:00
Krauß, Josefine
0baac36f35 Merge remote-tracking branch 'origin/master' 2024-07-05 11:51:56 +02:00
Krauß, Josefine
da53e5d6dc deleting corrupt output.jar 2024-07-05 11:51:33 +02:00
KingJulian
0593d988b4 Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell 2024-07-05 11:31:54 +02:00
KingJulian
8e55eaca93 Test update 2024-07-05 11:31:25 +02:00
Jochen Seyfried
31ac237ffd Updated README 2024-07-05 11:09:20 +02:00
Jochen Seyfried
e56139080f Merge remote-tracking branch 'origin/master' 2024-07-05 11:04:28 +02:00
Jochen Seyfried
f807721293 Added Documentation PDF 2024-07-05 11:04:12 +02:00
Krauß, Josefine
271bbf4b4b new jar after bugfix 2024-07-05 10:56:53 +02:00
Jochen Seyfried
5b4d08ba01 bugfix 2024-07-05 10:54:43 +02:00
Krauß, Josefine
3b5f157bb5 initial jar commit 2024-07-04 19:36:03 +02:00
Jochen Seyfried
59183f5b44 Deleted SuperStatementExpression.java 2024-07-04 19:01:43 +02:00
Jochen Seyfried
302b907d36 Code cleanup
Deleted imports and comments, fixed warnings and typos
2024-07-04 19:00:28 +02:00
Jochen Seyfried
32353b9a37 Second step of codeGen refactoring in which other methods were refactored to use the methods in CodeGenHelper 2024-07-04 18:48:34 +02:00
Jochen Seyfried
3e908293ee First step of code cleanup and refactoring.
Moved the localVarIndex setters into a separate helperClass and optimized bytecodesize in regard to variable pushes
2024-07-04 18:37:54 +02:00
Krauß, Josefine
aed7af7c68 Merge remote-tracking branch 'origin/master' 2024-07-04 18:11:18 +02:00
Krauß, Josefine
3a8b9ea9cd missing thisclass 2024-07-04 18:11:02 +02:00
Jochen Seyfried
aa8a647fa1 Deleted .class Files and added Directory 2024-07-04 15:56:18 +02:00
KingJulian
51240806b9 Test update 2024-07-04 15:50:04 +02:00
Jochen Seyfried
8f55a15aef Fixed chained instVar calls in AssignStatementExpression 2024-07-04 15:40:07 +02:00
edfaa93980 readme should link docu as soon as commited 2024-07-04 12:37:37 +00:00
Julian Murek
4b36453ff3 Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell 2024-07-04 13:36:16 +02:00
Julian Murek
78d6d402a2 Test update 2024-07-04 13:36:05 +02:00
Krauß, Josefine
0533ddbc5d refactoring 2024-07-04 11:57:49 +02:00
Krauß, Josefine
920fa2fa48 fixed wrong exception type 2024-07-04 11:10:14 +02:00
Krauß, Josefine
dbb61e2a81 update example file 2024-07-04 11:07:22 +02:00
Krauß, Josefine
7fb7cea2f7 example files for presentation 2024-07-04 11:04:33 +02:00
Krauß, Josefine
7e8c297d9a Merge remote-tracking branch 'origin/master' 2024-07-04 10:21:43 +02:00
Krauß, Josefine
c9ce9e02db compiler code for jar 2024-07-04 10:21:32 +02:00
Jochen Seyfried
4dfea0d69d Added Fakultaet.java as a Example for friday 2024-07-04 10:09:59 +02:00
Jochen Seyfried
e801717444 Print now can print fields of thisClass 2024-07-04 10:04:31 +02:00
David Mueller
6a56f51050 Vorzeichen Patch 2024-07-04 09:32:00 +02:00
403b31c550 format ASTGenerator 2024-07-04 09:17:34 +02:00
Jochen Seyfried
82384886c6 Added missing thisClass setters as already discussed during the meeting.
Also fixed chaining of InstVar and the bugs it created in MethodCallStatementExpression
2024-07-03 20:56:01 +02:00
Julian Murek
1dd405a00f Test update 2024-07-03 17:32:49 +02:00
6948797001 bugfix return 2024-07-03 15:18:53 +02:00
Julian Murek
d7016df1ba Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell 2024-07-03 14:48:46 +02:00
Julian Murek
384a5e9066 Test update 2024-07-03 14:48:38 +02:00
Krauß, Josefine
5d75c23f49 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/main/java/TestClass.java
2024-07-03 14:47:34 +02:00
Krauß, Josefine
ba9760fe43 moved some logic from methodcall to instvar 2024-07-03 14:46:24 +02:00
Julian Murek
888534955a Test update 2024-07-03 13:41:55 +02:00
Krauß, Josefine
f6358867f0 Merge remote-tracking branch 'origin/master' 2024-07-03 12:32:38 +02:00
Krauß, Josefine
0711028dc3 missing thisclass and subreceiver 2024-07-03 12:32:29 +02:00
Jochen Seyfried
97ab66122e Fixed methodCalls with no receiver 2024-07-03 11:56:47 +02:00
Krauß, Josefine
1100cef668 missing thisclass 2024-07-03 11:11:11 +02:00
Julian Murek
3c863aafde Test update 2024-07-03 10:05:04 +02:00
Jochen Seyfried
41d5cd428c Removed TODOs that are no longer needed 2024-07-03 09:14:29 +02:00
Jochen Seyfried
5dd3821ecb Added Comparison of complex types 2024-07-03 09:08:35 +02:00
Jochen Seyfried
c5752df15e Fixed an error regarding the owner of a method if the first method in a chain is not in the class where it is called 2024-07-03 08:18:56 +02:00
Jochen Seyfried
88bcfa5fa3 Fixed Error with InstVars in Assign, where the class in which the field was going to be in was not correct, due to the InstVar parameter not being set and it being treated as a localVar 2024-07-03 07:49:39 +02:00
Jochen Seyfried
5dae167443 Fixed TestClassInput to run through which included the right usage of the class fields as it always loaded this onto the stack, regardless of the class in which the field is in 2024-07-02 18:35:25 +02:00
Krauß, Josefine
47a8d50185 method call without using return is a void statement 2024-07-02 15:45:41 +02:00
Krauß, Josefine
94b3830561 instvar special case 2024-07-02 15:36:27 +02:00
Krauß, Josefine
3dcaad62f9 Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell 2024-07-02 15:22:33 +02:00
Krauß, Josefine
62060462a9 instvar debugging 2024-07-02 15:21:46 +02:00
Jochen Seyfried
d5b526b8fc fixed MethodCallStatementExpression maybe 2024-07-02 15:21:32 +02:00
Julian Murek
10f5dc692d Codegen now generates "output.jar" 2024-07-02 13:04:43 +02:00
Julian Murek
e46cede8d5 Test update 2024-07-02 12:57:44 +02:00
Jochen Seyfried
38aeaa657d First step to fixing methodCall 2024-07-01 23:35:24 +02:00
Jochen Seyfried
cabbbdcaf3 Fixed fields with no imminent value assignment 2024-07-01 20:55:02 +02:00
Krauß, Josefine
192dfae94b changes for jar build 2024-07-01 17:45:07 +02:00
Jochen Seyfried
c24a483880 Fixed complex return types of methods 2024-07-01 13:23:22 +02:00
Julian Murek
aa7d82b9ac Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell 2024-07-01 13:13:26 +02:00
Julian Murek
94ea539fab Test update 2024-07-01 13:13:07 +02:00
Jochen Seyfried
6bf2c75e02 Deleted print statement and tested functionality of method call 2024-07-01 11:45:51 +02:00
Krauß, Josefine
d2b307f86f Merge remote-tracking branch 'origin/master' 2024-07-01 11:19:42 +02:00
Krauß, Josefine
5b0dc04bd7 reached in wrong class and missing typecheckcall on parameters iexpression 2024-07-01 11:19:31 +02:00
6c015e72d5 generated antlr 2024-07-01 11:14:30 +02:00
Krauß, Josefine
cd9fc46a1f Merge remote-tracking branch 'origin/master' 2024-07-01 09:09:33 +02:00
Krauß, Josefine
9b0d8147db bugfix print should return void 2024-07-01 09:09:23 +02:00
Julian Murek
21ece58cc9 Add Print statements to AST equals Methods 2024-07-01 08:36:20 +02:00
8e0b215140 Merge remote-tracking branch 'origin/master' 2024-06-30 22:48:55 +02:00
3fa8400b72 bugfix print 2024-06-30 22:48:35 +02:00
Jochen Seyfried
07552e704e Added bytecodeGeneration for PrintStatement and fixed basic MethodCall 2024-06-30 18:04:04 +02:00
Krauß, Josefine
194ff3fcf7 Merge remote-tracking branch 'origin/master' 2024-06-30 15:25:21 +02:00
Krauß, Josefine
f5dcd4d79f typecheck for PrintStatement 2024-06-30 15:24:47 +02:00
492bab5477 Dateien nach "/" hochladen 2024-06-30 13:08:11 +00:00
David Mueller
99d23e89fa Merge remote-tracking branch 'origin/master' 2024-06-30 15:02:06 +02:00
David Mueller
16cf78521b Update UML- Diagramm 2024-06-30 15:01:57 +02:00
0c9acb2bc9 add PrintStatement to ast 2024-06-30 14:46:58 +02:00
David Mueller
2c7748e6a3 Adding PrintStatement to Grammar 2024-06-30 14:32:17 +02:00
Krauß, Josefine
4b2edaa6ff Merge remote-tracking branch 'origin/master' 2024-06-30 13:39:32 +02:00
Krauß, Josefine
dd2842138f missing case in methodcall 2024-06-30 13:39:20 +02:00
Jochen Seyfried
942597d535 Removed TODOs 2024-06-29 14:04:00 +02:00
Jochen Seyfried
392fea7d23 Fixed Bug concerning all BinaryOperators which are not booleanExpressions but produce a value. 2024-06-29 14:02:51 +02:00
Jochen Seyfried
d1da1c6eee Deleted TODOs which are done 2024-06-28 20:31:21 +02:00
Jochen Seyfried
b787b333fb Fixed usage of fields 2024-06-28 20:29:58 +02:00
Jochen Seyfried
27ca4a978f Updated the handling of fields 2024-06-28 20:16:19 +02:00
Jochen Seyfried
289231030a Merge remote-tracking branch 'origin/master' 2024-06-28 19:46:45 +02:00
3b2a328182 add expression to fieldecl 2024-06-28 19:46:09 +02:00
Jochen Seyfried
127726d342 Merge remote-tracking branch 'origin/master' 2024-06-28 19:36:24 +02:00
Krauß, Josefine
4bc38c0ff9 missing thisClass 2024-06-28 19:32:44 +02:00
Jochen Seyfried
34f4f307f3 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/main/java/abstractSyntaxTree/Program.java
2024-06-28 18:44:47 +02:00
Jochen Seyfried
c30dcdb773 Updated switch statements in case of char 2024-06-28 18:44:03 +02:00
Krauß, Josefine
f6bb836ee0 Merge remote-tracking branch 'origin/master' 2024-06-28 18:33:34 +02:00
Krauß, Josefine
7498ca6e4d constructor return type 2024-06-28 18:33:21 +02:00
Jochen Seyfried
66c7722728 After the realization that there was a mixup with the produced .class files we once again fix the codeGen
In this commit the standard constructors, mainMethod and standard variable declations were fixed and validated
2024-06-28 18:23:19 +02:00
4b7cb0b150 bugfix mainmethod ast 2024-06-28 15:32:08 +02:00
Krauß, Josefine
1358e3372f Merge remote-tracking branch 'origin/master' 2024-06-28 11:29:22 +02:00
Krauß, Josefine
5c81b88ca5 fixed code bloc without return 2024-06-28 11:28:58 +02:00
KingJulian
a3000d0ba1 Test update 2024-06-28 11:13:22 +02:00
Krauß, Josefine
d4f98693d6 Merge remote-tracking branch 'origin/master' 2024-06-27 09:30:43 +02:00
Krauß, Josefine
6365e994d2 fixed another localvaridentifier that just isnt local actually 2024-06-27 09:30:31 +02:00
Jochen Seyfried
377e9b3193 Implemented the new codeGen for MethodCallStatementExpression 2024-06-27 09:27:08 +02:00
Jochen Seyfried
eac4eb1db8 Merge remote-tracking branch 'origin/master' 2024-06-27 08:47:54 +02:00
Jochen Seyfried
d8602ddd18 Added MethodContext to MethodCallStatementExpression 2024-06-27 08:31:50 +02:00
b84ad2ef6b Merge remote-tracking branch 'origin/master' 2024-06-27 08:11:17 +02:00
60958538d8 change UnaryExpression 2024-06-27 08:11:04 +02:00
Krauß, Josefine
ed2f64eff9 bugfix nullpointer if no receiver 2024-06-26 16:12:21 +02:00
Krauß, Josefine
77a6dae94f added check if there is a main method 2024-06-26 15:55:34 +02:00
Krauß, Josefine
30334dc393 Merge remote-tracking branch 'origin/master' 2024-06-26 15:38:59 +02:00
Krauß, Josefine
2a2e14ae21 methodcall 2024-06-26 15:38:46 +02:00
9cf2ff6f37 Merge remote-tracking branch 'origin/master' 2024-06-25 17:09:26 +02:00
b402857713 fix methodCall 2024-06-25 17:09:16 +02:00
Krauß, Josefine
8182e1ee7a added thisClass to some other classes 2024-06-25 17:01:00 +02:00
Krauß, Josefine
ae260f6feb boolean instead of bool 2024-06-25 15:06:20 +02:00
Krauß, Josefine
7daece9b8f Merge remote-tracking branch 'origin/master' 2024-06-25 08:16:47 +02:00
Krauß, Josefine
b95bc75a1e made upperbound method static 2024-06-25 08:16:29 +02:00
Jochen Seyfried
1dac9245f2 Added other implementation for methodCallStatement 2024-06-23 16:42:27 +02:00
Jochen Seyfried
90936affb9 Changed "bool" to "boolean" 2024-06-22 16:39:29 +02:00
Jochen Seyfried
9ff069827a Fixed Bugs in bytecode generation 2024-06-22 16:33:53 +02:00
Jochen Seyfried
87e863e773 Implemented CodeGen for Constants and fixed an issue regarding the placements of local variables on the JVM stack.
( index JVM = index localVars + 1)
2024-06-22 12:30:06 +02:00
Krauß, Josefine
c764b710ea calling newstatementexpression from localvar 2024-06-20 13:59:44 +02:00
Julian Murek
e7d4a83a1d Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell 2024-06-20 13:28:31 +02:00
Julian Murek
dcb564bd0d Test update 2024-06-20 13:28:16 +02:00
c8c12e4d9a add expression to LocalVarDecl in ast 2024-06-20 13:17:53 +02:00
Krauß, Josefine
e23d84cd09 Merge remote-tracking branch 'origin/master' 2024-06-20 12:47:25 +02:00
Krauß, Josefine
8a26f700b5 methodcall not implemented, current input not working on ast or typechek or codegen 2024-06-20 12:47:03 +02:00
621ce16615 returnType of bLockStatement is now always null 2024-06-20 11:27:17 +02:00
Krauß, Josefine
5a66ce97ca Merge remote-tracking branch 'origin/master' 2024-06-20 11:03:41 +02:00
Krauß, Josefine
fdae734452 mostly refactoring und now using "typecheckexception" 2024-06-20 11:03:27 +02:00
ebd4f7ca4e fix parameterList in ast 2024-06-20 09:35:43 +02:00
Jochen Seyfried
719e19e7f8 Added TODOs 2024-06-20 09:07:29 +02:00
Krauß, Josefine
5220a65a92 testing in meeting 2024-06-20 08:30:12 +02:00
Krauß, Josefine
6585e67273 Merge remote-tracking branch 'origin/master' 2024-06-20 08:01:52 +02:00
Krauß, Josefine
6915a97432 instvar typecheck and getTypeCheckresults 2024-06-20 08:00:23 +02:00
c96d9fc1a1 fix block in constructor in ast 2024-06-20 07:37:24 +02:00
b00979c1a8 fix ast 2024-06-20 07:28:31 +02:00
112c5f2c1b add instVar to ast 2024-06-19 20:35:59 +02:00
KingJulian
46ac49576e Changed to take ".class" files again :) 2024-06-19 17:05:54 +02:00
KingJulian
eaac9898f4 test update 2024-06-19 15:26:41 +02:00
Julian Murek
e70580ac86 Update junit 2024-06-19 12:58:09 +02:00
afd2319d78 Merge remote-tracking branch 'origin/master' 2024-06-18 16:09:46 +02:00
821908f060 fix int in ASTGenerator 2024-06-18 16:09:31 +02:00
Krauß, Josefine
d8397753ca Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/main/java/Input.java
2024-06-18 15:42:27 +02:00
Krauß, Josefine
6fa199da1d makeing else f work without type of code block 2024-06-18 15:42:04 +02:00
666931fa44 fix SuperStatementExpression 2024-06-18 11:49:25 +02:00
cdc81f705a add method call to ast and change bool to boolean in grammar 2024-06-18 11:47:21 +02:00
Krauß, Josefine
6f9791455d Merge remote-tracking branch 'origin/master' 2024-06-18 10:08:25 +02:00
Krauß, Josefine
0f76b1fdae small change due to "not" as block return 2024-06-18 10:08:14 +02:00
KingJulian
c44ed5446d Vorläufige Testsuite für ByteCode-Testing 2024-06-16 12:28:27 +02:00
Krauß, Josefine
fa430301bb typecheck update for Example3 2024-06-14 17:00:03 +02:00
23f541ff7d add char and boolean values to ast 2024-06-12 20:19:02 +02:00
Jochen Seyfried
bc984a89e1 Merge remote-tracking branch 'origin/master' 2024-05-31 13:53:19 +02:00
Jochen Seyfried
63059994ec Implemented NewStatementExpression and finished the return of objects (classes, methods) with fully qualified name 2024-05-31 13:53:06 +02:00
Krauß, Josefine
949c2de28e Merge remote-tracking branch 'origin/master' 2024-05-31 13:41:45 +02:00
Krauß, Josefine
c71d5454c6 typecheck 2024-05-31 13:41:30 +02:00
d665c0393c Merge remote-tracking branch 'origin/master' 2024-05-31 13:08:26 +02:00
39e8e0ea6a change returnType of constructorDecl to null 2024-05-31 13:08:18 +02:00
Krauß, Josefine
0d827c5f32 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/main/java/abstractSyntaxTree/Datatype/BoolDatatype.java
#	src/main/java/abstractSyntaxTree/Datatype/CharDatatype.java
#	src/main/java/abstractSyntaxTree/Datatype/IntDatatype.java
#	src/main/java/abstractSyntaxTree/Expression/BinaryExpression.java
#	src/main/java/abstractSyntaxTree/Expression/InstVarExpression.java
#	src/main/java/abstractSyntaxTree/Expression/IntConstantExpression.java
#	src/main/java/abstractSyntaxTree/Expression/LocalVarIdentifier.java
#	src/main/java/abstractSyntaxTree/Expression/UnaryExpression.java
#	src/main/java/abstractSyntaxTree/Statement/BlockStatement.java
#	src/main/java/abstractSyntaxTree/Statement/EmptyStatement.java
#	src/main/java/abstractSyntaxTree/Statement/IfElseStatement.java
#	src/main/java/abstractSyntaxTree/Statement/IfStatement.java
#	src/main/java/abstractSyntaxTree/Statement/LocalVarDecl.java
#	src/main/java/abstractSyntaxTree/Statement/ReturnStatement.java
#	src/main/java/abstractSyntaxTree/Statement/WhileStatement.java
2024-05-31 13:05:31 +02:00
Krauß, Josefine
ec38d8049b gettypecheckresult 2024-05-31 12:59:58 +02:00
9d9dcfb9b6 add newDecl to ASTGenerator 2024-05-31 12:53:03 +02:00
Julian Murek
66428159c1 Import path adjusted 2024-05-31 12:13:41 +02:00
77bf6cff62 Merge remote-tracking branch 'origin/master' 2024-05-31 12:12:18 +02:00
a97548c3ee fix localvardecl 2024-05-31 12:11:43 +02:00
Julian Murek
06dc01f629 Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell 2024-05-31 12:11:32 +02:00
Julian Murek
50215afb07 Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell 2024-05-31 12:11:24 +02:00
Jochen Seyfried
5592a6cfe1 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/main/java/abstractSyntaxTree/StatementExpression/NewStatementExpression.java
2024-05-31 12:09:47 +02:00
Julian Murek
dac0b3370f Le update a la Julian 2024-05-31 12:09:23 +02:00
Jochen Seyfried
519d891743 NewStatementExpression start 2024-05-31 12:08:47 +02:00
d4cc24239d Merge remote-tracking branch 'origin/master' 2024-05-31 11:55:58 +02:00
25d379876b add assign 2024-05-31 11:55:33 +02:00
Krauß, Josefine
abc4e3ff70 continued typecheck 2024-05-31 11:54:57 +02:00
Krauß, Josefine
a147512dcb Merge remote-tracking branch 'origin/master' 2024-05-31 11:06:18 +02:00
Krauß, Josefine
b20b7adc99 removed unused method 2024-05-31 11:06:10 +02:00
3953bbe549 Merge remote-tracking branch 'origin/master' 2024-05-31 11:05:31 +02:00
7458be43d7 add class intConstant to ast 2024-05-31 11:05:05 +02:00
Krauß, Josefine
8d6d8d5588 merged assign statement expression 2024-05-31 11:03:16 +02:00
Krauß, Josefine
ef38079f58 Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell
# Conflicts:
#	src/main/java/abstractSyntaxTree/Class/MethodDecl.java
#	src/main/java/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java
#	src/main/java/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java
2024-05-31 11:00:50 +02:00
Krauß, Josefine
9d86ab3a9f method parameters 2024-05-31 10:59:06 +02:00
95313d8083 Merge remote-tracking branch 'origin/master' 2024-05-31 10:45:45 +02:00
8549799175 fix ifstmt in ASTGenerator 2024-05-31 10:44:45 +02:00
Jochen Seyfried
21dff015b5 Changed the order of arguments 2024-05-31 10:42:14 +02:00
Jochen Seyfried
9fa9dfdfb6 Fixed missing parameters in Program, MethodDecl, and RefType 2024-05-31 10:26:47 +02:00
Jochen Seyfried
ab19751146 Updated IStatement and IExpression classes to fit the method calls 2024-05-31 10:04:27 +02:00
Krauß, Josefine
5fa6664850 Merge branch 'master' of https://gitea.hb.dhbw-stuttgart.de/i22022/NichtHaskell
# Conflicts:
#	src/main/java/abstractSyntaxTree/Expression/LocalVarIdentifier.java
#	src/main/java/abstractSyntaxTree/Expression/UnaryExpression.java
#	src/main/java/abstractSyntaxTree/Statement/ReturnStatement.java
#	src/main/java/abstractSyntaxTree/StatementExpression/AssignStatementExpression.java
2024-05-31 09:42:21 +02:00
Krauß, Josefine
08d13a0df7 method parameters 2024-05-31 09:39:17 +02:00
d6fb825808 add Node to IExpression 2024-05-30 20:57:50 +02:00
873d1b7a0a Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/main/java/abstractSyntaxTree/Expression/IExpression.java
2024-05-30 20:38:46 +02:00
d1e39be655 add binary expressions in ast 2024-05-30 20:38:06 +02:00
Jochen Seyfried
b91174eeee Implemented CodeGen for Assign and MethodCall. But MethodCall is not working at the moment 2024-05-22 12:49:59 +02:00
Jochen Seyfried
108b8f63ea Updated CodeGen of FiledDecl and MethodDecl and Assign 2024-05-22 10:05:20 +02:00
Julian Murek
3be8d9854a euqals methods overriden in "Program, RefType, MethodDecl and FieldDecl" for AST comparison. 2024-05-14 15:34:26 +02:00
Krauß, Josefine
35fba57efa Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/main/java/abstractSyntaxTree/Statement/IfElseStatement.java
#	src/main/java/abstractSyntaxTree/Statement/IfStatement.java
#	src/main/java/abstractSyntaxTree/Statement/WhileStatement.java
2024-05-14 15:19:26 +02:00
Krauß, Josefine
6148b46063 parameterlist, typecheck 2024-05-14 15:18:18 +02:00
Krauß, Josefine
a59950e186 parameterlist, typecheck 2024-05-14 15:15:58 +02:00
Jochen Seyfried
0fcea195de Updated If and WhileStatement 2024-05-14 14:54:33 +02:00
Jochen Seyfried
f2260c7a73 Deleted ICLass and updated the MethodDecl codeGen 2024-05-14 14:51:59 +02:00
Krauß, Josefine
74e3cb8016 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	src/main/java/Compiler.java
#	src/main/java/abstractSyntaxTree/Class/MethodDecl.java
#	src/main/java/abstractSyntaxTree/Class/RefType.java
#	src/main/java/abstractSyntaxTree/Program.java
2024-05-14 14:48:25 +02:00
Krauß, Josefine
2f549e31e9 interface changes, added localvaridentifier, removed iclass interface, some type check for statements, delete varrefexpression 2024-05-14 14:45:04 +02:00
0a81315366 Merge remote-tracking branch 'origin/master' 2024-05-14 14:23:55 +02:00
99b979d77f add new package for astGenerator 2024-05-14 14:23:12 +02:00
Jochen Seyfried
6eb26e70d5 Deleted ICLass and updated the MethodDecl codeGen 2024-05-14 14:13:43 +02:00
Jochen Seyfried
7ff84e5ad7 Changed the methodContext to use the ParameterList 2024-05-14 11:53:00 +02:00
Krauß, Josefine
87cde5e048 inzterface changes typecheck 2024-05-14 11:33:17 +02:00
Krauß, Josefine
c3a9b9a7d6 Merge remote-tracking branch 'origin/master' 2024-05-14 11:32:40 +02:00
Krauß, Josefine
4ca936e619 using input from file 2024-05-14 11:32:21 +02:00
David Mueller
6e707cc7ed Antlr Changes EmptyStatement 2024-05-14 10:45:15 +02:00
David Mueller
d22ea6b962 Antlr Changes to Methodcalls from Return 2024-05-14 10:31:53 +02:00
091eaa912e add some visitstatement methods in ASTGenerator 2024-05-13 23:19:36 +02:00
e99b7adcd4 change methods in ASTGenerator 2024-05-13 22:09:24 +02:00
3783a1d61b Merge remote-tracking branch 'origin/master' 2024-05-13 22:08:05 +02:00
d0f3f3b938 change methods in ASTGenerator 2024-05-13 22:04:02 +02:00
Jochen Seyfried
b5b6f763e0 Updated the codeGen Methods in FieldDecl, MethodDecl and BlockStatement 2024-05-13 21:04:09 +02:00
cc05c58159 added ast methods, parameter classes 2024-05-11 20:45:51 +02:00
91340125ef added ast generator 2024-05-10 06:23:09 +02:00
484418e884 added ast 2024-05-10 06:18:32 +02:00
KingJulian
309aff9576 File to test Token-Generation 2024-05-09 18:35:40 +02:00
KingJulian
4c73ae6786 Updatet Tests for Token-Generation 2024-05-09 18:33:33 +02:00
Krauß, Josefine
4f2599d053 interface changes and some typecheck for code block. also some minor changes in blockstatement structure 2024-05-09 17:28:29 +02:00
Krauß, Josefine
371755f390 Merge remote-tracking branch 'origin/master' 2024-05-09 16:52:23 +02:00
Krauß, Josefine
9ec583b17f moved tables out of constructor and fixed some type check 2024-05-09 16:49:53 +02:00
David Mueller
9166d87afd Changes to the Grammar 2024-05-09 16:08:07 +02:00
Jochen Seyfried
1cd4d87a94 Deleted old Source 2024-05-09 15:58:48 +02:00
Jochen Seyfried
cf590b2248 Added dependencies to pom 2024-05-09 15:56:23 +02:00
Jochen Seyfried
0576bd303d Pom and gitignore 2024-05-09 15:41:52 +02:00
Jay
334f470488 Maven structure 2024-05-09 15:25:46 +02:00
Krauß, Josefine
85282ff90c Merge remote-tracking branch 'origin/master' 2024-05-09 15:12:23 +02:00
Krauß, Josefine
dbcf40ea84 antr gen package expilcitly added and some printlines in main 2024-05-09 15:12:08 +02:00
Jochen Seyfried
8419b1aa17 Changed the generation to a .class 2024-05-09 15:10:53 +02:00
Jochen Seyfried
80917ec222 Fixed nullPointer Exception for missing class name 2024-05-09 14:41:07 +02:00
Jochen Seyfried
965b758fba Fixed the Program call 2024-05-09 14:28:32 +02:00
Krauß, Josefine
5de106876a Merge remote-tracking branch 'origin/master' 2024-05-09 14:22:59 +02:00
Krauß, Josefine
2c6bef9e9e antr generated 2024-05-09 14:22:45 +02:00
Jochen Seyfried
950354a2e7 Merge remote-tracking branch 'origin/master' 2024-05-09 14:21:07 +02:00
Jochen Seyfried
2b671c32db Changed some missing parameters 2024-05-09 14:20:55 +02:00
Julian Murek
ec7dd2a10d Maven structure 2024-05-09 14:16:39 +02:00
Krauß, Josefine
b8a8a094f4 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	Source/abstractSyntaxTree/Class/MethodDecl.java
2024-05-08 15:15:25 +02:00
Krauß, Josefine
fe249c5b2a try to run main 2024-05-08 15:14:58 +02:00
Jochen Seyfried
1617e3ec62 Added RefType codeGen logic 2024-05-08 14:42:56 +02:00
Krauß, Josefine
f273c74693 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	Source/abstractSyntaxTree/Class/MethodDecl.java
#	Source/abstractSyntaxTree/Program.java
#	Source/abstractSyntaxTree/StatementExpression/MethodCallStatementExpression.java
2024-05-08 14:31:39 +02:00
Krauß, Josefine
783bab8580 context tables 2024-05-08 14:28:51 +02:00
Jochen Seyfried
9cda409dd3 Added Programm codeGen logic 2024-05-08 14:28:01 +02:00
Jochen Seyfried
103e80e318 Moved the RefType class to the class package 2024-05-08 14:15:11 +02:00
222 changed files with 12733 additions and 4720 deletions

6
.idea/.gitignore generated vendored Normal file
View 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
View 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
View 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
View 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
View 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>

View File

@@ -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>

View File

@@ -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.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Binary file not shown.

20
Examples/Fakultaet.java Normal file
View 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);
}
}

View 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;
}
}

View File

@@ -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

View File

@@ -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
View File

@@ -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

View File

@@ -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
View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -1,5 +0,0 @@
package TypeCheck;
public class TypeCheckResult {
public String type;
}

View File

@@ -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
}
}

View File

@@ -1,9 +0,0 @@
package abstractSyntaxTree.Class;
import TypeCheck.TypeCheckResult;
import java.util.List;
public interface IClass {
// visit method for code generation
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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 "=="

View File

@@ -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");
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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");
}
}

View File

@@ -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();
}
}
}

View File

@@ -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
}
}
}

View File

@@ -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
}
}

View File

@@ -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;
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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");
}
}

View File

@@ -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

Binary file not shown.

Binary file not shown.

67
pom.xml Normal file
View 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
View 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>

View 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
View 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.");
}
}

View File

@@ -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;

View 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;
}
}

View File

@@ -0,0 +1,7 @@
package TypeCheck;
public class TypeCheckException extends Exception {
public TypeCheckException(String message) {
super(message);
}
}

View 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);
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View File

@@ -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();
}
}

View 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();
}
}

View 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();
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View 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();
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View 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;
}
}

View File

@@ -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();
}
}

View File

@@ -0,0 +1,4 @@
package abstractSyntaxTree;
public interface Node {
}

View 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;
}
}

View File

@@ -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;
}
}

View 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));
}
}

View 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();
}
}

View File

@@ -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;
}
}

View 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();
}

View File

@@ -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();
}
}

View 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();
}
}

View 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();
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View 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;
}
}

File diff suppressed because one or more lines are too long

View 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

View 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) { }
}

View 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); }
}

File diff suppressed because one or more lines are too long

View 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);
}
}
}

View 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