Compare commits

...

3 Commits

Author SHA1 Message Date
3d88a704ae parser add optinoal parameters 2024-07-04 13:58:13 +02:00
30288731d3 mmooore Tests 2024-07-03 16:32:54 +02:00
f7d135cdd6 update pdf 2024-07-01 17:43:21 +02:00
6 changed files with 88 additions and 8 deletions

View File

@ -17,6 +17,8 @@ public class Main {
TestMalicious malicious = new TestMalicious();
TestLoop loop = new TestLoop();
TestMethodOverload overload = new TestMethodOverload();
TestShenanigance shenanigance = new TestShenanigance();
TestOptionalParameter optionalParameter = new TestOptionalParameter();
// constructing a basic class works
assert empty != null;
@ -35,6 +37,7 @@ public class Main {
// self-referencing methods work.
assert recursion.fibonacci(15) == 610;
assert loop.factorial(5) == 120;
assert loop.weirdFor() == 5;
// methods with the same name but different parameters work
assert overload.MethodOverload() == 42;
assert overload.MethodOverload(15) == 42 + 15;
@ -48,5 +51,14 @@ public class Main {
{
assert malicious.cursedFormatting(i) == i;
}
// other syntactic sugar
assert shenanigance.testAssignment() == 5;
assert shenanigance.divEqual() == 234_343_000 / 4;
assert shenanigance.testIf(5);
// optional parameters
assert optionalParameter.oneOptional() == 1;
assert optionalParameter.oneOptional(2) == 2;
assert optionalParameter.normalAndOptional(1) == 6;
assert optionalParameter.normalAndOptional(1, 0, 0) == 1;
}
}

View File

@ -9,4 +9,11 @@ public class TestLoop {
return tally;
}
int weirdFor() {
int k = 0;
for (; k < 5; k++) {
}
return k;
}
}

View File

@ -0,0 +1,10 @@
class TestOptionalParameter {
int oneOptional(int p = 1) {
return p;
}
int normalAndOptional(int a, int b = 2, int c = 3) {
return a + b + c;
}
}

View File

@ -0,0 +1,25 @@
class TestShenanigance {
int testAssignment() {
int x = 1;
int y = x = 5;
return y;
}
int divEqual() {
int x = 234_343_000;
x /= 4;
return x;
}
boolean testIf(int x) {
if (true && x < 8) {
char f = 'c';
return f > x ;
}
ifn't {
return false;
}
}
}

Binary file not shown.

View File

@ -1,5 +1,5 @@
{
module Parser.JavaParser (parse, parseStatement, parseExpression) where
module Parser.JavaParser (parse, parseStatement, parseExpression, parseMethod) where
import Ast
import Parser.Lexer
}
@ -7,6 +7,7 @@ import Parser.Lexer
%name parse
%name parseStatement statement
%name parseExpression expression
%name parseMethod classbodydeclarations
%tokentype { Token }
%error { parseError }
%errorhandlertype explist
@ -104,13 +105,13 @@ modifiers : modifier { }
classbodydeclarations : classbodydeclaration {
case $1 of
ConstructorDecl constructor -> ([constructor], [], [])
MethodDecl method -> ([], [method], [])
MethodDecl method -> ([], (convertMethodDeclarationWithOptionals method), [])
FieldDecls fields -> ([], [], fields)
}
| classbodydeclarations classbodydeclaration {
case ($1, $2) of
((constructors, methods, fields), ConstructorDecl constructor) -> ((constructors ++ [constructor]), methods, fields)
((constructors, methods, fields), MethodDecl method) -> (constructors, (methods ++ [method]), fields)
((constructors, methods, fields), MethodDecl method) -> (constructors, (methods ++ (convertMethodDeclarationWithOptionals method)), fields)
((constructors, methods, fields), FieldDecls newFields) -> (constructors, methods, (fields ++ newFields))
}
@ -136,7 +137,7 @@ constructordeclaration : constructordeclarator constructorbody { case $1 of (ide
fielddeclaration : type variabledeclarators SEMICOLON { FieldDecls $ map (convertDeclarator $1) $2 }
| modifiers type variabledeclarators SEMICOLON { FieldDecls $ map (convertDeclarator $2) $3 }
methoddeclaration : methodheader methodbody { case $1 of (returnType, (name, parameters)) -> MethodDecl (MethodDeclaration returnType name parameters $2) }
methoddeclaration : methodheader methodbody { case $1 of (returnType, (name, (parameters, optionalparameters))) -> MethodDecl (MethodDeclarationWithOptionals returnType name parameters optionalparameters $2) }
block : LBRACKET RBRACKET { Block [] }
| LBRACKET blockstatements RBRACKET { Block $2 }
@ -166,6 +167,10 @@ methodbody : block { $1 }
blockstatements : blockstatement { $1 }
| blockstatements blockstatement { $1 ++ $2}
formalandoptionalparameterlist : formalparameterlist { ($1, []) }
| formalparameterlist COMMA optionalparameterlist { ($1, $3) }
| optionalparameterlist { ([], $1) }
formalparameterlist : formalparameter { [$1] }
| formalparameterlist COMMA formalparameter { $1 ++ [$3] }
@ -175,8 +180,13 @@ explicitconstructorinvocation : THIS LBRACE RBRACE SEMICOLON { }
classtypelist : classtype { }
| classtypelist COMMA classtype { }
methoddeclarator : IDENTIFIER LBRACE RBRACE { ($1, []) }
| IDENTIFIER LBRACE formalparameterlist RBRACE { ($1, $3) }
methoddeclarator : IDENTIFIER LBRACE RBRACE { ($1, ([], [])) }
| IDENTIFIER LBRACE formalandoptionalparameterlist RBRACE { ($1, $3) }
optionalparameterlist : optionalparameter { [$1] }
| optionalparameterlist COMMA optionalparameter { $1 ++ [$3] }
optionalparameter : type variabledeclaratorid ASSIGN variableinitializer { OptionalParameter $1 $2 $4 }
primitivetype : BOOLEAN { "boolean" }
| numerictype { $1 }
@ -386,9 +396,9 @@ multiplicativeexpression : unaryexpression { $1 }
{
data MemberDeclaration = MethodDecl MethodDeclaration
data MemberDeclaration = MethodDecl MethodDeclarationWithOptionals
| ConstructorDecl ConstructorDeclaration
| FieldDecls [VariableDeclaration]
| FieldDecls [VariableDeclaration] deriving (Show)
data Declarator = Declarator Identifier (Maybe Expression)
@ -399,6 +409,22 @@ extractFunctionName :: Expression -> (Expression, Identifier)
extractFunctionName (BinaryOperation NameResolution exp (Reference functionname)) = (exp, functionname)
extractFunctionName (Reference functionname) = ((Reference "this"), functionname)
data OptionalParameter = OptionalParameter DataType Identifier Expression deriving (Show)
data MethodDeclarationWithOptionals = MethodDeclarationWithOptionals DataType Identifier [ParameterDeclaration] [OptionalParameter] Statement deriving (Show)
convertMethodDeclarationWithOptionals :: MethodDeclarationWithOptionals -> [MethodDeclaration]
convertMethodDeclarationWithOptionals (MethodDeclarationWithOptionals returnType id param [] stmt) = [MethodDeclaration returnType id param stmt]
convertMethodDeclarationWithOptionals (MethodDeclarationWithOptionals returnType id param (opt : optRest) stmt) = generateHelperMethod returnType id param opt : convertMethodDeclarationWithOptionals (generateBaseMethod returnType id param opt optRest stmt)
convertOptionalParameter :: OptionalParameter -> ParameterDeclaration
convertOptionalParameter (OptionalParameter dtype id exp) = ParameterDeclaration dtype id
generateHelperMethod :: DataType -> Identifier -> [ParameterDeclaration] -> OptionalParameter -> MethodDeclaration
generateHelperMethod returnType methodName params (OptionalParameter dtype id exp) =
let references = ((map (\(ParameterDeclaration paramType ident) -> (Reference ident)) params) ++ [exp])
methodcall = (MethodCall (Reference "this") methodName references)
lastStatement = if returnType == "void" then StatementExpressionStatement methodcall else Return $ Just $ StatementExpressionExpression methodcall
in MethodDeclaration returnType methodName params $ Block [lastStatement]
generateBaseMethod :: DataType -> Identifier -> [ParameterDeclaration] -> OptionalParameter -> [OptionalParameter] -> Statement -> MethodDeclarationWithOptionals
generateBaseMethod returnType methodName params (OptionalParameter dtype id exp) optRest stmt = MethodDeclarationWithOptionals returnType methodName (params ++ [ParameterDeclaration dtype id]) optRest stmt
parseError :: ([Token], [String]) -> a
parseError (errortoken, expected) = error ("parse error on token: " ++ show errortoken ++ "\nexpected one of: " ++ show expected)