Merge branch 'refs/heads/main' into testsuites

This commit is contained in:
JonathanFleischmann 2024-07-03 22:15:31 +02:00
commit 09319df7f4
8 changed files with 116 additions and 72 deletions

View File

@ -9,7 +9,7 @@
## Erbrachte Leistungen ## Erbrachte Leistungen
- Laura Schleicher: Grammatik entwickeln, Records, Statements als Liste zurückgeben, Generator, Syntactic Sugar auflösen - Laura Schleicher: Grammatik entwickeln, Records, Statements als Liste zurückgeben, Generator, Syntactic Sugar auflösen
- Julian Kraus: Grammatik entwickeln, Generator, Syntactic Sugar auflösen, custom Exceptions im Parser - Julian Kraus: Grammatik entwickeln, Generator, Syntactic Sugar auflösen, Parser Exceptions sammeln
- Ahmad Juha: Typcheck - Ahmad Juha: Typcheck
- Simon Wittmann: Codegen und Tool für ASM - Simon Wittmann: Codegen und Tool für ASM
- Jonathan Fleischmann: - Jonathan Fleischmann:

View File

@ -14,8 +14,11 @@ import java.util.List;
public class ASTGenerator { public class ASTGenerator {
public static CollectingErrorListener errorListener;
public static Class generateAST(DecafParser.ClassContext ctx, CollectingErrorListener errorListener2) {
errorListener = errorListener2;
public static Class generateAST(DecafParser.ClassContext ctx) {
List<Declaration> declarations = new ArrayList<>(); List<Declaration> declarations = new ArrayList<>();
if (ctx.field() != null) { if (ctx.field() != null) {
declarations = ctx.field().stream().map(ASTGenerator::generateFieldVariable).toList(); declarations = ctx.field().stream().map(ASTGenerator::generateFieldVariable).toList();
@ -30,9 +33,9 @@ public class ASTGenerator {
Block mainmeth = null; Block mainmeth = null;
if (!ctx.mainmeth().isEmpty()) { if (!ctx.mainmeth().isEmpty()) {
if (ctx.mainmeth().size() > 1) { if (ctx.mainmeth().size() > 1) {
throw new RuntimeException("Only one main method allowed!"); errorListener.generatorError("Only one main method allowed!");
} }
mainmeth = new BlockGenerator().visit(ctx.mainmeth().get(0).block()); mainmeth = new BlockGenerator(errorListener).visit(ctx.mainmeth().get(0).block());
} }
List<Method> meths = new ArrayList<>(); List<Method> meths = new ArrayList<>();
if (ctx.meth() != null) { if (ctx.meth() != null) {
@ -55,7 +58,7 @@ public class ASTGenerator {
if (ctx.params() != null) { if (ctx.params() != null) {
params = ctx.params().param().stream().map(ASTGenerator::generateParameter).toList(); params = ctx.params().param().stream().map(ASTGenerator::generateParameter).toList();
} }
Block block = new BlockGenerator().visit(ctx.block()); Block block = new BlockGenerator(errorListener).visit(ctx.block());
return new Method(getType(ctx.returntype()), ctx.id().IDENTIFIER().getText(), params, block); return new Method(getType(ctx.returntype()), ctx.id().IDENTIFIER().getText(), params, block);
} }
@ -64,7 +67,7 @@ public class ASTGenerator {
if (ctx.params() != null) { if (ctx.params() != null) {
params = ctx.params().param().stream().map(ASTGenerator::generateParameter).toList(); params = ctx.params().param().stream().map(ASTGenerator::generateParameter).toList();
} }
Block block = new BlockGenerator().visit(ctx.block()); Block block = new BlockGenerator(errorListener).visit(ctx.block());
return new Constructor( ctx.id().getText(), params, block); return new Constructor( ctx.id().getText(), params, block);
} }
@ -78,7 +81,8 @@ public class ASTGenerator {
if (ctx.id() != null) { if (ctx.id() != null) {
return Type.REFERENCE(ctx.id().getText()); return Type.REFERENCE(ctx.id().getText());
} }
throw new RuntimeException("No type found!"); errorListener.generatorError("No type found");
return null;
} }
public static Type getType(DecafParser.ReturntypeContext ctx) { public static Type getType(DecafParser.ReturntypeContext ctx) {
if (ctx.type() != null){ if (ctx.type() != null){
@ -87,6 +91,7 @@ public class ASTGenerator {
if (ctx.VOID() != null){ if (ctx.VOID() != null){
return Type.VOID; return Type.VOID;
} }
throw new RuntimeException("No type found!"); errorListener.generatorError("No type found");
return null;
} }
} }

View File

@ -10,17 +10,22 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class BlockGenerator extends DecafBaseVisitor<Block> { public class BlockGenerator extends DecafBaseVisitor<Block> {
private final CollectingErrorListener errorListener;
public BlockGenerator(CollectingErrorListener errorListener) {
this.errorListener = errorListener;
}
@Override @Override
public Block visitBlock(DecafParser.BlockContext ctx) { public Block visitBlock(DecafParser.BlockContext ctx) {
List<Statement> statements = new ArrayList<>(ctx.stmt().size()); List<Statement> statements = new ArrayList<>(ctx.stmt().size());
for (DecafParser.StmtContext stmtContext : ctx.stmt()) { for (DecafParser.StmtContext stmtContext : ctx.stmt()) {
List<Statement> statementList = new StatementGenerator().visit(stmtContext); List<Statement> statementList = new StatementGenerator(errorListener).visit(stmtContext);
if (statementList != null){ if (statementList != null){
statements.addAll(statementList); statements.addAll(statementList);
} }
} }
if (ctx.return_() != null){ if (ctx.return_() != null){
statements.add(ctx.return_().expr() == null ? new Return(null) : new Return(new ExpressionGenerator().visit(ctx.return_().expr()))); statements.add(ctx.return_().expr() == null ? new Return(null) : new Return(new ExpressionGenerator(errorListener).visit(ctx.return_().expr())));
} }
return new Block(statements); return new Block(statements);
} }

View File

@ -0,0 +1,26 @@
package de.maishai;
import org.antlr.v4.runtime.BaseErrorListener;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import java.util.ArrayList;
import java.util.List;
public class CollectingErrorListener extends BaseErrorListener {
private final List<String> errors = new ArrayList<>();
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
errors.add("Error in line " + line + ":" + charPositionInLine + " " + msg);
}
public void generatorError(String msg) {
errors.add("Error: " + msg);
}
public List<String> getErrors() {
return errors;
}
}

View File

@ -23,23 +23,30 @@ public class Compiler {
public static Program generateAST(List<String> fromSources) { public static Program generateAST(List<String> fromSources) {
List<Class> classes = new ArrayList<>(); List<Class> classes = new ArrayList<>();
CollectingErrorListener errorListener = new CollectingErrorListener();
for (String fromSource : fromSources) { for (String fromSource : fromSources) {
CharStream input = CharStreams.fromString(fromSource); CharStream input = CharStreams.fromString(fromSource);
DecafLexer lexer = new DecafLexer(input); DecafLexer lexer = new DecafLexer(input);
//add custom error listener //add custom error listener
lexer.removeErrorListeners(); lexer.removeErrorListeners();
lexer.addErrorListener(ThrowingErrorListener.INSTANCE); lexer.addErrorListener(errorListener);
CommonTokenStream tokens = new CommonTokenStream(lexer); CommonTokenStream tokens = new CommonTokenStream(lexer);
DecafParser parser = new DecafParser(tokens); DecafParser parser = new DecafParser(tokens);
//add custom error listener //add custom error listener
parser.removeErrorListeners(); parser.removeErrorListeners();
parser.addErrorListener(ThrowingErrorListener.INSTANCE); parser.addErrorListener(errorListener);
DecafParser.ClassContext tree = parser.class_(); //Parsen DecafParser.ClassContext tree = parser.class_(); //Parsen
classes.add(ASTGenerator.generateAST(tree)); classes.add(ASTGenerator.generateAST(tree, errorListener));
}
for (String error : errorListener.getErrors()) {
LOGGER.severe(error);
}
if (!errorListener.getErrors().isEmpty()) {
throw new RuntimeException("Errors during parsing");
} }
return new Program(classes); return new Program(classes);
} }

View File

@ -11,9 +11,15 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ExpressionGenerator extends DecafBaseVisitor<Expression> { public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
private final CollectingErrorListener errorListener;
public ExpressionGenerator(CollectingErrorListener errorListener) {
this.errorListener = errorListener;
}
@Override @Override
public Expression visitBinaryOperation(DecafParser.BinaryOperationContext ctx) { public Expression visitBinaryOperation(DecafParser.BinaryOperationContext ctx) {
return generateBinary(ctx); return generateBinary(ctx, errorListener);
} }
@Override @Override
@ -25,12 +31,13 @@ public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
if (ctx.unaryOp().SUB() != null) { if (ctx.unaryOp().SUB() != null) {
return new Unary(UnaryOperator.SUB, expr); return new Unary(UnaryOperator.SUB, expr);
} }
throw new RuntimeException("No unary operator found."); errorListener.generatorError("No unary operator found");
return null;
} }
@Override @Override
public Expression visitConstant(DecafParser.ConstantContext ctx) { public Expression visitConstant(DecafParser.ConstantContext ctx) {
return generateConstant(ctx.literal()); return generateConstant(ctx.literal(), errorListener);
} }
@Override @Override
@ -46,7 +53,7 @@ public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
Expression recipient = null; Expression recipient = null;
if (ctx.fieldVarAccess().recipient() != null) { if (ctx.fieldVarAccess().recipient() != null) {
List<DecafParser.RecipientContext> recipientList = ctx.fieldVarAccess().recipient(); List<DecafParser.RecipientContext> recipientList = ctx.fieldVarAccess().recipient();
recipient = ExpressionGenerator.generateRecursiveOwnerChain(recipientList, ctx.fieldVarAccess().newCall() != null ? StatementGenerator.generateNew(ctx.fieldVarAccess().newCall()) : null, isField); recipient = ExpressionGenerator.generateRecursiveOwnerChain(recipientList, ctx.fieldVarAccess().newCall() != null ? StatementGenerator.generateNew(ctx.fieldVarAccess().newCall(), errorListener) : null, isField, errorListener);
} }
if (recipient == null) { if (recipient == null) {
return new FieldVarAccess(isField, null, ctx.fieldVarAccess().id().IDENTIFIER().getText()); return new FieldVarAccess(isField, null, ctx.fieldVarAccess().id().IDENTIFIER().getText());
@ -54,7 +61,7 @@ public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
return new FieldVarAccess(true, recipient, ctx.fieldVarAccess().id().IDENTIFIER().getText()); return new FieldVarAccess(true, recipient, ctx.fieldVarAccess().id().IDENTIFIER().getText());
} }
public static Expression generateConstant(DecafParser.LiteralContext ctx) { public static Expression generateConstant(DecafParser.LiteralContext ctx, CollectingErrorListener errorListener) {
if (ctx.NUMBER() != null) { if (ctx.NUMBER() != null) {
return new IntLiteral(Integer.valueOf(ctx.NUMBER().getText())); return new IntLiteral(Integer.valueOf(ctx.NUMBER().getText()));
} }
@ -63,17 +70,19 @@ public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
} }
if (ctx.CHARLITERAL() != null) { if (ctx.CHARLITERAL() != null) {
if (ctx.CHARLITERAL().getText().length() != 3) { if (ctx.CHARLITERAL().getText().length() != 3) {
throw new RuntimeException("Wrong format for Char literal. Good format: 'c' Bad format: " + ctx.CHARLITERAL().getText()); errorListener.generatorError("Wrong format for Char literal. Good format: 'c' Bad format: " + ctx.CHARLITERAL().getText());
return null;
} }
return new CharLiteral(ctx.CHARLITERAL().getText().charAt(1)); return new CharLiteral(ctx.CHARLITERAL().getText().charAt(1));
} }
throw new RuntimeException("No literal found!"); errorListener.generatorError("No literal found");
return null;
} }
public static Binary generateBinary(DecafParser.BinaryOperationContext ctx) { public static Binary generateBinary(DecafParser.BinaryOperationContext ctx, CollectingErrorListener errorListener) {
ExpressionGenerator eGen = new ExpressionGenerator(); ExpressionGenerator eGen = new ExpressionGenerator(errorListener);
Binary binary = new Binary(eGen.visit(ctx.expr().get(0)) // left side Binary binary = new Binary(eGen.visit(ctx.expr().get(0)) // left side
, generateOperator(ctx.binaryOp()) //operator , generateOperator(ctx.binaryOp(), errorListener) //operator
, eGen.visit(ctx.expr().get(1))); //right side , eGen.visit(ctx.expr().get(1))); //right side
binary = pointBeforeLineLogic(ctx, binary); binary = pointBeforeLineLogic(ctx, binary);
@ -81,7 +90,7 @@ public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
return binary; return binary;
} }
public static Operator generateOperator(DecafParser.BinaryOpContext ctx) { public static Operator generateOperator(DecafParser.BinaryOpContext ctx, CollectingErrorListener errorListener) {
if (ctx.ADD() != null) return Operator.ADD; if (ctx.ADD() != null) return Operator.ADD;
if (ctx.SUB() != null) return Operator.SUB; if (ctx.SUB() != null) return Operator.SUB;
if (ctx.MUL() != null) return Operator.MUL; if (ctx.MUL() != null) return Operator.MUL;
@ -95,7 +104,8 @@ public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
if (ctx.NE() != null) return Operator.NE; if (ctx.NE() != null) return Operator.NE;
if (ctx.AND() != null) return Operator.AND; if (ctx.AND() != null) return Operator.AND;
if (ctx.OR() != null) return Operator.OR; if (ctx.OR() != null) return Operator.OR;
throw new RuntimeException("No operator found!"); errorListener.generatorError("No operator found");
return null;
} }
@Override @Override
@ -109,7 +119,7 @@ public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
Expression recursiveOwnerChain = null; Expression recursiveOwnerChain = null;
if (ctx.methCall().recipient() != null) { if (ctx.methCall().recipient() != null) {
List<DecafParser.RecipientContext> recipientList = ctx.methCall().recipient(); List<DecafParser.RecipientContext> recipientList = ctx.methCall().recipient();
recursiveOwnerChain = ExpressionGenerator.generateRecursiveOwnerChain(recipientList, ctx.methCall().newCall() != null ? StatementGenerator.generateNew(ctx.methCall().newCall()) : null, isField); recursiveOwnerChain = ExpressionGenerator.generateRecursiveOwnerChain(recipientList, ctx.methCall().newCall() != null ? StatementGenerator.generateNew(ctx.methCall().newCall(), errorListener) : null, isField, errorListener);
} }
List<Expression> args = new ArrayList<>(); List<Expression> args = new ArrayList<>();
if (ctx.methCall().methName().args() != null) { if (ctx.methCall().methName().args() != null) {
@ -126,11 +136,11 @@ public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
@Override @Override
public Expression visitNew(DecafParser.NewContext ctx) { public Expression visitNew(DecafParser.NewContext ctx) {
return StatementGenerator.generateNew(ctx.newCall()); return StatementGenerator.generateNew(ctx.newCall(), errorListener);
} }
public static Expression generateRecursiveOwnerChain(List<DecafParser.RecipientContext> ctxList, Expression recipient, Boolean isField) { public static Expression generateRecursiveOwnerChain(List<DecafParser.RecipientContext> ctxList, Expression recipient, Boolean isField, CollectingErrorListener errorListener) {
if (ctxList.isEmpty()) { if (ctxList.isEmpty()) {
return recipient; return recipient;
} }
@ -141,23 +151,24 @@ public class ExpressionGenerator extends DecafBaseVisitor<Expression> {
if (ctxList.isEmpty()) { if (ctxList.isEmpty()) {
return new FieldVarAccess(isField, recipient, ctx.id().IDENTIFIER().getText()); return new FieldVarAccess(isField, recipient, ctx.id().IDENTIFIER().getText());
} }
return new FieldVarAccess(true, generateRecursiveOwnerChain(ctxList, recipient, isField), ctx.id().IDENTIFIER().getText()); return new FieldVarAccess(true, generateRecursiveOwnerChain(ctxList, recipient, isField, errorListener), ctx.id().IDENTIFIER().getText());
} }
if (ctx.methName() != null) { if (ctx.methName() != null) {
List<Expression> args = new ArrayList<>(); List<Expression> args = new ArrayList<>();
if (ctx.methName().args() != null) { if (ctx.methName().args() != null) {
for (var expr : ctx.methName().args().expr()) { for (var expr : ctx.methName().args().expr()) {
Expression astExpr = expr.accept(new ExpressionGenerator()); Expression astExpr = expr.accept(new ExpressionGenerator(errorListener));
args.add(astExpr); args.add(astExpr);
} }
} }
if (ctxList.isEmpty()) { if (ctxList.isEmpty()) {
return new MethodCall(new FieldVarAccess(isField, recipient, ctx.methName().id().IDENTIFIER().getText()), args); return new MethodCall(new FieldVarAccess(isField, recipient, ctx.methName().id().IDENTIFIER().getText()), args);
} }
return new MethodCall(new FieldVarAccess(true, generateRecursiveOwnerChain(ctxList, recipient, isField), ctx.methName().id().IDENTIFIER().getText()), args); return new MethodCall(new FieldVarAccess(true, generateRecursiveOwnerChain(ctxList, recipient, isField, errorListener), ctx.methName().id().IDENTIFIER().getText()), args);
} }
throw new RuntimeException(); errorListener.generatorError("Unknown Recipient while generating Recursive Owner Chain");
return null;
} }
private static Binary pointBeforeLineLogic(DecafParser.BinaryOperationContext ctx, Binary binary) { private static Binary pointBeforeLineLogic(DecafParser.BinaryOperationContext ctx, Binary binary) {

View File

@ -10,18 +10,24 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class StatementGenerator extends DecafBaseVisitor<List<Statement>> { public class StatementGenerator extends DecafBaseVisitor<List<Statement>> {
private final CollectingErrorListener errorListener;
public StatementGenerator(CollectingErrorListener errorListener) {
this.errorListener = errorListener;
}
@Override @Override
public List<Statement> visitIf(DecafParser.IfContext ctx) { public List<Statement> visitIf(DecafParser.IfContext ctx) {
Expression expr = new ExpressionGenerator().visit(ctx.ifCall().expr()); Expression expr = new ExpressionGenerator(errorListener).visit(ctx.ifCall().expr());
Block ifBlock = new BlockGenerator().visit(ctx.ifCall().block(0)); Block ifBlock = new BlockGenerator(errorListener).visit(ctx.ifCall().block(0));
Block elseBlock = null; Block elseBlock = null;
if (ctx.ifCall().block().size() == 2) { if (ctx.ifCall().block().size() == 2) {
elseBlock = new BlockGenerator().visit(ctx.ifCall().block(1)); elseBlock = new BlockGenerator(errorListener).visit(ctx.ifCall().block(1));
} }
if (ctx.ifCall().elseIf() != null){ if (ctx.ifCall().elseIf() != null){
for (int i = ctx.ifCall().elseIf().size()-1; i >= 0; i--) { for (int i = ctx.ifCall().elseIf().size()-1; i >= 0; i--) {
IfElse current = new IfElse(new ExpressionGenerator().visit(ctx.ifCall().elseIf(i).expr()), IfElse current = new IfElse(new ExpressionGenerator(errorListener).visit(ctx.ifCall().elseIf(i).expr()),
new BlockGenerator().visit(ctx.ifCall().elseIf(i).block()), new BlockGenerator(errorListener).visit(ctx.ifCall().elseIf(i).block()),
elseBlock); elseBlock);
elseBlock = new Block(List.of(current)); elseBlock = new Block(List.of(current));
} }
@ -33,12 +39,12 @@ public class StatementGenerator extends DecafBaseVisitor<List<Statement>> {
@Override @Override
public List<Statement> visitFor(DecafParser.ForContext ctx) { public List<Statement> visitFor(DecafParser.ForContext ctx) {
Expression expr = new ExpressionGenerator().visit(ctx.expr()); Expression expr = new ExpressionGenerator(errorListener).visit(ctx.expr());
Assignment update = generateAssign(ctx.assign().get(ctx.assign().size() - 1)); Assignment update = generateAssign(ctx.assign().get(ctx.assign().size() - 1));
Block block = new BlockGenerator().visit(ctx.block()); Block block = new BlockGenerator(errorListener).visit(ctx.block());
if (ctx.assign().size() == 1) { if (ctx.assign().size() == 1) {
Declaration declaration = new Declaration(ctx.localVarWithInitialization().id().IDENTIFIER().getText(), ASTGenerator.getType(ctx.localVarWithInitialization().type())); Declaration declaration = new Declaration(ctx.localVarWithInitialization().id().IDENTIFIER().getText(), ASTGenerator.getType(ctx.localVarWithInitialization().type()));
Expression initialization = new ExpressionGenerator().visit(ctx.localVarWithInitialization().expr()); Expression initialization = new ExpressionGenerator(errorListener).visit(ctx.localVarWithInitialization().expr());
Assignment init = new Assignment(new FieldVarAccess(false, null, declaration.name()), initialization); Assignment init = new Assignment(new FieldVarAccess(false, null, declaration.name()), initialization);
return List.of(declaration, new For(init, expr, update, block)); return List.of(declaration, new For(init, expr, update, block));
} }
@ -48,15 +54,15 @@ public class StatementGenerator extends DecafBaseVisitor<List<Statement>> {
@Override @Override
public List<Statement> visitWhile(DecafParser.WhileContext ctx) { public List<Statement> visitWhile(DecafParser.WhileContext ctx) {
Expression expr = new ExpressionGenerator().visit(ctx.expr()); Expression expr = new ExpressionGenerator(errorListener).visit(ctx.expr());
Block block = new BlockGenerator().visit(ctx.block()); Block block = new BlockGenerator(errorListener).visit(ctx.block());
return List.of(new While(expr, block)); return List.of(new While(expr, block));
} }
@Override @Override
public List<Statement> visitDoWhile(DecafParser.DoWhileContext ctx) { public List<Statement> visitDoWhile(DecafParser.DoWhileContext ctx) {
Block block = new BlockGenerator().visit(ctx.block()); Block block = new BlockGenerator(errorListener).visit(ctx.block());
Expression expr = new ExpressionGenerator().visit(ctx.expr()); Expression expr = new ExpressionGenerator(errorListener).visit(ctx.expr());
return List.of(new DoWhile(block, expr)); return List.of(new DoWhile(block, expr));
} }
@ -79,7 +85,7 @@ public class StatementGenerator extends DecafBaseVisitor<List<Statement>> {
@Override @Override
public List<Statement> visitLocalVarDecWithInitialization(DecafParser.LocalVarDecWithInitializationContext ctx) { public List<Statement> visitLocalVarDecWithInitialization(DecafParser.LocalVarDecWithInitializationContext ctx) {
Declaration declaration = new Declaration(ctx.localVarWithInitialization().id().IDENTIFIER().getText(), ASTGenerator.getType(ctx.localVarWithInitialization().type())); Declaration declaration = new Declaration(ctx.localVarWithInitialization().id().IDENTIFIER().getText(), ASTGenerator.getType(ctx.localVarWithInitialization().type()));
Expression initialization = new ExpressionGenerator().visit(ctx.localVarWithInitialization().expr()); Expression initialization = new ExpressionGenerator(errorListener).visit(ctx.localVarWithInitialization().expr());
return List.of(declaration, new Assignment(new FieldVarAccess(false, null, declaration.name()), initialization)); return List.of(declaration, new Assignment(new FieldVarAccess(false, null, declaration.name()), initialization));
} }
@ -91,14 +97,14 @@ public class StatementGenerator extends DecafBaseVisitor<List<Statement>> {
@Override @Override
public List<Statement> visitPrint(DecafParser.PrintContext ctx) { public List<Statement> visitPrint(DecafParser.PrintContext ctx) {
return List.of(new Print(new ExpressionGenerator().visit(ctx.expr()))); return List.of(new Print(new ExpressionGenerator(errorListener).visit(ctx.expr())));
} }
private Assignment generateAssign(DecafParser.AssignContext ctx) { private Assignment generateAssign(DecafParser.AssignContext ctx) {
FieldVarAccess fieldVarAccess; FieldVarAccess fieldVarAccess;
if (ctx.incrDecr() == null) { if (ctx.incrDecr() == null) {
fieldVarAccess = generateField(ctx.fieldVarAccess()); fieldVarAccess = generateField(ctx.fieldVarAccess());
Expression expr = resolveFancyAssign(ctx.assignSign(), fieldVarAccess, new ExpressionGenerator().visit(ctx.expr())); Expression expr = resolveFancyAssign(ctx.assignSign(), fieldVarAccess, new ExpressionGenerator(errorListener).visit(ctx.expr()), errorListener);
return new Assignment(fieldVarAccess, expr); return new Assignment(fieldVarAccess, expr);
} }
fieldVarAccess = generateField(ctx.incrDecr().fieldVarAccess()); fieldVarAccess = generateField(ctx.incrDecr().fieldVarAccess());
@ -110,7 +116,7 @@ public class StatementGenerator extends DecafBaseVisitor<List<Statement>> {
Boolean isField = fieldIdContext.THIS() != null; Boolean isField = fieldIdContext.THIS() != null;
Expression recipient = null; Expression recipient = null;
if (fieldIdContext.recipient() != null) { if (fieldIdContext.recipient() != null) {
recipient = ExpressionGenerator.generateRecursiveOwnerChain(fieldIdContext.recipient(), null, isField); recipient = ExpressionGenerator.generateRecursiveOwnerChain(fieldIdContext.recipient(), null, isField, errorListener);
} }
if (recipient == null) { if (recipient == null) {
return new FieldVarAccess(isField, null, fieldIdContext.id().IDENTIFIER().getText()); return new FieldVarAccess(isField, null, fieldIdContext.id().IDENTIFIER().getText());
@ -130,14 +136,14 @@ public class StatementGenerator extends DecafBaseVisitor<List<Statement>> {
List<Expression> args = new ArrayList<>(); List<Expression> args = new ArrayList<>();
if (ctx.methCall().methName().args() != null) { if (ctx.methCall().methName().args() != null) {
for (var expr : ctx.methCall().methName().args().expr()) { for (var expr : ctx.methCall().methName().args().expr()) {
Expression astExpr = expr.accept(new ExpressionGenerator()); Expression astExpr = expr.accept(new ExpressionGenerator(errorListener));
args.add(astExpr); args.add(astExpr);
} }
} }
Expression recursiveOwnerChain = null; Expression recursiveOwnerChain = null;
if (ctx.methCall().recipient() != null) { if (ctx.methCall().recipient() != null) {
List<DecafParser.RecipientContext> recipientList = ctx.methCall().recipient(); List<DecafParser.RecipientContext> recipientList = ctx.methCall().recipient();
recursiveOwnerChain = ExpressionGenerator.generateRecursiveOwnerChain(recipientList, ctx.methCall().newCall() != null ? generateNew(ctx.methCall().newCall()) : null, isField); recursiveOwnerChain = ExpressionGenerator.generateRecursiveOwnerChain(recipientList, ctx.methCall().newCall() != null ? generateNew(ctx.methCall().newCall(), errorListener) : null, isField, errorListener);
} }
if (recursiveOwnerChain == null) { if (recursiveOwnerChain == null) {
return List.of(new MethodCall(new FieldVarAccess(isField, null, ctx.methCall().methName().id().IDENTIFIER().getText()), args)); return List.of(new MethodCall(new FieldVarAccess(isField, null, ctx.methCall().methName().id().IDENTIFIER().getText()), args));
@ -147,22 +153,22 @@ public class StatementGenerator extends DecafBaseVisitor<List<Statement>> {
@Override @Override
public List<Statement> visitNew(DecafParser.NewContext ctx) { public List<Statement> visitNew(DecafParser.NewContext ctx) {
return List.of( generateNew(ctx.newCall())); return List.of( generateNew(ctx.newCall(), errorListener));
} }
public static New generateNew(DecafParser.NewCallContext ctx){ public static New generateNew(DecafParser.NewCallContext ctx, CollectingErrorListener errorListener) {
Type type = ASTGenerator.getType(ctx.type()); Type type = ASTGenerator.getType(ctx.type());
List<Expression> args = new ArrayList<>(); List<Expression> args = new ArrayList<>();
if (ctx.args() != null) { if (ctx.args() != null) {
for (var expr : ctx.args().expr()) { for (var expr : ctx.args().expr()) {
Expression astExpr = expr.accept(new ExpressionGenerator()); Expression astExpr = expr.accept(new ExpressionGenerator(errorListener));
args.add(astExpr); args.add(astExpr);
} }
} }
return new New(type, args); return new New(type, args);
} }
public static Expression resolveFancyAssign(DecafParser.AssignSignContext ctx, FieldVarAccess fieldVarAccess, Expression expression) { public static Expression resolveFancyAssign(DecafParser.AssignSignContext ctx, FieldVarAccess fieldVarAccess, Expression expression, CollectingErrorListener errorListener) {
if (ctx.ASSIGN() != null) if (ctx.ASSIGN() != null)
return expression; return expression;
if (ctx.ADD_ASSIGN() != null) if (ctx.ADD_ASSIGN() != null)
@ -175,6 +181,7 @@ public class StatementGenerator extends DecafBaseVisitor<List<Statement>> {
return new Binary(fieldVarAccess, Operator.DIV, expression); return new Binary(fieldVarAccess, Operator.DIV, expression);
if (ctx.MOD_ASSIGN() != null) if (ctx.MOD_ASSIGN() != null)
return new Binary(fieldVarAccess, Operator.MOD, expression); return new Binary(fieldVarAccess, Operator.MOD, expression);
throw new RuntimeException("No assign sign found!"); errorListener.generatorError("No assign sign found");
return null;
} }
} }

View File

@ -1,17 +0,0 @@
package de.maishai;
import org.antlr.v4.runtime.BaseErrorListener;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.misc.ParseCancellationException;
public class ThrowingErrorListener extends BaseErrorListener {
public static final ThrowingErrorListener INSTANCE = new ThrowingErrorListener();
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e)
throws ParseCancellationException {
throw new ParseCancellationException("Error in line " + line + ":" + charPositionInLine + " " + msg);
}
}