add context analysis and custom visitors
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.*;
|
||||
|
||||
75
src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java
Normal file
75
src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
19
src/main/java/de/hsrm/compiler/Klang/nodes/Block.java
Normal file
19
src/main/java/de/hsrm/compiler/Klang/nodes/Block.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
9
src/main/java/de/hsrm/compiler/Klang/nodes/Node.java
Normal file
9
src/main/java/de/hsrm/compiler/Klang/nodes/Node.java
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package de.hsrm.compiler.Klang.nodes.expressions;
|
||||
|
||||
import de.hsrm.compiler.Klang.nodes.*;
|
||||
|
||||
public abstract class Expression extends Node {
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package de.hsrm.compiler.Klang.nodes.statements;
|
||||
|
||||
import de.hsrm.compiler.Klang.nodes.Node;
|
||||
|
||||
public abstract class Statement extends Node {
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
14
src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java
Normal file
14
src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user