Programmieren in Java - Vorlesung 10: Ein Interpreter für While

Werbung
Programmieren in Java
Vorlesung 10: Ein Interpreter für While
Prof. Dr. Peter Thiemann
Albert-Ludwigs-Universität Freiburg, Germany
SS 2015
Peter Thiemann (Univ. Freiburg)
Programmieren in Java
JAVA
1 / 18
Inhalt
Interpreter für While
Die Sprache While
Ausführung von While
Testen
Peter Thiemann (Univ. Freiburg)
Programmieren in Java
JAVA
2 / 18
Interpreter für While
Interpreter für While
Interpreter
I
I
Ein Interpreter ist ein Programm zur Ausführung von anderen
Programmen
Eingaben
I
I
I
Ein Programm (-text) P in einer Sprache L
Die Eingabe für das Programm P
Ausgabe
I
Die Ausgabe des Programms P
Peter Thiemann (Univ. Freiburg)
Programmieren in Java
JAVA
4 / 18
Interpreter für While
Architektur des Interpreters
I
Parser
I
I
I
Einlesen des Programmtextes
Erstellen einer Objektrepräsentation des Programmtextes
abstract syntax tree (AST)
Runner
I
I
I
Durchlaufen des AST
Ausführen der Statements
Auswerten von Ausdrücken
Peter Thiemann (Univ. Freiburg)
Programmieren in Java
JAVA
5 / 18
Die Sprache While
Interpreter für While
Die Sprache While
Syntax von While
BNF für 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ächste 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ücke, wie gehabt
Peter Thiemann (Univ. Freiburg)
Programmieren in Java
JAVA
7 / 18
Interpreter für While
Die Sprache While
Objektrepräsentation (AST)
1
2
3
1
2
3
4
5
6
I
Composite und Visitor Pattern
I
Hier: Visitor ohne Rückgabewert
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ür While
Die Sprache While
Objektrepräsentation (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<IStmt> stmts;
public void accept(StmtVisitor v) {
v.visitSequence(this);
}
}
Für jede Art Anweisung eine Klasse (mit Standardkonstruktor)
Peter Thiemann (Univ. Freiburg)
Programmieren in Java
JAVA
9 / 18
Parser für While
Interpreter für While
Die Sprache While
Parser für While
1
2
3
4
5
6
I
Gleiches Muster wie für Ausdrücke:
recursive descent parser
I
Möglichkeit: Erweiterung des Ausdrucksparsers mittels Vererbung
I
Kleine Änderungen am Ausdrucksparser lecture20150622.Parser
erforderlich:
die privaten Methoden für den Scanner müssen protected gemacht
werden
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ür While
Die Sprache While
Parser für 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” . ”(” <expr> ”)” <stmt> ”else” <stmt>
if (scan.getLexeme(REGEX OPEN PAREN) != null) {
// ”if” ”(” . <expr> ”)” <stmt> ”else” <stmt>
IExpr condition = parseExpr();
// ”if” ”(” <expr> . ”)” <stmt> ”else” <stmt>
if (scan.getLexeme(REGEX CLOSE PAREN) != null) {
// ”if” ”(” <expr> ”)” . <stmt> ”else” <stmt>
IStmt trueBranch = parseStmt();
// ”if” ”(” <expr> ”)” <stmt> . ”else” <stmt>
if (scan.getLexeme(”else”) != null) {
// ”if” ”(” <expr> ”)” <stmt> ”else” . <stmt>
IStmt falseBranch = parseStmt();
// ”if” ”(” <expr> ”)” <stmt> ”else” <stmt> .
return new If(condition, trueBranch, falseBranch);
}}}}
Peter Thiemann (Univ. Freiburg)
Programmieren in Java
JAVA
12 / 18
Ausführung von While
Interpreter für While
Ausführung von While
Ausführung von While
I
Durch RunVisitor, eine Implementierung von StmtVisitor
I
Interner Zustand des RunVisitor ist die Belegung der Variablen
I
Repräsentiert durch eine Abbildung von Variablennamen auf Zahlen:
Map<String,Integer>
Peter Thiemann (Univ. Freiburg)
Programmieren in Java
JAVA
14 / 18
Interpreter für While
Ausführung 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<String,Integer> state;
private final IExprVisitor eval;
6
7
8
9
10
11
14
15
16
6
7
public RunVisitor(
Map<String,Integer> 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ür While
Testen
Testen des Interpreters
1
2
I
Mittels JUnit Testfällen
I
Für jeden Testfall muss zunächst eine Belegung der Variablen, also
eine Map, generiert werden und damit ein RunVisitor instanziert werden:
Map<String,Integer> state = new HashMap<String,Integer>();
RunVisitor r = new RunVisitor(state);
I
Anstatt diese Anweisungen in jedem Testfall zu wiederholen, kann
eine Before-Methode geschrieben werden.
I
Dafür müssen die Werte in Instanzvariable der Testklasse verlagert
werden.
Peter Thiemann (Univ. Freiburg)
Programmieren in Java
JAVA
17 / 18
Interpreter für While
Testen
Before-Methode
1
2
3
4
5
6
7
8
9
10
11
12
13
public class RunVisitorTest {
private Map<String, Integer> state;
private RunVisitor r;
@Before public void setup() {
state = new HashMap<String,Integer>();
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ührt
Peter Thiemann (Univ. Freiburg)
Programmieren in Java
JAVA
18 / 18
Herunterladen