Merge branch 'feature/nestes-expressions' into 'master'

Feature/nested expressions

See merge request mkais001/klang!2
This commit is contained in:
Dennis Kaiser
2019-12-16 21:52:31 +01:00
15 changed files with 398 additions and 382 deletions

6
.gitignore vendored
View File

@@ -16,3 +16,9 @@ src/main/antlr4/de/hsrm/compiler/Klang/.antlr
# assembly files # assembly files
*.s *.s
# other sourcecode files
*.c
# build output
out

View File

@@ -44,14 +44,21 @@ return_statement
; ;
expression expression
: atom MULT atom #multiplicationExpression : atom #atomExpression
| atom op=(ADD | SUB) atom #additiveExpression | OPAR lhs=expression ADD rhs=expression CPAR #additionExpression
| atom MOD atom #moduloExpression | OPAR lhs=expression SUB rhs=expression CPAR #substractionExpression
| SUB atom #unaryNegateExpression | OPAR lhs=expression MUL rhs=expression CPAR #multiplicationExpression
| atom #atomExpression | OPAR lhs=expression DIV rhs=expression CPAR #divisionExpression
| OPAR lhs=expression MOD rhs=expression CPAR #moduloExpression
| SUB expression #negateExpression
| functionCall #functionCallExpression | functionCall #functionCallExpression
; ;
atom
: INTEGER_LITERAL #intAtom
| IDENT # variable
;
functionCall functionCall
: IDENT OPAR arguments CPAR : IDENT OPAR arguments CPAR
; ;
@@ -60,11 +67,6 @@ arguments
: (expression (COMMA expression)*)? : (expression (COMMA expression)*)?
; ;
atom
: INTEGER_LITERAL #intAtom
| IDENT # variable
;
PRINT: 'print'; PRINT: 'print';
IF: 'if'; IF: 'if';
ELSE: 'else'; ELSE: 'else';
@@ -79,10 +81,11 @@ CPAR: ')';
COMMA: ','; COMMA: ',';
EQUAL: '='; EQUAL: '=';
MULT: '*'; MUL: '*';
ADD: '+'; ADD: '+';
SUB: '-'; SUB: '-';
MOD: '%'; MOD: '%';
DIV: '/';
INTEGER_LITERAL INTEGER_LITERAL
: [0-9]+ : [0-9]+

View File

@@ -66,38 +66,33 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
} }
@Override @Override
public Node visitMultiplicationExpression(KlangParser.MultiplicationExpressionContext ctx) { public Node visitAdditionExpression(KlangParser.AdditionExpressionContext ctx) {
Node left = this.visit(ctx.atom(0)); return new AdditionExpression((Expression) this.visit(ctx.lhs), (Expression) this.visit(ctx.rhs));
Node right = this.visit(ctx.atom(1));
Node result = new MultiplicativeExpression((Expression) left, (Expression) right);
result.type = left.type; // We have to actually compute this in the future
return result;
} }
@Override @Override
public Node visitAdditiveExpression(KlangParser.AdditiveExpressionContext ctx) { public Node visitSubstractionExpression(KlangParser.SubstractionExpressionContext ctx) {
Node left = this.visit(ctx.atom(0)); return new SubstractionExpression((Expression) this.visit(ctx.lhs), (Expression) this.visit(ctx.rhs));
Node right = this.visit(ctx.atom(1)); }
Node result = new AdditiveExpression((Expression) left, (Expression) right);
result.type = left.type; // We have to actually compute this in the future @Override
return result; public Node visitMultiplicationExpression(KlangParser.MultiplicationExpressionContext ctx) {
return new MultiplicationExpression((Expression) this.visit(ctx.lhs), (Expression) this.visit(ctx.rhs));
}
@Override
public Node visitDivisionExpression(KlangParser.DivisionExpressionContext ctx) {
return new DivisionExpression((Expression) this.visit(ctx.lhs), (Expression) this.visit(ctx.rhs));
} }
@Override @Override
public Node visitModuloExpression(KlangParser.ModuloExpressionContext ctx) { public Node visitModuloExpression(KlangParser.ModuloExpressionContext ctx) {
Node left = this.visit(ctx.atom(0)); return new ModuloExpression((Expression) this.visit(ctx.lhs), (Expression) this.visit(ctx.rhs));
Node right = this.visit(ctx.atom(1));
Node result = new ModuloExpression((Expression) left, (Expression) right);
result.type = left.type; // We have to actually compute this in the future
return result;
} }
@Override @Override
public Node visitUnaryNegateExpression(KlangParser.UnaryNegateExpressionContext ctx) { public Node visitNegateExpression(KlangParser.NegateExpressionContext ctx) {
Node atom = this.visit(ctx.atom()); return new NegateExpression((Expression) this.visit(ctx.expression()));
Node result = new NegateExpression((Expression) atom);
result.type = atom.type;
return result;
} }
@Override @Override

View File

@@ -1,71 +0,0 @@
package de.hsrm.compiler.Klang;
public class JSVisitor extends KlangBaseVisitor<Void> {
private final StringBuilder sb;
public JSVisitor(StringBuilder sb) {
this.sb = sb;
}
@Override
public Void visitStatement(KlangParser.StatementContext ctx) {
for (int i = 0; i < ctx.children.size(); i++) {
this.visit(ctx.children.get(i));
sb.append("\n");
}
return null;
}
@Override
public Void visitPrint(KlangParser.PrintContext ctx) {
sb.append("console.log(");
this.visit(ctx.expression());
sb.append(");");
return null;
}
@Override
public Void visitMultiplicationExpression(KlangParser.MultiplicationExpressionContext ctx) {
this.visit(ctx.atom(0));
sb.append(" * ");
this.visit(ctx.atom(1));
return null;
}
@Override
public Void visitAdditiveExpression(KlangParser.AdditiveExpressionContext ctx) {
this.visit(ctx.atom(0));
switch (ctx.op.getType()) {
case KlangParser.ADD:
sb.append(" + ");
break;
case KlangParser.SUB:
sb.append(" - ");
break;
}
this.visit(ctx.atom(1));
return null;
}
@Override
public Void visitModuloExpression(KlangParser.ModuloExpressionContext ctx) {
this.visit(ctx.atom(0));
sb.append(" % ");
this.visit(ctx.atom(1));
return null;
}
@Override
public Void visitUnaryNegateExpression(KlangParser.UnaryNegateExpressionContext ctx) {
sb.append("-");
this.visit(ctx.atom());
return null;
}
@Override
public Void visitIntAtom(KlangParser.IntAtomContext ctx) {
sb.append(ctx.getText());
return null;
}
}

View File

@@ -2,9 +2,8 @@ package de.hsrm.compiler.Klang.nodes.expressions;
import de.hsrm.compiler.Klang.visitors.Visitor; import de.hsrm.compiler.Klang.visitors.Visitor;
public class AdditiveExpression extends BinaryExpression { public class AdditionExpression extends BinaryExpression {
public AdditionExpression(Expression lhs, Expression rhs) {
public AdditiveExpression(Expression lhs, Expression rhs) {
super(lhs, rhs); super(lhs, rhs);
} }
@@ -12,5 +11,4 @@ public class AdditiveExpression extends BinaryExpression {
public <R> R welcome(Visitor<R> v) { public <R> R welcome(Visitor<R> v) {
return v.visit(this); return v.visit(this);
} }
} }

View File

@@ -1,7 +1,6 @@
package de.hsrm.compiler.Klang.nodes.expressions; package de.hsrm.compiler.Klang.nodes.expressions;
public abstract class BinaryExpression extends Expression { public abstract class BinaryExpression extends Expression {
public Expression lhs; public Expression lhs;
public Expression rhs; public Expression rhs;

View File

@@ -0,0 +1,14 @@
package de.hsrm.compiler.Klang.nodes.expressions;
import de.hsrm.compiler.Klang.visitors.Visitor;
public class DivisionExpression extends BinaryExpression {
public DivisionExpression(Expression lhs, Expression rhs) {
super(lhs, rhs);
}
@Override
public <R> R welcome(Visitor<R> v) {
return v.visit(this);
}
}

View File

@@ -3,7 +3,6 @@ package de.hsrm.compiler.Klang.nodes.expressions;
import de.hsrm.compiler.Klang.visitors.Visitor; import de.hsrm.compiler.Klang.visitors.Visitor;
public class ModuloExpression extends BinaryExpression { public class ModuloExpression extends BinaryExpression {
public ModuloExpression(Expression lhs, Expression rhs) { public ModuloExpression(Expression lhs, Expression rhs) {
super(lhs, rhs); super(lhs, rhs);
} }
@@ -12,5 +11,4 @@ public class ModuloExpression extends BinaryExpression {
public <R> R welcome(Visitor<R> v) { public <R> R welcome(Visitor<R> v) {
return v.visit(this); return v.visit(this);
} }
} }

View File

@@ -1,9 +1,9 @@
package de.hsrm.compiler.Klang.nodes.expressions; package de.hsrm.compiler.Klang.nodes.expressions;
import de.hsrm.compiler.Klang.visitors.Visitor;; import de.hsrm.compiler.Klang.visitors.Visitor;
public class MultiplicativeExpression extends BinaryExpression { public class MultiplicationExpression extends BinaryExpression {
public MultiplicativeExpression(Expression lhs, Expression rhs) { public MultiplicationExpression(Expression lhs, Expression rhs) {
super(lhs, rhs); super(lhs, rhs);
} }

View File

@@ -0,0 +1,14 @@
package de.hsrm.compiler.Klang.nodes.expressions;
import de.hsrm.compiler.Klang.visitors.Visitor;
public class SubstractionExpression extends BinaryExpression {
public SubstractionExpression(Expression lhs, Expression rhs) {
super(lhs, rhs);
}
@Override
public <R> R welcome(Visitor<R> v) {
return v.visit(this);
}
}

View File

@@ -21,24 +21,38 @@ public class EvalVisitor implements Visitor<Value> {
} }
@Override @Override
public Value visit(MultiplicativeExpression e) { public Value visit(AdditionExpression e) {
Value a = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value b = e.rhs.welcome(this); Value rhs = e.rhs.welcome(this);
return new Value(a.asInteger() * b.asInteger()); return new Value(lhs.asInteger() + rhs.asInteger());
} }
@Override @Override
public Value visit(AdditiveExpression e) { public Value visit(SubstractionExpression e) {
Value a = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value b = e.rhs.welcome(this); Value rhs = e.rhs.welcome(this);
return new Value(a.asInteger() + b.asInteger()); return new Value(lhs.asInteger() - rhs.asInteger());
}
@Override
public Value visit(MultiplicationExpression e) {
Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.welcome(this);
return new Value(lhs.asInteger() * rhs.asInteger());
}
@Override
public Value visit(DivisionExpression e) {
Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.welcome(this);
return new Value(lhs.asInteger() / rhs.asInteger());
} }
@Override @Override
public Value visit(ModuloExpression e) { public Value visit(ModuloExpression e) {
Value a = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value b = e.rhs.welcome(this); Value rhs = e.rhs.welcome(this);
return new Value(a.asInteger() % b.asInteger()); return new Value(lhs.asInteger() % rhs.asInteger());
} }
@Override @Override
@@ -52,7 +66,7 @@ public class EvalVisitor implements Visitor<Value> {
Value result = this.env.get(e.name); Value result = this.env.get(e.name);
if (result == null) { if (result == null) {
throw new RuntimeException("Variable with name " +e.name + " not found."); throw new RuntimeException("Variable with name " + e.name + " not found.");
} }
return result; return result;
@@ -123,7 +137,7 @@ public class EvalVisitor implements Visitor<Value> {
// Stelle sicher, dass die Länge der argumente und parameter übereinstimmen // Stelle sicher, dass die Länge der argumente und parameter übereinstimmen
if (e.arguments.length != func.parameters.length) { if (e.arguments.length != func.parameters.length) {
throw new RuntimeException("Error with function call " +e.name + ": Number of parameters wrong"); throw new RuntimeException("Error with function call " + e.name + ": Number of parameters wrong");
} }
// Baue ein neues environment // Baue ein neues environment
@@ -147,7 +161,7 @@ public class EvalVisitor implements Visitor<Value> {
public Value visit(Program e) { public Value visit(Program e) {
// Funktionsdefinitionen für die Auswertung // Funktionsdefinitionen für die Auswertung
// von Funktionsaufrufen speichern // von Funktionsaufrufen speichern
for (var funcDef: e.funcs) { for (var funcDef : e.funcs) {
this.funcs.put(funcDef.name, funcDef); this.funcs.put(funcDef.name, funcDef);
} }

View File

@@ -6,20 +6,9 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import de.hsrm.compiler.Klang.nodes.Block; import de.hsrm.compiler.Klang.nodes.*;
import de.hsrm.compiler.Klang.nodes.FunctionDefinition; import de.hsrm.compiler.Klang.nodes.expressions.*;
import de.hsrm.compiler.Klang.nodes.Program; import de.hsrm.compiler.Klang.nodes.statements.*;
import de.hsrm.compiler.Klang.nodes.expressions.AdditiveExpression;
import de.hsrm.compiler.Klang.nodes.expressions.FunctionCall;
import de.hsrm.compiler.Klang.nodes.expressions.IntegerExpression;
import de.hsrm.compiler.Klang.nodes.expressions.ModuloExpression;
import de.hsrm.compiler.Klang.nodes.expressions.MultiplicativeExpression;
import de.hsrm.compiler.Klang.nodes.expressions.NegateExpression;
import de.hsrm.compiler.Klang.nodes.expressions.Variable;
import de.hsrm.compiler.Klang.nodes.statements.IfStatement;
import de.hsrm.compiler.Klang.nodes.statements.PrintStatement;
import de.hsrm.compiler.Klang.nodes.statements.ReturnStatement;
import de.hsrm.compiler.Klang.nodes.statements.VariableAssignment;
public class GenASM implements Visitor<Void> { public class GenASM implements Visitor<Void> {
@@ -81,25 +70,61 @@ public class GenASM implements Visitor<Void> {
@Override @Override
public Void visit(Variable e) { public Void visit(Variable e) {
this.ex.write(" movq " +this.env.get(e.name) +"(%rbp), %rax\n"); this.ex.write(" movq " + this.env.get(e.name) + "(%rbp), %rax\n");
return null; return null;
} }
@Override @Override
public Void visit(MultiplicativeExpression e) { public Void visit(AdditionExpression e) {
e.lhs.welcome(this); e.lhs.welcome(this);
this.ex.write(" movq %rax, %rbx\n"); this.ex.write(" pushq %rax\n");
e.rhs.welcome(this); e.rhs.welcome(this);
this.ex.write(" popq %rbx\n");
this.ex.write(" addq %rbx, %rax\n");
return null;
}
@Override
public Void visit(SubstractionExpression e) {
e.lhs.welcome(this);
this.ex.write(" pushq %rax\n");
e.rhs.welcome(this);
this.ex.write(" popq %rbx\n");
this.ex.write(" subq %rbx, %rax\n");
return null;
}
@Override
public Void visit(MultiplicationExpression e) {
e.lhs.welcome(this);
this.ex.write(" pushq %rax\n");
e.rhs.welcome(this);
this.ex.write(" popq %rbx\n");
this.ex.write(" imulq %rbx, %rax\n"); this.ex.write(" imulq %rbx, %rax\n");
return null; return null;
} }
@Override @Override
public Void visit(AdditiveExpression e) { public Void visit(DivisionExpression e) {
e.lhs.welcome(this); e.lhs.welcome(this);
this.ex.write(" movq %rax, %rbx\n"); this.ex.write(" pushq %rax\n");
e.rhs.welcome(this); e.rhs.welcome(this);
this.ex.write(" addq %rbx, %rax\n"); this.ex.write(" movq %rax, %rbx\n");
this.ex.write(" popq %rax\n");
this.ex.write(" xor %rdx, %rdx\n"); // clear upper part of division
this.ex.write(" idiv %rbx\n"); // %rax/%rbx, quotient now in %rax
return null;
}
@Override
public Void visit(ModuloExpression e) {
this.ex.write(" pushq %rax\n");
e.rhs.welcome(this);
this.ex.write(" movq %rax, %rbx\n");
this.ex.write(" popq %rax\n");
this.ex.write(" xor %rdx, %rdx\n"); // clear upper part of division
this.ex.write(" idiv %rbx\n"); // %rax/%rbx, remainder now in %rdx
this.ex.write(" movq %rdx, %rax\n");
return null; return null;
} }
@@ -110,17 +135,6 @@ public class GenASM implements Visitor<Void> {
return null; return null;
} }
@Override
public Void visit(ModuloExpression e) {
e.rhs.welcome(this);
this.ex.write(" movq %rax, %rbx\n");
e.lhs.welcome(this);
this.ex.write(" xor %rdx, %rdx\n"); // clear remainder register
this.ex.write(" idiv %ebx\n"); // %rax/%rbx, remainder now in %rdx
this.ex.write(" movq %rdx, %rax\n");
return null;
}
@Override @Override
public Void visit(IfStatement e) { public Void visit(IfStatement e) {
int then = ++lCount; int then = ++lCount;
@@ -205,7 +219,7 @@ public class GenASM implements Visitor<Void> {
} }
// Reserviere Platz auf dem Stack für jede lokale variable // Reserviere Platz auf dem Stack für jede lokale variable
for (String lok_var: vars) { for (String lok_var : vars) {
offset -= 8; offset -= 8;
this.ex.write(" pushq $0\n"); this.ex.write(" pushq $0\n");
this.env.put(lok_var, offset); this.env.put(lok_var, offset);

View File

@@ -2,20 +2,9 @@ package de.hsrm.compiler.Klang.visitors;
import java.util.Set; import java.util.Set;
import de.hsrm.compiler.Klang.nodes.Block; import de.hsrm.compiler.Klang.nodes.*;
import de.hsrm.compiler.Klang.nodes.FunctionDefinition; import de.hsrm.compiler.Klang.nodes.expressions.*;
import de.hsrm.compiler.Klang.nodes.Program; import de.hsrm.compiler.Klang.nodes.statements.*;
import de.hsrm.compiler.Klang.nodes.expressions.AdditiveExpression;
import de.hsrm.compiler.Klang.nodes.expressions.FunctionCall;
import de.hsrm.compiler.Klang.nodes.expressions.IntegerExpression;
import de.hsrm.compiler.Klang.nodes.expressions.ModuloExpression;
import de.hsrm.compiler.Klang.nodes.expressions.MultiplicativeExpression;
import de.hsrm.compiler.Klang.nodes.expressions.NegateExpression;
import de.hsrm.compiler.Klang.nodes.expressions.Variable;
import de.hsrm.compiler.Klang.nodes.statements.IfStatement;
import de.hsrm.compiler.Klang.nodes.statements.PrintStatement;
import de.hsrm.compiler.Klang.nodes.statements.ReturnStatement;
import de.hsrm.compiler.Klang.nodes.statements.VariableAssignment;
class GetVars implements Visitor<Void> { class GetVars implements Visitor<Void> {
@@ -36,14 +25,35 @@ class GetVars implements Visitor<Void> {
} }
@Override @Override
public Void visit(MultiplicativeExpression e) { public Void visit(AdditionExpression e) {
e.lhs.welcome(this); e.lhs.welcome(this);
e.rhs.welcome(this); e.rhs.welcome(this);
return null; return null;
} }
@Override @Override
public Void visit(AdditiveExpression e) { public Void visit(SubstractionExpression e) {
e.lhs.welcome(this);
e.rhs.welcome(this);
return null;
}
@Override
public Void visit(MultiplicationExpression e) {
e.lhs.welcome(this);
e.rhs.welcome(this);
return null;
}
@Override
public Void visit(DivisionExpression e) {
e.lhs.welcome(this);
e.rhs.welcome(this);
return null;
}
@Override
public Void visit(ModuloExpression e) {
e.lhs.welcome(this); e.lhs.welcome(this);
e.rhs.welcome(this); e.rhs.welcome(this);
return null; return null;
@@ -55,13 +65,6 @@ class GetVars implements Visitor<Void> {
return null; return null;
} }
@Override
public Void visit(ModuloExpression e) {
e.lhs.welcome(this);
e.rhs.welcome(this);
return null;
}
@Override @Override
public Void visit(IfStatement e) { public Void visit(IfStatement e) {
e.cond.welcome(this); e.cond.welcome(this);

View File

@@ -72,33 +72,60 @@ public class PrettyPrintVisitor implements Visitor<Void> {
} }
@Override @Override
public Void visit(MultiplicativeExpression e) { public Void visit(AdditionExpression e) {
e.lhs.welcome(this); ex.write("(");
ex.write(" * ");
e.rhs.welcome(this);
return null;
}
@Override
public Void visit(AdditiveExpression e) {
e.lhs.welcome(this); e.lhs.welcome(this);
ex.write(" + "); ex.write(" + ");
e.rhs.welcome(this); e.rhs.welcome(this);
ex.write(")");
return null; return null;
} }
@Override @Override
public Void visit(NegateExpression e) { public Void visit(SubstractionExpression e) {
ex.write(" - "); ex.write("(");
e.lhs.welcome(this); e.lhs.welcome(this);
ex.write(" - ");
e.rhs.welcome(this);
ex.write(")");
return null;
}
@Override
public Void visit(MultiplicationExpression e) {
ex.write("(");
e.lhs.welcome(this);
ex.write(" * ");
e.rhs.welcome(this);
ex.write(")");
return null;
}
@Override
public Void visit(DivisionExpression e) {
ex.write("(");
e.lhs.welcome(this);
ex.write(" / ");
e.rhs.welcome(this);
ex.write(")");
return null; return null;
} }
@Override @Override
public Void visit(ModuloExpression e) { public Void visit(ModuloExpression e) {
ex.write("(");
e.lhs.welcome(this); e.lhs.welcome(this);
ex.write(" % "); ex.write(" % ");
e.rhs.welcome(this); e.rhs.welcome(this);
ex.write(")");
return null;
}
@Override
public Void visit(NegateExpression e) {
ex.write(" - ");
e.lhs.welcome(this);
return null; return null;
} }

View File

@@ -9,10 +9,12 @@ import de.hsrm.compiler.Klang.nodes.statements.*;
public interface Visitor<R> { public interface Visitor<R> {
R visit(IntegerExpression e); R visit(IntegerExpression e);
R visit(Variable e); R visit(Variable e);
R visit(MultiplicativeExpression e); R visit(AdditionExpression e);
R visit(AdditiveExpression e); R visit(SubstractionExpression e);
R visit(NegateExpression e); R visit(MultiplicationExpression e);
R visit(DivisionExpression e);
R visit(ModuloExpression e); R visit(ModuloExpression e);
R visit(NegateExpression e);
R visit(IfStatement e); R visit(IfStatement e);
R visit(PrintStatement e); R visit(PrintStatement e);
R visit(VariableAssignment e); R visit(VariableAssignment e);