Declaration is now a Statement and Varaibles can be declared anywhere BUT now it actually all get's parsed in the right order

This commit is contained in:
laurenz 2024-05-18 16:18:52 +02:00
parent 4b69908ed7
commit 9757c082e1
17 changed files with 719 additions and 515 deletions

View File

@ -14,9 +14,9 @@ constructor: PUBLIC id '(' params? ')' block;
params : param (',' param)*; params : param (',' param)*;
param : type id; param : type id;
block : '{' (localVar | stmt)* return? '}'; block : '{' (stmt)* return? '}';
localVar : type id ';' localVar : type id;
| type id '=' expr';'; localVarWithInitialization: type id '=' expr;
return: 'return' expr ';' return: 'return' expr ';'
| 'return' ';' | 'return' ';'
; ;
@ -27,6 +27,8 @@ stmt : 'if' '(' expr ')' block ('else' block)? #If
| 'while' '(' expr ')' block #While | 'while' '(' expr ')' block #While
| 'do' block 'while' '(' expr ')' ';'? #DoWhile | 'do' block 'while' '(' expr ')' ';'? #DoWhile
| 'break' ';' #Break | 'break' ';' #Break
| localVar ';' #LocalVarDec
| localVarWithInitialization ';' #LocalVarDecWithInitialization
| assign ';' #Assignment | assign ';' #Assignment
| stmtexpr ';' #StatementExpressionstmt | stmtexpr ';' #StatementExpressionstmt
; ;

View File

@ -1,8 +1,12 @@
package de.maishai; package de.maishai;
import de.maishai.antlr.DecafParser; import de.maishai.antlr.DecafParser;
import de.maishai.ast.records.*; import de.maishai.ast.records.Block;
import de.maishai.ast.records.Class; import de.maishai.ast.records.Class;
import de.maishai.ast.records.Constructor;
import de.maishai.ast.records.Declaration;
import de.maishai.ast.records.Method;
import de.maishai.ast.records.Parameter;
import de.maishai.typedast.Type; import de.maishai.typedast.Type;
import java.util.ArrayList; import java.util.ArrayList;
@ -21,7 +25,7 @@ public class ASTGenerator {
constructors = ctx.constructor().stream().map(ASTGenerator::generateConstructor).toList(); constructors = ctx.constructor().stream().map(ASTGenerator::generateConstructor).toList();
} }
else { else {
constructors.add(new Constructor(ctx.id().IDENTIFIER().getText(), List.of(), new Block(List.of(), List.of()))); constructors.add(new Constructor(ctx.id().IDENTIFIER().getText(), List.of(), new Block(List.of())));
} }
List<Method> meths = new ArrayList<>(); List<Method> meths = new ArrayList<>();
if (ctx.meth() != null) { if (ctx.meth() != null) {

View File

@ -2,24 +2,23 @@ package de.maishai;
import de.maishai.antlr.DecafBaseVisitor; import de.maishai.antlr.DecafBaseVisitor;
import de.maishai.antlr.DecafParser; import de.maishai.antlr.DecafParser;
import de.maishai.ast.records.Declaration; import de.maishai.ast.records.Block;
import de.maishai.ast.records.Return; import de.maishai.ast.records.Return;
import de.maishai.ast.records.Statement; import de.maishai.ast.records.Statement;
import de.maishai.ast.records.Block;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class BlockGenerator extends DecafBaseVisitor<Block> { public class BlockGenerator extends DecafBaseVisitor<Block> {
@Override @Override
public Block visitBlock(DecafParser.BlockContext ctx) { public Block visitBlock(DecafParser.BlockContext ctx) {
List<Declaration> vars = ctx.localVar().stream().map(var -> new VariableGenerator().visit(var)).toList(); List<Statement> statements = new ArrayList<>(ctx.stmt().size());
List<Statement> statements = VariableGenerator.generateInstanciations(ctx.localVar());
for (DecafParser.StmtContext stmtContext : ctx.stmt()) { for (DecafParser.StmtContext stmtContext : ctx.stmt()) {
statements.add(new StatementGenerator().visit(stmtContext)); statements.addAll(new StatementGenerator().visit(stmtContext));
} }
if (ctx.return_() != null){ if (ctx.return_() != null){
statements.add(ctx.return_().isEmpty() ? new Return(null) : new Return(new ExpressionGenerator().visit(ctx.return_()))); statements.add(ctx.return_().isEmpty() ? new Return(null) : new Return(new ExpressionGenerator().visit(ctx.return_())));
} }
return new Block(vars, statements); return new Block(statements);
} }
} }

View File

@ -18,6 +18,25 @@ import java.util.List;
*/ */
public class Compiler { public class Compiler {
public static void main(String[] args) {
generateAST(List.of("""
public class E2ETests {
char ZZ;
int p;
public E2ETests() {
this.ZZ = 'z';
}
public int method(){
x += 4;
this.p = x;
int x = 5;
return this.p;
}
}
"""));
}
public static Program generateAST(List<String> fromSources) { public static Program generateAST(List<String> fromSources) {
List<Class> classes = new ArrayList<>(); List<Class> classes = new ArrayList<>();
for (String fromSource : fromSources) { for (String fromSource : fromSources) {
@ -97,10 +116,10 @@ public class Compiler {
} }
} }
public static void main(String[] args) { // public static void main(String[] args) {
generateByteCodeFileFromFile(List.of("src/main/resources/JavaTestfiles/ClassWithConstructor.java", // generateByteCodeFileFromFile(List.of("src/main/resources/JavaTestfiles/ClassWithConstructor.java",
"src/main/resources/JavaTestfiles/ClassWithConstructorAndMethodCall.java", // "src/main/resources/JavaTestfiles/ClassWithConstructorAndMethodCall.java",
"src/main/resources/JavaTestfiles/ComplexClass.java"), // "src/main/resources/JavaTestfiles/ComplexClass.java"),
List.of("ClassWithConstructor","ClassWithConstructorAndMethodCall","ComplexClass")); // List.of("ClassWithConstructor","ClassWithConstructorAndMethodCall","ComplexClass"));
} // }
} }

View File

@ -3,57 +3,82 @@ package de.maishai;
import de.maishai.antlr.DecafBaseVisitor; import de.maishai.antlr.DecafBaseVisitor;
import de.maishai.antlr.DecafParser; import de.maishai.antlr.DecafParser;
import de.maishai.ast.Operator; import de.maishai.ast.Operator;
import de.maishai.ast.records.Assignment;
import de.maishai.ast.records.Binary;
import de.maishai.ast.records.Block;
import de.maishai.ast.records.Break;
import de.maishai.ast.records.Declaration;
import de.maishai.ast.records.DoWhile;
import de.maishai.ast.records.Expression; import de.maishai.ast.records.Expression;
import de.maishai.ast.records.FieldVarAccess;
import de.maishai.ast.records.For;
import de.maishai.ast.records.IfElse;
import de.maishai.ast.records.MethodCall;
import de.maishai.ast.records.New;
import de.maishai.ast.records.Statement; import de.maishai.ast.records.Statement;
import de.maishai.ast.records.*; import de.maishai.ast.records.While;
import de.maishai.typedast.Type; import de.maishai.typedast.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class StatementGenerator extends DecafBaseVisitor<Statement> { public class StatementGenerator extends DecafBaseVisitor<List<Statement>> {
@Override @Override
public Statement visitIf(DecafParser.IfContext ctx) { public List<Statement> visitIf(DecafParser.IfContext ctx) {
Expression expr = new ExpressionGenerator().visit(ctx.expr()); Expression expr = new ExpressionGenerator().visit(ctx.expr());
Block ifBlock = new BlockGenerator().visit(ctx.block(0)); Block ifBlock = new BlockGenerator().visit(ctx.block(0));
if (ctx.block().size() == 2) { if (ctx.block().size() == 2) {
Block elseBlock = new BlockGenerator().visit(ctx.block(1)); Block elseBlock = new BlockGenerator().visit(ctx.block(1));
return new IfElse(expr, ifBlock, elseBlock); return List.of(new IfElse(expr, ifBlock, elseBlock));
} }
return new IfElse(expr, ifBlock, null); return List.of(new IfElse(expr, ifBlock, null));
} }
@Override @Override
public For visitFor(DecafParser.ForContext ctx) { public List<Statement> visitFor(DecafParser.ForContext ctx) {
Assignment init = generateAssign(ctx.assign(0)); Assignment init = generateAssign(ctx.assign(0));
Expression expr = new ExpressionGenerator().visit(ctx.expr()); Expression expr = new ExpressionGenerator().visit(ctx.expr());
Assignment update = generateAssign(ctx.assign(1)); Assignment update = generateAssign(ctx.assign(1));
Block block = new BlockGenerator().visit(ctx.block()); Block block = new BlockGenerator().visit(ctx.block());
return new For(init, expr, update, block); return List.of(new For(init, expr, update, block));
} }
@Override @Override
public Statement visitWhile(DecafParser.WhileContext ctx) { public List<Statement> visitWhile(DecafParser.WhileContext ctx) {
Expression expr = new ExpressionGenerator().visit(ctx.expr()); Expression expr = new ExpressionGenerator().visit(ctx.expr());
Block block = new BlockGenerator().visit(ctx.block()); Block block = new BlockGenerator().visit(ctx.block());
return new While(expr, block); return List.of(new While(expr, block));
} }
@Override @Override
public DoWhile visitDoWhile(DecafParser.DoWhileContext ctx) { public List<Statement> visitDoWhile(DecafParser.DoWhileContext ctx) {
Block block = new BlockGenerator().visit(ctx.block()); Block block = new BlockGenerator().visit(ctx.block());
Expression expr = new ExpressionGenerator().visit(ctx.expr()); Expression expr = new ExpressionGenerator().visit(ctx.expr());
return new DoWhile(block, expr); return List.of(new DoWhile(block, expr));
} }
@Override @Override
public Statement visitBreak(DecafParser.BreakContext ctx) { public List<Statement> visitBreak(DecafParser.BreakContext ctx) {
return new Break(); return List.of(new Break());
} }
@Override @Override
public Statement visitAssignment(DecafParser.AssignmentContext ctx) { public List<Statement> visitLocalVarDec(DecafParser.LocalVarDecContext ctx) {
return generateAssign(ctx.assign()); Declaration declaration = new Declaration(ctx.localVar().id().IDENTIFIER().getText(), ASTGenerator.getType(ctx.localVar().type()));
return List.of(declaration);
}
@Override
public List<Statement> visitLocalVarDecWithInitialization(DecafParser.LocalVarDecWithInitializationContext ctx) {
Declaration declaration = new Declaration(ctx.localVarWithInitialization().id().IDENTIFIER().getText(), ASTGenerator.getType(ctx.localVarWithInitialization().type()));
Expression initialization = new ExpressionGenerator().visit(ctx.localVarWithInitialization().expr());
return List.of(declaration, new Assignment(new FieldVarAccess(false, null, declaration.name()), initialization));
}
@Override
public List<Statement> visitAssignment(DecafParser.AssignmentContext ctx) {
return List.of(generateAssign(ctx.assign()));
} }
private Assignment generateAssign(DecafParser.AssignContext ctx) { private Assignment generateAssign(DecafParser.AssignContext ctx) {
@ -70,7 +95,7 @@ public class StatementGenerator extends DecafBaseVisitor<Statement> {
//StatementExpression //StatementExpression
@Override @Override
public Statement visitMethodCall(DecafParser.MethodCallContext ctx) { public List<Statement> visitMethodCall(DecafParser.MethodCallContext ctx) {
boolean isField = ctx.methCall().THIS() != null; boolean isField = ctx.methCall().THIS() != null;
Expression recursiveOwnerChain = null; Expression recursiveOwnerChain = null;
if (ctx.methCall().recipient() != null) { if (ctx.methCall().recipient() != null) {
@ -82,18 +107,18 @@ public class StatementGenerator extends DecafBaseVisitor<Statement> {
Expression astExpr = expr.accept(new ExpressionGenerator()); Expression astExpr = expr.accept(new ExpressionGenerator());
args.add(astExpr); args.add(astExpr);
} }
return new MethodCall(new FieldVarAccess(isField, recursiveOwnerChain, ctx.methCall().methName().id().IDENTIFIER().getText()), args); return List.of(new MethodCall(new FieldVarAccess(isField, recursiveOwnerChain, ctx.methCall().methName().id().IDENTIFIER().getText()), args));
} }
@Override @Override
public Statement visitNew(DecafParser.NewContext ctx) { public List<Statement> visitNew(DecafParser.NewContext ctx) {
Type type = ASTGenerator.getType(ctx.type()); Type type = ASTGenerator.getType(ctx.type());
List<Expression> args = new ArrayList<>(); List<Expression> args = new ArrayList<>();
for (var expr : ctx.args().expr()) { for (var expr : ctx.args().expr()) {
Expression astExpr = expr.accept(new ExpressionGenerator()); Expression astExpr = expr.accept(new ExpressionGenerator());
args.add(astExpr); args.add(astExpr);
} }
return new New(type, args); return List.of(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) {

View File

@ -1,32 +0,0 @@
package de.maishai;
import de.maishai.antlr.DecafBaseVisitor;
import de.maishai.antlr.DecafParser;
import de.maishai.ast.records.Assignment;
import de.maishai.ast.records.Declaration;
import de.maishai.ast.records.FieldVarAccess;
import de.maishai.ast.records.Statement;
import de.maishai.typedast.Type;
import java.util.ArrayList;
import java.util.List;
public class VariableGenerator extends DecafBaseVisitor<Declaration> {
public static List<Statement> generateInstanciations(List<DecafParser.LocalVarContext> localVarContexts) {
List<Statement> assignements = new ArrayList<>(localVarContexts.size());
for (DecafParser.LocalVarContext localVarContext : localVarContexts) {
if (!localVarContext.expr().isEmpty()) {
assignements.add(new Assignment(new FieldVarAccess(false, null, localVarContext.id().IDENTIFIER().getText()), new ExpressionGenerator().visit(localVarContext.expr())));
}
}
return assignements;
}
@Override
public Declaration visitLocalVar(DecafParser.LocalVarContext ctx) {
Type type = ASTGenerator.getType(ctx.type());
return new Declaration(ctx.id().IDENTIFIER().getText(), type);
}
}

File diff suppressed because one or more lines are too long

View File

@ -156,6 +156,18 @@ public class DecafBaseListener implements DecafListener {
* <p>The default implementation does nothing.</p> * <p>The default implementation does nothing.</p>
*/ */
@Override public void exitLocalVar(DecafParser.LocalVarContext ctx) { } @Override public void exitLocalVar(DecafParser.LocalVarContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterLocalVarWithInitialization(DecafParser.LocalVarWithInitializationContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitLocalVarWithInitialization(DecafParser.LocalVarWithInitializationContext ctx) { }
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
@ -228,6 +240,30 @@ public class DecafBaseListener implements DecafListener {
* <p>The default implementation does nothing.</p> * <p>The default implementation does nothing.</p>
*/ */
@Override public void exitBreak(DecafParser.BreakContext ctx) { } @Override public void exitBreak(DecafParser.BreakContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterLocalVarDec(DecafParser.LocalVarDecContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitLocalVarDec(DecafParser.LocalVarDecContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterLocalVarDecWithInitialization(DecafParser.LocalVarDecWithInitializationContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitLocalVarDecWithInitialization(DecafParser.LocalVarDecWithInitializationContext ctx) { }
/** /**
* {@inheritDoc} * {@inheritDoc}
* *

View File

@ -96,6 +96,13 @@ public class DecafBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
* {@link #visitChildren} on {@code ctx}.</p> * {@link #visitChildren} on {@code ctx}.</p>
*/ */
@Override public T visitLocalVar(DecafParser.LocalVarContext ctx) { return visitChildren(ctx); } @Override public T visitLocalVar(DecafParser.LocalVarContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLocalVarWithInitialization(DecafParser.LocalVarWithInitializationContext ctx) { return visitChildren(ctx); }
/** /**
* {@inheritDoc} * {@inheritDoc}
* *
@ -138,6 +145,20 @@ public class DecafBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
* {@link #visitChildren} on {@code ctx}.</p> * {@link #visitChildren} on {@code ctx}.</p>
*/ */
@Override public T visitBreak(DecafParser.BreakContext ctx) { return visitChildren(ctx); } @Override public T visitBreak(DecafParser.BreakContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLocalVarDec(DecafParser.LocalVarDecContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLocalVarDecWithInitialization(DecafParser.LocalVarDecWithInitializationContext ctx) { return visitChildren(ctx); }
/** /**
* {@inheritDoc} * {@inheritDoc}
* *

View File

@ -127,6 +127,16 @@ public interface DecafListener extends ParseTreeListener {
* @param ctx the parse tree * @param ctx the parse tree
*/ */
void exitLocalVar(DecafParser.LocalVarContext ctx); void exitLocalVar(DecafParser.LocalVarContext ctx);
/**
* Enter a parse tree produced by {@link DecafParser#localVarWithInitialization}.
* @param ctx the parse tree
*/
void enterLocalVarWithInitialization(DecafParser.LocalVarWithInitializationContext ctx);
/**
* Exit a parse tree produced by {@link DecafParser#localVarWithInitialization}.
* @param ctx the parse tree
*/
void exitLocalVarWithInitialization(DecafParser.LocalVarWithInitializationContext ctx);
/** /**
* Enter a parse tree produced by {@link DecafParser#return}. * Enter a parse tree produced by {@link DecafParser#return}.
* @param ctx the parse tree * @param ctx the parse tree
@ -197,6 +207,30 @@ public interface DecafListener extends ParseTreeListener {
* @param ctx the parse tree * @param ctx the parse tree
*/ */
void exitBreak(DecafParser.BreakContext ctx); void exitBreak(DecafParser.BreakContext ctx);
/**
* Enter a parse tree produced by the {@code LocalVarDec}
* labeled alternative in {@link DecafParser#stmt}.
* @param ctx the parse tree
*/
void enterLocalVarDec(DecafParser.LocalVarDecContext ctx);
/**
* Exit a parse tree produced by the {@code LocalVarDec}
* labeled alternative in {@link DecafParser#stmt}.
* @param ctx the parse tree
*/
void exitLocalVarDec(DecafParser.LocalVarDecContext ctx);
/**
* Enter a parse tree produced by the {@code LocalVarDecWithInitialization}
* labeled alternative in {@link DecafParser#stmt}.
* @param ctx the parse tree
*/
void enterLocalVarDecWithInitialization(DecafParser.LocalVarDecWithInitializationContext ctx);
/**
* Exit a parse tree produced by the {@code LocalVarDecWithInitialization}
* labeled alternative in {@link DecafParser#stmt}.
* @param ctx the parse tree
*/
void exitLocalVarDecWithInitialization(DecafParser.LocalVarDecWithInitializationContext ctx);
/** /**
* Enter a parse tree produced by the {@code Assignment} * Enter a parse tree produced by the {@code Assignment}
* labeled alternative in {@link DecafParser#stmt}. * labeled alternative in {@link DecafParser#stmt}.

File diff suppressed because it is too large Load Diff

View File

@ -82,6 +82,12 @@ public interface DecafVisitor<T> extends ParseTreeVisitor<T> {
* @return the visitor result * @return the visitor result
*/ */
T visitLocalVar(DecafParser.LocalVarContext ctx); T visitLocalVar(DecafParser.LocalVarContext ctx);
/**
* Visit a parse tree produced by {@link DecafParser#localVarWithInitialization}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitLocalVarWithInitialization(DecafParser.LocalVarWithInitializationContext ctx);
/** /**
* Visit a parse tree produced by {@link DecafParser#return}. * Visit a parse tree produced by {@link DecafParser#return}.
* @param ctx the parse tree * @param ctx the parse tree
@ -123,6 +129,20 @@ public interface DecafVisitor<T> extends ParseTreeVisitor<T> {
* @return the visitor result * @return the visitor result
*/ */
T visitBreak(DecafParser.BreakContext ctx); T visitBreak(DecafParser.BreakContext ctx);
/**
* Visit a parse tree produced by the {@code LocalVarDec}
* labeled alternative in {@link DecafParser#stmt}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitLocalVarDec(DecafParser.LocalVarDecContext ctx);
/**
* Visit a parse tree produced by the {@code LocalVarDecWithInitialization}
* labeled alternative in {@link DecafParser#stmt}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitLocalVarDecWithInitialization(DecafParser.LocalVarDecWithInitializationContext ctx);
/** /**
* Visit a parse tree produced by the {@code Assignment} * Visit a parse tree produced by the {@code Assignment}
* labeled alternative in {@link DecafParser#stmt}. * labeled alternative in {@link DecafParser#stmt}.

View File

@ -4,5 +4,5 @@ package de.maishai.ast.records;
import java.util.List; import java.util.List;
public record Block(List<Declaration> localVariables, List<Statement> stmts) implements Node { public record Block(List<Statement> stmts) implements Node {
} }

View File

@ -2,5 +2,5 @@ package de.maishai.ast.records;
import de.maishai.typedast.Type; import de.maishai.typedast.Type;
public record Declaration(String name, Type type) implements Node { public record Declaration(String name, Type type) implements Statement {
} }

View File

@ -1,4 +1,4 @@
package de.maishai.ast.records; package de.maishai.ast.records;
public sealed interface Node permits Block, Class, Constructor, Declaration, Expression, Method, Parameter, Program, Statement { public sealed interface Node permits Block, Class, Constructor, Expression, Method, Parameter, Program, Statement {
} }

View File

@ -1,4 +1,4 @@
package de.maishai.ast.records; package de.maishai.ast.records;
public sealed interface Statement extends Node permits Assignment, Break, DoWhile, For, IfElse, MethodCall, New, Return, While { public sealed interface Statement extends Node permits Assignment, Break, Declaration, DoWhile, For, IfElse, MethodCall, New, Return, While {
} }

View File

@ -36,11 +36,10 @@ public class TypedBlock implements TypedNode {
return; return;
} }
for (Declaration var : unTypedBlock.localVariables()) {
vars.add(new TypedLocalVariable(typedProgram, var));
}
for (var stmt : unTypedBlock.stmts()) { for (var stmt : unTypedBlock.stmts()) {
if (stmt instanceof Declaration){
vars.add(new TypedLocalVariable(typedProgram,(Declaration) stmt));
}
if (stmt instanceof Assignment assignment) { if (stmt instanceof Assignment assignment) {
TypedAssignment typedAssignment = new TypedAssignment(typedProgram, assignment); TypedAssignment typedAssignment = new TypedAssignment(typedProgram, assignment);
typedAssignment.typeCheck(typedProgram); typedAssignment.typeCheck(typedProgram);