Gruppen 5 und 7
Samuel Teuber
propa@teuber.dev
https://teuber.dev/propa
wait
und notify
/notifyAll
benötigen einen aktiven Monitor!curThreads++;
if (curThreads == maxThreads) freeAll();
else wait()
notifyAll
aufrufen, um alle aufzuwecken?Idee: String -> Folge von Tokens
Grammatik $G = \left(\Sigma, V, P, S\right)$
$w \Rightarrow z$ Anwendung einer Produktion auf $w$ ergibt $z$
$w \Rightarrow^*z$ Anwendung einer, mehrer (oder keiner) Produktion verwandelt w in z
$w \Rightarrow^+ z$ Anwendung mind. einer Produktion
(vs. konkreter Syntaxbaum)
Normalerweise konstruiert ein Parser den AST direkt
LL: Liest einmal von links nach rechts, baut dabei Linksableitung auf
$$ P = \{S \rightarrow AB\\ A \rightarrow a \mid aA\\ B \rightarrow ab \} $$$k$-Lookahead
Für $\chi\in\Sigma^*$ ist der $k$-Anfang $k\colon\chi$ der Präfix der Länge $k$ von $\chi\#\#\dots$ ($\#\notin\Sigma$)
Bestimme Menge $First_1$ und $Follow_1$ für alle Nichtterminale
Eine (kontextfreie) Grammatik ist genau dann eine $SSL(k)$-Grammatik, wenn für alle Paare von Produktionen $A \rightarrow \alpha \mid \beta$ ($\alpha \neq \beta$) gilt:
$$ First_k\left(\alpha\ Follow_k\left(A\right)\right) \cap First_k\left(\beta\ Follow_k\left(A\right)\right) = \emptyset $$Für $\alpha \nRightarrow^* \varepsilon$ und $\beta \nRightarrow^* \varepsilon$: $$ SLL \iff First(\alpha) \cap First(\beta) = \emptyset $$
Für $\alpha \Rightarrow^* \varepsilon$ und $\beta \nRightarrow^* \varepsilon$: $$ SLL \iff First(\alpha) \cap First(\beta) = Follow(A) \cap First(\beta) = \emptyset $$
Ist $G$ eine $SLL(1)$-Grammatik?
Vermeiden von gemeinsamen Nichtterminal-Anfängen:
Parse-Funktion für Nichtterminal A:
switch (lexer.current) {...}
expect(TokenType.a);
parseA();
parseB();
Grammatik: $$ \textit{Value} \rightarrow \textbf{string} \mid \textbf{number} \mid \textit{Object}\\ \textit{Object} \rightarrow \textbf{\{} \textit{Members} \textbf{\}}\\ \textit{Members} \rightarrow \textit{Pair } \textit{Members'}\\ \textit{Members'} \rightarrow \textbf{, } \textit{Members} \mid \varepsilon\\ \textit{Pair} \rightarrow \textbf{string} \textbf{ : } \textit{Value} $$
Grammatik: $$ \textit{Value} \rightarrow \textbf{string} \mid \textbf{number} \mid \textit{Object}\\ \textit{Object} \rightarrow \textbf{\{} \textit{Members} \textbf{\}}\\ \textit{Members} \rightarrow \textit{Pair } \textit{Members'}\\ \textit{Members'} \rightarrow \textbf{, } \textit{Members} \mid \varepsilon\\ \textit{Pair} \rightarrow \textbf{string} \textbf{ : } \textit{Value} $$
JSONValue parseValue() {
String s;
switch (token.getType()) {
case STRING: s = token.getSymbol();
nextToken(); return new JSONString(s);
case NUMBER: s = token.getSymbol();
nextToken(); return new JSONNumber(s);
case LCURLY: return parseObject();
default: error();
}
}
JSONObject parseObject() {
switch (token.getType()) {
case LCURLY:
nextToken();
JSONObject o = new JSONObject(parseMembers());
if (token.getType() != RCURLY) error();
nextToken();
return o;
break;
default: error();
}
}
Grammatik: $$ \textit{Value} \rightarrow \textbf{string} \mid \textbf{number} \mid \textit{Object}\\ \textit{Object} \rightarrow \textbf{\{} \textit{Members} \textbf{\}}\\ \textit{Members} \rightarrow \textit{Pair } \textit{Members'}\\ \textit{Members'} \rightarrow \textbf{, } \textit{Members} \mid \varepsilon\\ \textit{Pair} \rightarrow \textbf{string} \textbf{ : } \textit{Value} $$
Pair parsePair() {
if (token.getType() != TokenType.STRING) error();
JSONString s = new JSONString(token.getSymbol());
nextToken();
if (token.getType() != TokenType.COLON) error();
nextToken();
JSONValue v = parseValue();
return new Pair(s, v);
}
Grammatik: $$ \textit{Value} \rightarrow \textbf{string} \mid \textbf{number} \mid \textit{Object}\\ \textit{Object} \rightarrow \textbf{\{} \textit{Members} \textbf{\}}\\ \textit{Members} \rightarrow \textit{Pair } \textit{Members'}\\ \textit{Members'} \rightarrow \textbf{, } \textit{Members} \mid \varepsilon\\ \textit{Pair} \rightarrow \textbf{string} \textbf{ : } \textit{Value} $$
List<Pair> parseMembers() {
List<Pair> l = new LinkedList<Pair>();
l.add(parsePair());
while (true) {
if (token.getType() == COMMA) {
nextToken();
l.add(parsePair());
} else {
break;
}
}
return l;
}
(x + (y * z))-7
- + x * y z 7
x y z * + 7 -
iconst_4
iload_1
imul
iconst_5
iadd
iconst_3
idiv
iconst_2
isub
a * (x - 1) + c
iload_n
, iconst_n
, isub
, imul
, iadd
static
: $p_0$ ist this
invokevirtual
/invokestatic
public classTest {
int bar() {
return foo(42);
}
int foo(int i) {
return i;
}
}
int bar();
aload_0
bipush 42
invokevirtual #2
ireturn
int foo(int);
iload_1
ireturn
if ((a > c) || (c > 0))
a = a - this.f(a * (x - 1) + c);
this
in Variable 0a
-> 1; b
-> 2; c
->3Erstmal nur if
Benötigte Instruktionen:
iload_n
, if_icmpgt <label>
, iconst_n
, goto <label>
???
no_shortcut:
???
then:
...
else:
finish:
a = a - this.f(a * (x - 1) + c);
this
in Variable 0a
-> 1; x
-> 2; c
->3Benötigte Instruktionen:
iload_n
, aload_n
, iconst_n
, isub
, imul
, iadd
, isub
, invokevirtual
, goto
then:
???
else:
finish: