Programmieren in Java Vorlesung 10: Ein Interpreter f¨ ur While

Prof. Dr. Peter Thiemann Albert-Ludwigs-Universit¨ at Freiburg, Germany

SS 2015

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

1 / 18

Inhalt

Interpreter f¨ ur While Die Sprache While Ausf¨ uhrung von While Testen

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

2 / 18

Interpreter fu¨r While

Interpreter f¨ ur While

Interpreter

I

I

Ein Interpreter ist ein Programm zur Ausf¨ uhrung von anderen Programmen Eingaben I I

I

Ein Programm (-text) P in einer Sprache L Die Eingabe f¨ ur das Programm P

Ausgabe I

Die Ausgabe des Programms P

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

4 / 18

Interpreter f¨ ur While

Architektur des Interpreters

I

Parser I I

I

Einlesen des Programmtextes Erstellen einer Objektrepr¨asentation des Programmtextes abstract syntax tree (AST)

Runner I I I

Durchlaufen des AST Ausf¨ uhren der Statements Auswerten von Ausdr¨ ucken

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

5 / 18

Die Sprache While

Interpreter f¨ ur While

Die Sprache While

Syntax von While BNF f¨ur While hstmti

::= | | | hstmt1 i ::= |

I I

I

hvar i = hexpr i Zuweisung if ( hexpr i ) hstmti else hstmti Bedingte Anweisung while ( hexpr i ) hstmti While Schleife { hstmt1 i Sequenz } . . . leer hstmti ; hstmt1 i n¨achste Anweisung

hstmti = Statement = Anweisung hstmt1i spezifiziert eine Liste von Anweisungen, wobei jede Anweisung durch Semikolon abgeschlossen ist und das Ende mit schließender geschweifter Klammer markiert ist hexpri = arithmetische Ausdr¨ ucke, wie gehabt

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

7 / 18

Interpreter f¨ ur While

Die Sprache While

Objektrepr¨asentation (AST)

1 2 3

1 2 3 4 5 6

I

Composite und Visitor Pattern

I

Hier: Visitor ohne R¨ uckgabewert

public interface IStmt { void accept(StmtVisitor v); } public interface StmtVisitor { void visitAssign(Assign s); void visitIf(If s); void visitSequence(Sequence s); void visitWhile(While s); }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

8 / 18

Interpreter f¨ ur While

Die Sprache While

Objektrepr¨asentation (AST) II 1 2 3 4 5 6 7

1 2 3 4 5 6 7 8

public class Assign implements IStmt { public final String var; public final IExpr exp; public void accept(StmtVisitor v) { v.visitAssign(this); } } public class If implements IStmt { public final IExpr condition; public final IStmt trueBranch; public final IStmt falseBranch; public void accept(StmtVisitor v) { v.visitIf(this); } } I

1 2 3 4 5 6 7

1 2 3 4 5 6

public class While implements IStmt { public final IExpr condition; public final IStmt body; public void accept(StmtVisitor v) { v.visitWhile(this); } } public class Sequence implements IStmt { public final Collection stmts; public void accept(StmtVisitor v) { v.visitSequence(this); } }

F¨ ur jede Art Anweisung eine Klasse (mit Standardkonstruktor)

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

9 / 18

Parser fu¨r While

Interpreter f¨ ur While

Die Sprache While

Parser f¨ur While I

Gleiches Muster wie f¨ ur Ausdr¨ ucke: recursive descent parser

I

M¨oglichkeit: Erweiterung des Ausdrucksparsers mittels Vererbung ¨ Kleine Anderungen am Ausdrucksparser lecture20150622.Parser erforderlich: die privaten Methoden f¨ ur den Scanner m¨ ussen protected gemacht werden

I

1 2 3 4 5 6

protected boolean lookingAt(String regex) { return scan.lookingAt(regex); } protected String getLexeme(String regex) { return scan.getLexeme(regex); }

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

11 / 18

Interpreter f¨ ur While

Die Sprache While

Parser f¨ur If-Anweisung (Beispiel, Auszug) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

public IStmt parseStmt() { String lexeme = scan.getLexeme(REGEX WORD); if (”if”.equals(lexeme)) { // ”if” . ”(” ”)” ”else” if (scan.getLexeme(REGEX OPEN PAREN) != null) { // ”if” ”(” . ”)” ”else” IExpr condition = parseExpr(); // ”if” ”(” . ”)” ”else” if (scan.getLexeme(REGEX CLOSE PAREN) != null) { // ”if” ”(” ”)” . ”else” IStmt trueBranch = parseStmt(); // ”if” ”(” ”)” . ”else” if (scan.getLexeme(”else”) != null) { // ”if” ”(” ”)” ”else” . IStmt falseBranch = parseStmt(); // ”if” ”(” ”)” ”else” . return new If(condition, trueBranch, falseBranch); }}}} Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

12 / 18

Ausfu¨hrung von While

Interpreter f¨ ur While

Ausf¨ uhrung von While

Ausf¨uhrung von While

I

Durch RunVisitor, eine Implementierung von StmtVisitor

I

Interner Zustand des RunVisitor ist die Belegung der Variablen

I

Repr¨asentiert durch eine Abbildung von Variablennamen auf Zahlen: Map

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

14 / 18

Interpreter f¨ ur While

Ausf¨ uhrung von While

RunVisitor public void visitIf(If s) { if (s.condition.accept(eval) != 0) { s.trueBranch.accept(this); } else { s.falseBranch.accept(this); } } public void visitSequence(Sequence s) { for(IStmt stmt : s.stmts) { stmt.accept(this); } } public void visitWhile(While s) { while( s.condition.accept(eval) != 0) { s.body.accept(this); } }

1 1 2

public class RunVisitor implements StmtVisitor {

2 3

3 4 5

4

public final Map state; private final IExprVisitor eval;

6 7 8 9 10 11

14 15 16

6 7

public RunVisitor( Map state) { this.state = state; this.eval = new Eval(state); }

12 13

5

8 9 10 11 12 13

public void visitAssign(Assign s) { int value = s.exp.accept(eval); state.put(s.var, value); }

14 15 16 17 18

Peter Thiemann (Univ. Freiburg)

}

Programmieren in Java

JAVA

15 / 18

Testen des Interpreters

Interpreter f¨ ur While

Testen

Testen des Interpreters

1 2

I

Mittels JUnit Testf¨allen

I

F¨ ur jeden Testfall muss zun¨achst eine Belegung der Variablen, also eine Map, generiert werden und damit ein RunVisitor instanziert werden:

Map state = new HashMap(); RunVisitor r = new RunVisitor(state); I

Anstatt diese Anweisungen in jedem Testfall zu wiederholen, kann eine Before-Methode geschrieben werden.

I

Daf¨ ur m¨ ussen die Werte in Instanzvariable der Testklasse verlagert werden.

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

17 / 18

Interpreter f¨ ur While

Testen

Before-Methode 1 2 3 4 5 6 7 8 9 10 11 12 13

public class RunVisitorTest { private Map state; private RunVisitor r; @Before public void setup() { state = new HashMap(); r = new RunVisitor(state); } @Test public void test() { IStmt ass1 = new Assign(”x”, cnst(1)); ass1.accept(r); assertEquals(state.get(”x”), new Integer(1)); } }

Vor jedem Testfall mit Annotation

@Test

I

wird eine neue RunVisitorTest Instanz erzeugt

I

werden die Methoden mit Annotation @Before ausgef¨ uhrt

Peter Thiemann (Univ. Freiburg)

Programmieren in Java

JAVA

18 / 18