diff --git a/resources/syntaxtreegenerator/javFiles/Switch.jav b/resources/syntaxtreegenerator/javFiles/Switch.jav new file mode 100644 index 00000000..b864db3a --- /dev/null +++ b/resources/syntaxtreegenerator/javFiles/Switch.jav @@ -0,0 +1,41 @@ +import java.lang.Integer; +import java.lang.String; +import java.lang.Boolean; + +class SwitchStatement { + + boolean switchStandard(){ + str = "SwitchMe"; + switch(str){ + case String s: return true; + default: return false; + } + } + + boolean switchInteger(){ + i = 5; + switch(i){ + case Integer j: + case String s: i = 6; break; + default: i = 0; break; + } + return (i==0); + } + + boolean guardedPattern(){ + var i = 1; + switch(i){ + case Integer j && j == 1: return true; + default: return false; + } + } + + /* boolean enclosedPattern(){ + var i = "Test"; + var j = switch(i){ + case (String s)->{ yield 0;} + case Integer i ->{ yield 1;} + }; + return (j==0); + } */ +} \ No newline at end of file diff --git a/src/main/antlr4/de/dhbwstuttgart/parser/antlr/Java17Parser.g4 b/src/main/antlr4/de/dhbwstuttgart/parser/antlr/Java17Parser.g4 index bc5f8f93..c2781f1c 100644 --- a/src/main/antlr4/de/dhbwstuttgart/parser/antlr/Java17Parser.g4 +++ b/src/main/antlr4/de/dhbwstuttgart/parser/antlr/Java17Parser.g4 @@ -575,8 +575,10 @@ switchBlockStatementGroup ; switchLabel - : CASE (constantExpression=expression | enumConstantName=IDENTIFIER | pattern) ':' - | DEFAULT ':' + : CASE constantExpression=expression ':' #switchLabelConst + | CASE enumConstantName=IDENTIFIER ':' #switchLabelEnum + | CASE pattern ':' #switchLabelPattern + | DEFAULT ':' #switchLabelDefault ; forControl @@ -720,7 +722,7 @@ switchLabeledRule // Java17 guardedPattern - : variableModifier* typeType? annotation* identifier ('&&' expression)* + : variableModifier* typeType annotation* identifier ('&&' expression)* | guardedPattern '&&' expression ; diff --git a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java index ada763a2..c7bf49b3 100644 --- a/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java +++ b/src/main/java/de/dhbwstuttgart/parser/SyntaxTreeGenerator/StatementGenerator.java @@ -34,6 +34,8 @@ import de.dhbwstuttgart.parser.antlr.Java17Parser.EqualityexpressionContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.ExpressionContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.FltLiteralContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.ForloopContext; +import de.dhbwstuttgart.parser.antlr.Java17Parser.GPatternContext; +import de.dhbwstuttgart.parser.antlr.Java17Parser.GuardedPatternContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.IdentifierContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.InstanceofexpressionContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.IntLiteralContext; @@ -48,6 +50,7 @@ import de.dhbwstuttgart.parser.antlr.Java17Parser.NewinstanceexpressionContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.NullLiteralContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.OrexpressionContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.PPatternContext; +import de.dhbwstuttgart.parser.antlr.Java17Parser.PatternContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.PostfixexpressionContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.PrefixexpressionContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.PrimaryClassrefContext; @@ -64,6 +67,11 @@ import de.dhbwstuttgart.parser.antlr.Java17Parser.SemistmtContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.ShiftexpressionContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.StmtexpressionContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.StringLiteralContext; +import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchBlockStatementGroupContext; +import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchLabelConstContext; +import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchLabelContext; +import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchLabelDefaultContext; +import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchLabelPatternContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchexpressionstmtContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.SwitchstmtContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.SynchronizedstmtContext; @@ -78,18 +86,19 @@ import de.dhbwstuttgart.parser.scope.GenericsRegistry; import de.dhbwstuttgart.parser.scope.JavaClassRegistry; import de.dhbwstuttgart.syntaxtree.FormalParameter; import de.dhbwstuttgart.syntaxtree.ParameterList; -import de.dhbwstuttgart.syntaxtree.TypePattern; import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; import de.dhbwstuttgart.syntaxtree.statement.Assign; import de.dhbwstuttgart.syntaxtree.statement.AssignLeftSide; import de.dhbwstuttgart.syntaxtree.statement.AssignToField; import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr; import de.dhbwstuttgart.syntaxtree.statement.Block; +import de.dhbwstuttgart.syntaxtree.statement.Break; import de.dhbwstuttgart.syntaxtree.statement.CastExpr; import de.dhbwstuttgart.syntaxtree.statement.DoStmt; import de.dhbwstuttgart.syntaxtree.statement.Expression; import de.dhbwstuttgart.syntaxtree.statement.ExpressionReceiver; import de.dhbwstuttgart.syntaxtree.statement.FieldVar; +import de.dhbwstuttgart.syntaxtree.statement.GuardedPattern; import de.dhbwstuttgart.syntaxtree.statement.IfStmt; import de.dhbwstuttgart.syntaxtree.statement.InstanceOf; import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression; @@ -104,7 +113,11 @@ import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid; import de.dhbwstuttgart.syntaxtree.statement.Statement; import de.dhbwstuttgart.syntaxtree.statement.StaticClassName; import de.dhbwstuttgart.syntaxtree.statement.Super; +import de.dhbwstuttgart.syntaxtree.statement.Switch; +import de.dhbwstuttgart.syntaxtree.statement.SwitchBlock; +import de.dhbwstuttgart.syntaxtree.statement.SwitchLabel; import de.dhbwstuttgart.syntaxtree.statement.This; +import de.dhbwstuttgart.syntaxtree.statement.Pattern; import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr; import de.dhbwstuttgart.syntaxtree.statement.WhileStmt; import de.dhbwstuttgart.syntaxtree.type.RefType; @@ -324,8 +337,11 @@ public class StatementGenerator { } private Statement convert(Java17Parser.SwitchstmtContext stmt) { - // TODO - throw new NotImplementedException(); + List switchBlocks = new ArrayList<>(); + for (SwitchBlockStatementGroupContext blockstmt : stmt.switchBlockStatementGroup()) { + switchBlocks.add(convert(blockstmt)); + } + return new Switch(switchBlocks, convert(stmt.parExpression().expression()).getType(), true, stmt.getStart()); } private Statement convert(Java17Parser.SwitchexpressionstmtContext switchexpression) { @@ -338,9 +354,65 @@ public class StatementGenerator { throw new NotImplementedException(); } - private Statement convert(Java17Parser.SwitchBlockStatementGroupContext stmt) { - // TODO - throw new NotImplementedException(); + private SwitchBlock convert(Java17Parser.SwitchBlockStatementGroupContext stmt) { + List labels = new ArrayList<>(); + stmt.switchLabel().forEach((label) -> { + labels.add(convert(label)); + }); + List block = new ArrayList<>(); + stmt.blockStatement().stream().forEach((blockStmt) -> { + block.addAll(convert(blockStmt)); + }); + return new SwitchBlock(labels, block, stmt.getStart()); + } + + private SwitchLabel convert(SwitchLabelContext switchLabel) { + Expression caseExpression = switch (switchLabel) { + case SwitchLabelConstContext cons -> { + yield convert(cons.constantExpression); + } + case SwitchLabelPatternContext pattern -> { + yield convert(pattern.pattern()); + } + case SwitchLabelDefaultContext def -> { + yield null; + } + default -> throw new NotImplementedException(); + }; + Token offset = switchLabel.getStart(); + if (Objects.isNull(caseExpression)) { + return new SwitchLabel(null, TypePlaceholder.fresh(offset), offset); + } else { + return new SwitchLabel(caseExpression, caseExpression.getType(), offset); + } + + } + + private Pattern convert(PatternContext pattern) { + return switch (pattern) { + case PPatternContext pPattern -> { + yield convert(pPattern.primaryPattern()); + } + case GPatternContext gPattern -> { + GuardedPatternContext guarded = gPattern.guardedPattern(); + List conditions = guarded.expression().stream().map((expr) -> { + return convert(expr); + }).toList(); + yield new GuardedPattern(conditions, guarded.identifier().getText(), TypeGenerator.convert(guarded.typeType(), reg, generics), guarded.getStart()); + } + default -> throw new NotImplementedException(); + }; + } + + private Pattern convert(PrimaryPatternContext pPattern) { + switch (pPattern) { + case TPatternContext tPattern: + TypePatternContext typePattern = tPattern.typePattern(); + return new Pattern(typePattern.identifier().getText(), TypeGenerator.convert(typePattern.typeType(), reg, generics), typePattern.getStart()); + default: + throw new NotImplementedException(); + + } } private Statement convert(Java17Parser.WhileloopContext stmt) { @@ -421,8 +493,13 @@ public class StatementGenerator { } private Statement convert(Java17Parser.BreakstmtContext stmt) { - // TODO - throw new NotImplementedException(); + Token offset = stmt.getStart(); + if (!Objects.isNull(stmt.identifier())) { + return new Break(localVars.get(stmt.identifier().getText()), offset); + } else { + return new Break(TypePlaceholder.fresh(offset), offset); + } + } private Statement convert(Java17Parser.ContinuestmtContext stmt) { @@ -723,7 +800,7 @@ public class StatementGenerator { String localVarName = typePatternCtx.identifier().getText(); RefTypeOrTPHOrWildcardOrGeneric localVarType = TypeGenerator.convert(typePatternCtx.typeType(), reg, generics); localVars.put(localVarName, localVarType); - return new InstanceOf(left, new TypePattern(localVarName, localVarType, typePatternCtx.getStart()), offset); + return new InstanceOf(left, new Pattern(localVarName, localVarType, typePatternCtx.getStart()), offset); default: throw new NotImplementedException(); } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/TypePattern.java b/src/main/java/de/dhbwstuttgart/syntaxtree/TypePattern.java deleted file mode 100644 index 3a6ac754..00000000 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/TypePattern.java +++ /dev/null @@ -1,12 +0,0 @@ -package de.dhbwstuttgart.syntaxtree; - -import org.antlr.v4.runtime.Token; - -import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; - -public class TypePattern extends FormalParameter { - // TypePattern und FormalParameter sind exakt gleich aufgebaut - public TypePattern(String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { - super(name, type, offset); - } -} diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Block.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Block.java index 73a92c7e..bc35364b 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Block.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Block.java @@ -1,4 +1,5 @@ package de.dhbwstuttgart.syntaxtree.statement; + import java.util.*; import de.dhbwstuttgart.syntaxtree.StatementVisitor; @@ -7,20 +8,15 @@ import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation; import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import org.antlr.v4.runtime.Token; - -public class Block extends Statement -{ +public class Block extends Statement { public Block(List statements, Token offset) { - super(TypePlaceholder.fresh(offset), offset); - this.statements = statements; - } + super(TypePlaceholder.fresh(offset), offset); + this.statements = statements; + } - - public List statements = new ArrayList<>(); - public List getStatements() - { + public List getStatements() { return statements; } @@ -29,5 +25,3 @@ public class Block extends Statement visitor.visit(this); } } - - diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/GuardedPattern.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/GuardedPattern.java new file mode 100644 index 00000000..dcfd7665 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/GuardedPattern.java @@ -0,0 +1,22 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import java.util.List; + +import org.antlr.v4.runtime.Token; + +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class GuardedPattern extends Pattern { + + private List conditions; + + public GuardedPattern(List conditions, String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { + super(name, type, offset); + this.conditions = conditions; + } + + public List getConditions() { + return conditions; + } + +} diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/IfStmt.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/IfStmt.java index 4af1e770..2c64af84 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/IfStmt.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/IfStmt.java @@ -7,17 +7,13 @@ import de.dhbwstuttgart.typeinference.constraints.ConstraintSet; import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceInformation; import org.antlr.v4.runtime.Token; - -public class IfStmt extends Statement -{ +public class IfStmt extends Statement { public final Expression expr; public final Statement then_block; public final Statement else_block; - public IfStmt(RefTypeOrTPHOrWildcardOrGeneric type, - Expression expr, Statement thenBlock, Statement elseBlock, Token offset) - { - super(type,offset); + public IfStmt(RefTypeOrTPHOrWildcardOrGeneric type, Expression expr, Statement thenBlock, Statement elseBlock, Token offset) { + super(type, offset); this.expr = expr; this.then_block = thenBlock; this.else_block = elseBlock; diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java index fe4cf9b0..7b9e0555 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/InstanceOf.java @@ -3,7 +3,6 @@ package de.dhbwstuttgart.syntaxtree.statement; import org.antlr.v4.runtime.Token; import de.dhbwstuttgart.syntaxtree.StatementVisitor; -import de.dhbwstuttgart.syntaxtree.TypePattern; import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; @@ -16,7 +15,7 @@ public class InstanceOf extends BinaryExpr { this.reftype = reftype; } - public InstanceOf(Expression expr, TypePattern pattern, Token offset) { + public InstanceOf(Expression expr, Pattern pattern, Token offset) { super(BinaryExpr.Operator.INSTOF, TypePlaceholder.fresh(offset), expr, new LocalVar(pattern.getName(), pattern.getType(), pattern.getOffset()), offset); this.reftype = pattern.getType(); this.name = pattern.getName(); diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Pattern.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Pattern.java new file mode 100644 index 00000000..42230a15 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Pattern.java @@ -0,0 +1,27 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import org.antlr.v4.runtime.Token; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class Pattern extends Expression { + + private String name; + + public Pattern(String name, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { + super(type, offset); + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public void accept(StatementVisitor visitor) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'accept'"); + } + +} diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/RecordPattern.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/RecordPattern.java new file mode 100644 index 00000000..e69de29b diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Switch.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Switch.java index bfe48a0c..452f8298 100644 --- a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Switch.java +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/Switch.java @@ -1,5 +1,8 @@ package de.dhbwstuttgart.syntaxtree.statement; +import java.util.ArrayList; +import java.util.List; + import org.antlr.v4.runtime.Token; import de.dhbwstuttgart.syntaxtree.StatementVisitor; @@ -7,15 +10,18 @@ import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; public class Switch extends Statement { - public Switch(RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { + private List blocks = new ArrayList<>(); + + public Switch(List blocks, RefTypeOrTPHOrWildcardOrGeneric type, Boolean isStatement, Token offset) { super(type, offset); - // TODO Auto-generated constructor stub + if (isStatement) + setStatement(); + this.blocks = blocks; } @Override public void accept(StatementVisitor visitor) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'accept'"); + // visitor.visit(this); } } diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SwitchBlock.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SwitchBlock.java new file mode 100644 index 00000000..7a61ebd6 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SwitchBlock.java @@ -0,0 +1,29 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import java.util.ArrayList; +import java.util.List; + +import org.antlr.v4.runtime.Token; + +public class SwitchBlock extends Block { + + private List labels = new ArrayList<>(); + + private Boolean defaultBlock = false; + + public SwitchBlock(List labels, List statements, Token offset) { + super(statements, offset); + this.labels = labels; + } + + public SwitchBlock(List labels, List statements, Boolean isDefault, Token offset) { + super(statements, offset); + this.labels = labels; + this.defaultBlock = isDefault; + } + + public Boolean isDefault() { + return defaultBlock; + } + +} diff --git a/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SwitchLabel.java b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SwitchLabel.java new file mode 100644 index 00000000..d5e8b1f8 --- /dev/null +++ b/src/main/java/de/dhbwstuttgart/syntaxtree/statement/SwitchLabel.java @@ -0,0 +1,34 @@ +package de.dhbwstuttgart.syntaxtree.statement; + +import org.antlr.v4.runtime.Token; + +import de.dhbwstuttgart.syntaxtree.StatementVisitor; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class SwitchLabel extends Expression { + + private Expression caseExpression; + private Boolean defaultCase = false; + + public SwitchLabel(Expression caseExpression, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { + super(type, offset); + this.caseExpression = caseExpression; + } + + public SwitchLabel(Expression caseExpression, Boolean def, RefTypeOrTPHOrWildcardOrGeneric type, Token offset) { + super(type, offset); + this.caseExpression = caseExpression; + this.defaultCase = def; + } + + public Boolean isDefault() { + return this.defaultCase; + } + + @Override + public void accept(StatementVisitor visitor) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'accept'"); + } + +} diff --git a/src/test/java/syntaxtreegenerator/TestNewFeatures.java b/src/test/java/syntaxtreegenerator/TestNewFeatures.java index 3c6f13e3..e5813d86 100644 --- a/src/test/java/syntaxtreegenerator/TestNewFeatures.java +++ b/src/test/java/syntaxtreegenerator/TestNewFeatures.java @@ -68,6 +68,25 @@ public class TestNewFeatures { fail("An error occured while generating the AST for applyLambda.jav"); } } + + @Test + public void switchTest() { + try { + /* + * FileInputStream fileIn = new FileInputStream(javFiles.get("Record")[1]); String expectedAST = new String(fileIn.readAllBytes()); fileIn.close(); expectedAST = expectedAST.replaceAll("TPH [A-Z]+", "TPH"); + */ + File srcfile = javFiles.get("Switch")[0]; + JavaTXCompiler compiler = new JavaTXCompiler(srcfile); + String resultingAST = new String(ASTPrinter.print(compiler.sourceFiles.get(srcfile))); + resultingAST = resultingAST.replaceAll("TPH [A-Z]+", "TPH"); + // System.out.println("Expected:\n" + new String(expectedAST)); + System.out.println("Result:\n" + new String(resultingAST)); + // assertEquals("Comparing expected and resulting AST for applyLambda.jav", expectedAST, resultingAST); + } catch (Exception exc) { + exc.printStackTrace(); + fail("An error occured while generating the AST for applyLambda.jav"); + } + } } class JavFilter implements FileFilter {