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)*;
param : type id;
block : '{' (localVar | stmt)* return? '}';
localVar : type id ';'
| type id '=' expr';';
block : '{' (stmt)* return? '}';
localVar : type id;
localVarWithInitialization: type id '=' expr;
return: 'return' expr ';'
| 'return' ';'
;
@ -27,6 +27,8 @@ stmt : 'if' '(' expr ')' block ('else' block)? #If
| 'while' '(' expr ')' block #While
| 'do' block 'while' '(' expr ')' ';'? #DoWhile
| 'break' ';' #Break
| localVar ';' #LocalVarDec
| localVarWithInitialization ';' #LocalVarDecWithInitialization
| assign ';' #Assignment
| stmtexpr ';' #StatementExpressionstmt
;

View File

@ -1,8 +1,12 @@
package de.maishai;
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.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 java.util.ArrayList;
@ -21,7 +25,7 @@ public class ASTGenerator {
constructors = ctx.constructor().stream().map(ASTGenerator::generateConstructor).toList();
}
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<>();
if (ctx.meth() != null) {

View File

@ -2,24 +2,23 @@ package de.maishai;
import de.maishai.antlr.DecafBaseVisitor;
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.Statement;
import de.maishai.ast.records.Block;
import java.util.ArrayList;
import java.util.List;
public class BlockGenerator extends DecafBaseVisitor<Block> {
@Override
public Block visitBlock(DecafParser.BlockContext ctx) {
List<Declaration> vars = ctx.localVar().stream().map(var -> new VariableGenerator().visit(var)).toList();
List<Statement> statements = VariableGenerator.generateInstanciations(ctx.localVar());
List<Statement> statements = new ArrayList<>(ctx.stmt().size());
for (DecafParser.StmtContext stmtContext : ctx.stmt()) {
statements.add(new StatementGenerator().visit(stmtContext));
statements.addAll(new StatementGenerator().visit(stmtContext));
}
if (ctx.return_() != null){
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 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) {
List<Class> classes = new ArrayList<>();
for (String fromSource : fromSources) {
@ -97,10 +116,10 @@ public class Compiler {
}
}
public static void main(String[] args) {
generateByteCodeFileFromFile(List.of("src/main/resources/JavaTestfiles/ClassWithConstructor.java",
"src/main/resources/JavaTestfiles/ClassWithConstructorAndMethodCall.java",
"src/main/resources/JavaTestfiles/ComplexClass.java"),
List.of("ClassWithConstructor","ClassWithConstructorAndMethodCall","ComplexClass"));
}
// public static void main(String[] args) {
// generateByteCodeFileFromFile(List.of("src/main/resources/JavaTestfiles/ClassWithConstructor.java",
// "src/main/resources/JavaTestfiles/ClassWithConstructorAndMethodCall.java",
// "src/main/resources/JavaTestfiles/ComplexClass.java"),
// List.of("ClassWithConstructor","ClassWithConstructorAndMethodCall","ComplexClass"));
// }
}

View File

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

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>
*/
@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}
*
@ -228,6 +240,30 @@ public class DecafBaseListener implements DecafListener {
* <p>The default implementation does nothing.</p>
*/
@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}
*

View File

@ -96,6 +96,13 @@ public class DecafBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
* {@link #visitChildren} on {@code ctx}.</p>
*/
@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}
*
@ -138,6 +145,20 @@ public class DecafBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
* {@link #visitChildren} on {@code ctx}.</p>
*/
@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}
*

View File

@ -127,6 +127,16 @@ public interface DecafListener extends ParseTreeListener {
* @param ctx the parse tree
*/
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}.
* @param ctx the parse tree
@ -197,6 +207,30 @@ public interface DecafListener extends ParseTreeListener {
* @param ctx the parse tree
*/
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}
* 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
*/
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}.
* @param ctx the parse tree
@ -123,6 +129,20 @@ public interface DecafVisitor<T> extends ParseTreeVisitor<T> {
* @return the visitor result
*/
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}
* labeled alternative in {@link DecafParser#stmt}.

View File

@ -4,5 +4,5 @@ package de.maishai.ast.records;
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;
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;
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;
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;
}
for (Declaration var : unTypedBlock.localVariables()) {
vars.add(new TypedLocalVariable(typedProgram, var));
}
for (var stmt : unTypedBlock.stmts()) {
if (stmt instanceof Declaration){
vars.add(new TypedLocalVariable(typedProgram,(Declaration) stmt));
}
if (stmt instanceof Assignment assignment) {
TypedAssignment typedAssignment = new TypedAssignment(typedProgram, assignment);
typedAssignment.typeCheck(typedProgram);