mirror of
https://github.com/JonathanFleischmann/CompilerULTIMATE.git
synced 2024-12-27 09:08:04 +00:00
collect parser errors
This commit is contained in:
parent
a5d13fd2a9
commit
e23ec8ad82
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
26
src/main/java/de/maishai/CollectingErrorListener.java
Normal file
26
src/main/java/de/maishai/CollectingErrorListener.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -23,23 +23,27 @@ 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);
|
||||||
}
|
}
|
||||||
return new Program(classes);
|
return new Program(classes);
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user