add context analysis and custom visitors

This commit is contained in:
2019-11-04 17:35:15 +01:00
parent bef26434c6
commit c26cb6ddf5
22 changed files with 355 additions and 123 deletions

View File

@@ -1,3 +1,4 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//target/generated-sources/antlr4=UTF-8
encoding/<project>=UTF-8

View File

@@ -1,4 +1,4 @@
// Generated from /home/marvin/Documents/university/compiler/klang/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 by ANTLR 4.7.1
// Generated from /home/nitrix/Development/hsrm/cb/klang/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 by ANTLR 4.7.1
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Token;

View File

@@ -1,4 +1,4 @@
// Generated from /home/marvin/Documents/university/compiler/klang/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 by ANTLR 4.7.1
// Generated from /home/nitrix/Development/hsrm/cb/klang/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 by ANTLR 4.7.1
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.*;

View File

@@ -0,0 +1,75 @@
package de.hsrm.compiler.Klang;
import de.hsrm.compiler.Klang.nodes.*;
import de.hsrm.compiler.Klang.nodes.expressions.*;
import de.hsrm.compiler.Klang.nodes.statements.*;
import de.hsrm.compiler.Klang.types.Type;
public class ContextAnalysis extends KlangBaseVisitor<Node> {
@Override
public Node visitPrint(KlangParser.PrintContext ctx) {
Node expression = this.visit(ctx.expression());
return new PrintStatement((Expression) expression);
}
@Override
public Node visitIf_statement(KlangParser.If_statementContext ctx) {
Node condition = this.visit(ctx.expression());
Node thenBlock = this.visit(ctx.braced_block(0));
if (ctx.braced_block().size() > 1) {
Node elseBlock = this.visit(ctx.braced_block(1));
return new IfStatement((Expression) condition, (Block) thenBlock, (Block) elseBlock);
} else {
return new IfStatement((Expression) condition, (Block) thenBlock, null);
}
}
@Override
public Node visitMultiplicationExpression(KlangParser.MultiplicationExpressionContext ctx) {
Node left = this.visit(ctx.atom(0));
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
public Node visitAdditiveExpression(KlangParser.AdditiveExpressionContext ctx) {
Node left = this.visit(ctx.atom(0));
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
return result;
}
@Override
public Node visitModuloExpression(KlangParser.ModuloExpressionContext ctx) {
Node left = this.visit(ctx.atom(0));
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
public Node visitUnaryNegateExpression(KlangParser.UnaryNegateExpressionContext ctx) {
Node atom = this.visit(ctx.atom());
Node result = new NegateExpression((Expression) atom);
result.type = atom.type;
return result;
}
@Override
public Node visitAtomExpression(KlangParser.AtomExpressionContext ctx) {
return this.visit(ctx.atom());
}
@Override
public Node visitIntAtom(KlangParser.IntAtomContext ctx) {
Node n = new IntegerExpression(Integer.parseInt(ctx.getText()));
n.type = Type.getIntegerType();
return n;
}
}

View File

@@ -4,6 +4,9 @@ package de.hsrm.compiler.Klang;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
import de.hsrm.compiler.Klang.nodes.Node;
import de.hsrm.compiler.Klang.visitors.EvalVisitor;
public class Klang {
public static void main(String[] args) throws Exception {
// create a CharStream that reads from standard input
@@ -19,9 +22,11 @@ public class Klang {
KlangParser parser = new KlangParser(tokens);
ParseTree tree = parser.parse(); // begin parsing at init rule
// StringBuilder sb = new StringBuilder();
Visitor visitor = new Visitor();
visitor.visit(tree);
// System.out.println(sb.toString());
ContextAnalysis ctxAnal = new ContextAnalysis();
Node node = ctxAnal.visit(tree); // this gets us the DAST
// This
EvalVisitor visitor = new EvalVisitor();
node.welcome(visitor);
}
}

View File

@@ -1,55 +1,13 @@
package de.hsrm.compiler.Klang;
public class Value {
private Object value;
public static Value VOID = new Value(new Object());
public Value(Object value) {
this.value = value;
}
final Object value;
public Value(Object value) {
this.value = value;
}
public Integer asInteger() {
return (Integer)value;
}
public String asString() {
return String.valueOf(value);
}
public boolean isDouble() {
return value instanceof Double;
}
@Override
public int hashCode() {
if(value == null) {
return 0;
}
return this.value.hashCode();
}
@Override
public boolean equals(Object o) {
if(value == o) {
return true;
}
if(value == null || o == null || o.getClass() != value.getClass()) {
return false;
}
Value that = (Value)o;
return this.value.equals(that.value);
}
@Override
public String toString() {
return String.valueOf(value);
}
public int asInteger() {
return (int) this.value;
}
}

View File

@@ -1,68 +0,0 @@
package de.hsrm.compiler.Klang;
public class Visitor extends KlangBaseVisitor<Value> {
@Override
public Value visitPrint(KlangParser.PrintContext ctx) {
Value value = this.visit(ctx.expression());
System.out.println(value);
return value;
}
@Override
public Value visitIf_statement(KlangParser.If_statementContext ctx) {
Value cond = this.visit(ctx.expression());
if (cond.asInteger() != 0) {
this.visit(ctx.braced_block(0));
} else if (ctx.braced_block().size() > 1) {
this.visit(ctx.braced_block(1));
}
return null;
}
@Override
public Value visitMultiplicationExpression(KlangParser.MultiplicationExpressionContext ctx) {
Value left = this.visit(ctx.atom(0));
Value right = this.visit(ctx.atom(1));
return new Value(left.asInteger() * right.asInteger());
}
@Override
public Value visitAdditiveExpression(KlangParser.AdditiveExpressionContext ctx) {
Value left = this.visit(ctx.atom(0));
Value right = this.visit(ctx.atom(1));
switch (ctx.op.getType()) {
case KlangParser.ADD:
return new Value(left.asInteger() + right.asInteger());
case KlangParser.SUB:
return new Value(left.asInteger() - right.asInteger());
default:
throw new RuntimeException(
"Unknown operator for additive expression: " + KlangParser.VOCABULARY.getDisplayName(ctx.op.getType()));
}
}
@Override
public Value visitModuloExpression(KlangParser.ModuloExpressionContext ctx) {
Value left = this.visit(ctx.atom(0));
Value right = this.visit(ctx.atom(1));
return new Value(left.asInteger() % right.asInteger());
}
@Override
public Value visitUnaryNegateExpression(KlangParser.UnaryNegateExpressionContext ctx) {
Value value = this.visit(ctx.atom());
return new Value(-value.asInteger());
}
@Override
public Value visitAtomExpression(KlangParser.AtomExpressionContext ctx) {
return this.visit(ctx.atom());
}
@Override
public Value visitIntAtom(KlangParser.IntAtomContext ctx) {
return new Value(Integer.parseInt(ctx.getText()));
}
}

View File

@@ -0,0 +1,19 @@
package de.hsrm.compiler.Klang.nodes;
import de.hsrm.compiler.Klang.nodes.statements.Statement;
import de.hsrm.compiler.Klang.visitors.Visitor;
public class Block extends Node {
public Statement[] statements;
public Block(Statement[] statements) {
this.statements = statements;
}
@Override
public <R> R welcome(Visitor<R> v) {
return null;
}
}

View File

@@ -0,0 +1,9 @@
package de.hsrm.compiler.Klang.nodes;
import de.hsrm.compiler.Klang.types.*;
import de.hsrm.compiler.Klang.visitors.*;
public abstract class Node {
public Type type;
public abstract <R> R welcome(Visitor<R> v);
}

View File

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

View File

@@ -0,0 +1,12 @@
package de.hsrm.compiler.Klang.nodes.expressions;
public abstract class BinaryExpression extends Expression {
public Expression lhs;
public Expression rhs;
public BinaryExpression(Expression lhs, Expression rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
}

View File

@@ -0,0 +1,6 @@
package de.hsrm.compiler.Klang.nodes.expressions;
import de.hsrm.compiler.Klang.nodes.*;
public abstract class Expression extends Node {
}

View File

@@ -0,0 +1,16 @@
package de.hsrm.compiler.Klang.nodes.expressions;
import de.hsrm.compiler.Klang.visitors.Visitor;
public class IntegerExpression extends Expression {
public int value;
public IntegerExpression(int value) {
this.value = value;
}
@Override
public <R> R welcome(Visitor<R> v) {
return v.visit(this);
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,10 @@
package de.hsrm.compiler.Klang.nodes.expressions;
public abstract class UnaryExpression extends Expression {
public Expression lhs;
public UnaryExpression(Expression lhs) {
this.lhs = lhs;
}
}

View File

@@ -0,0 +1,24 @@
package de.hsrm.compiler.Klang.nodes.statements;
import de.hsrm.compiler.Klang.nodes.Block;
import de.hsrm.compiler.Klang.nodes.expressions.Expression;
import de.hsrm.compiler.Klang.visitors.Visitor;
public class IfStatement extends Statement {
public Expression cond;
public Block then;
public Block alt;
public IfStatement(Expression cond, Block then, Block alt) {
this.cond = cond;
this.then = then;
this.alt = alt;
}
@Override
public <R> R welcome(Visitor<R> v) {
return v.visit(this);
}
}

View File

@@ -0,0 +1,17 @@
package de.hsrm.compiler.Klang.nodes.statements;
import de.hsrm.compiler.Klang.nodes.expressions.Expression;
import de.hsrm.compiler.Klang.visitors.Visitor;
public class PrintStatement extends Statement {
public Expression expression;
public PrintStatement(Expression expression) {
this.expression = expression;
}
@Override
public <R> R welcome(Visitor<R> v) {
return v.visit(this);
}
}

View File

@@ -0,0 +1,6 @@
package de.hsrm.compiler.Klang.nodes.statements;
import de.hsrm.compiler.Klang.nodes.Node;
public abstract class Statement extends Node {
}

View File

@@ -0,0 +1,66 @@
package de.hsrm.compiler.Klang.visitors;
import de.hsrm.compiler.Klang.Value;
import de.hsrm.compiler.Klang.nodes.expressions.*;
import de.hsrm.compiler.Klang.nodes.statements.*;
public class EvalVisitor implements Visitor<Value> {
@Override
public Value visit(IntegerExpression e) {
return new Value(e.value);
}
@Override
public Value visit(MultiplicativeExpression e) {
Value a = e.lhs.welcome(this);
Value b = e.rhs.welcome(this);
return new Value(a.asInteger() * b.asInteger());
}
@Override
public Value visit(AdditiveExpression e) {
Value a = e.lhs.welcome(this);
Value b = e.rhs.welcome(this);
return new Value(a.asInteger() + b.asInteger());
}
@Override
public Value visit(ModuloExpression e) {
Value a = e.lhs.welcome(this);
Value b = e.rhs.welcome(this);
return new Value(a.asInteger() % b.asInteger());
}
@Override
public Value visit(NegateExpression e) {
Value a = e.lhs.welcome(this);
return new Value(-a.asInteger());
}
@Override
public Value visit(IfStatement e) {
// In the future we have to make sure that the
// value is actually a type that we can use as boolean
Value condition = e.cond.welcome(this);
if (condition.asInteger() != 0) {
e.then.welcome(this);
} else if(e.alt != null) {
e.alt.welcome(this);
}
return null;
}
@Override
public Value visit(PrintStatement e) {
Value value = e.expression.welcome(this);
// In the future we have to determine of which type the value is
// before calling an "asX()" method
System.out.println(value.asInteger());
return null;
}
}

View File

@@ -0,0 +1,14 @@
package de.hsrm.compiler.Klang.visitors;
import de.hsrm.compiler.Klang.nodes.expressions.*;
import de.hsrm.compiler.Klang.nodes.statements.*;
public interface Visitor<R> {
R visit(IntegerExpression e);
R visit(MultiplicativeExpression e);
R visit(AdditiveExpression e);
R visit(NegateExpression e);
R visit(ModuloExpression e);
R visit(IfStatement e);
R visit(PrintStatement e);
}