class UebersetzerWhileList(object): def __init__(self, variablenzustand): self.quellcode = None self.programm = [] self.variablenzustand = variablenzustand self.bonsai_code = [] self.bonsai_text = '' self.i = 0 def setQuellcode(self, q): self.quellcode = q def getProgramm(self): return self.programm def getBonsaiCode(self): return self.bonsai_code def getBonsaiText(self): return self.bonsai_text def neueVariable(self, bez): existiertBereits = False for eintrag in self.variablenzustand.variablen: if eintrag[0] == bez: existiertBereits = True if not existiertBereits: self.variablenzustand.variablen = self.variablenzustand.variablen + [[bez, 0]] def c_programm(self, p): 'programm : anweisungsfolge' c = self.c_anweisungsfolge(p) c = c + [('hlt', '')] return c def c_anweisungsfolge(self, p): '''anweisungsfolge : anweisung anweisungsfolge | anweisung''' c = [] for anw in p: c_a = self.c_anweisung(anw) c = c + c_a return c def c_anweisung(self, p): '''anweisung : VAR ZUW term | PASS | WHILE bedingung DP anweisungsfolge END | IF bedingung DP anweisungsfolge ELSE DP anweisungsfolge END''' if p[0] == "=": # Bezeichner ggf in variablenzustand eintragen bez_a = p[1][1] self.neueVariable(bez_a) # Zuweisung vom Typ a = n if p[2][0][0] == 'ZAHL': c = self.c_zuw_a_gleich_n(p) # Zuweisung vom Typ a = b elif p[2][0][0] == 'VAR': c = self.c_zuw_a_gleich_b(p) # Zuweisung vom Typ a = b + n elif p[2][0][0] == '+' and p[2][1][0] == 'VAR' and p[2][2][0] == 'ZAHL': c = self.c_zuw_a_gleich_b_plus_n(p) # Zuweisung vom Typ a = b - n elif p[2][0][0] == '-' and p[2][1][0] == 'VAR' and p[2][2][0] == 'ZAHL': c = self.c_zuw_a_gleich_b_minus_n(p) # Zuweisung vom Typ a = b + c elif p[2][0][0] == '+' and p[2][1][0] == 'VAR' and p[2][2][0] == 'VAR': c = self.c_zuw_a_gleich_b_plus_c(p) # Zuweisung vom Typ a = b - c elif p[2][0][0] == '-' and p[2][1][0] == 'VAR' and p[2][2][0] == 'VAR': c = self.c_zuw_a_gleich_b_minus_c(p) elif p[0] == "if": c = self.c_if(p) elif p[0] == "while": c = self.c_while(p) elif p[0] == "pass": c = [] return c def neueHilfsvariable(self): bez_h = '_h'+str(self.i) self.neueVariable(bez_h) self.i = self.i+1 return bez_h def c_zuw_a_gleich_null(self, bez_a): """ AZ {a: n} EZ {a: 0} """ c = \ [('tst', bez_a), ('jmp', '(+2)'), ('jmp', '(+3)'), ('dec', bez_a), ('jmp', '(-4)')] return c def c_trans_a_nach_b_und_c(self, bez_a, bez_b, bez_c): """ AZ {a: n; b: 0; c: 0} EZ {a: 0; b: n; c: n} """ c = \ [('tst', bez_a), ('jmp', '(+2)'), ('jmp', '(+5)'), ('dec', bez_a), ('inc', bez_b), ('inc', bez_c), ('jmp', '(-6)')] return c def c_trans_a_nach_b(self, bez_a, bez_b): """ AZ {a: n; b: 0} EZ {a: 0; b: n} """ c = \ [('tst', bez_a), ('jmp', '(+2)'), ('jmp', '(+4)'), ('dec', bez_a), ('inc', bez_b), ('jmp', '(-5)')] return c def c_zuw_a_gleich_n(self, p): bez_a = p[1][1] wert_n = int(p[2][0][1]) # a = 0 c = self.c_zuw_a_gleich_null(bez_a) # n mal inc a for i in range(wert_n): c = c + [('inc', bez_a)] return c def c_zuw_a_gleich_b(self, p): bez_a = p[1][1] bez_b = p[2][0][1] # Hilfsvariable erzeugen bez_h = self.neueHilfsvariable() # a = 0 c = self.c_zuw_a_gleich_null(bez_a) # b -> a, h c = c + self.c_trans_a_nach_b_und_c(bez_b, bez_a, bez_h) # h -> b c = c + self.c_trans_a_nach_b(bez_h, bez_b) # Zähler für Hilfsvariablen zurücksetzen self.i = self.i-1 return c def c_zuw_a_gleich_b_plus_n(self, p): bez_a = p[1][1] bez_b = p[2][1][1] wert_n = int(p[2][2][1]) # Hilfsvariablen erzeugen bez_h_b = self.neueHilfsvariable() bez_h_k = self.neueHilfsvariable() # b -> h_b, h_k c = self.c_trans_a_nach_b_und_c(bez_b, bez_h_b, bez_h_k) # h_k -> b c = c + self.c_trans_a_nach_b(bez_h_k, bez_b) # n mal inc h_b for i in range(wert_n): c = c + [('inc', bez_h_b)] # a = 0 c = c + self.c_zuw_a_gleich_null(bez_a) # h_b -> a c = c + self.c_trans_a_nach_b(bez_h_b, bez_a) # Zähler für Hilfsvariablen zurücksetzen self.i = self.i-1 self.i = self.i-1 return c def c_zuw_a_gleich_b_minus_n(self, p): bez_a = p[1][1] bez_b = p[2][1][1] wert_n = int(p[2][2][1]) # Hilfsvariablen erzeugen bez_h_b = self.neueHilfsvariable() bez_h_k = self.neueHilfsvariable() # b -> h_b, h_k c = self.c_trans_a_nach_b_und_c(bez_b, bez_h_b, bez_h_k) # h_k -> b c = c + self.c_trans_a_nach_b(bez_h_k, bez_b) # n mal dec h_b for i in range(wert_n): c = c + \ [('dec', bez_h_b)] # a = 0 c = c + self.c_zuw_a_gleich_null(bez_a) # h_b -> a c = c + self.c_trans_a_nach_b(bez_h_b, bez_a) # Zähler für Hilfsvariablen zurücksetzen self.i = self.i-1 self.i = self.i-1 return c def c_zuw_a_gleich_b_plus_c(self, p): bez_a = p[1][1] bez_b = p[2][1][1] bez_c = p[2][2][1] # Hilfsvariablen erzeugen bez_h_e = self.neueHilfsvariable() bez_h_k = self.neueHilfsvariable() # b -> h_e, h_k c = self.c_trans_a_nach_b_und_c(bez_b, bez_h_e, bez_h_k) # h_k -> b c = c + self.c_trans_a_nach_b(bez_h_k, bez_b) # c -> h_e, h_k c = c + self.c_trans_a_nach_b_und_c(bez_c, bez_h_e, bez_h_k) # h_k -> c c = c + self.c_trans_a_nach_b(bez_h_k, bez_c) # a = 0 c = c + self.c_zuw_a_gleich_null(bez_a) # h_e -> a c = c + self.c_trans_a_nach_b(bez_h_e, bez_a) # Zähler für Hilfsvariablen zurücksetzen self.i = self.i-1 self.i = self.i-1 return c def c_zuw_a_gleich_b_minus_c(self, p): bez_a = p[1][1] bez_b = p[2][1][1] bez_c = p[2][2][1] # Hilfsvariablen erzeugen bez_h_b = self.neueHilfsvariable() bez_h_c = self.neueHilfsvariable() bez_h_k = self.neueHilfsvariable() # b -> h_b, h_k c = self.c_trans_a_nach_b_und_c(bez_b, bez_h_b, bez_h_k) # h_k -> b c = c + self.c_trans_a_nach_b(bez_h_k, bez_b) # c -> h_c, h_k c = c + self.c_trans_a_nach_b_und_c(bez_c, bez_h_c, bez_h_k) # h_k -> c c = c + self.c_trans_a_nach_b(bez_h_k, bez_c) # h_c mal h_b-- und h_c-- c = c + \ [('tst', bez_h_c), ('jmp', '(+2)'), ('jmp', '(+4)'), ('dec', bez_h_c), ('dec', bez_h_b), ('jmp', '(-5)')] # a = 0 c = c + self.c_zuw_a_gleich_null(bez_a) # h_b -> a c = c + self.c_trans_a_nach_b(bez_h_b, bez_a) # Zähler für Hilfsvariablen zurücksetzen self.i = self.i-1 self.i = self.i-1 self.i = self.i-1 return c def c_bedingung(self, p, bez_h): if p[0] == "==" and p[1][0] == 'VAR' and p[2][0] == 'ZAHL' and p[2][1] == '0': c = self.c_bed_a_gleich_null(p, bez_h) elif p[0] == "!=" and p[1][0] == 'VAR' and p[2][0] == 'ZAHL' and p[2][1] == '0': c = self.c_bed_a_ungleich_null(p, bez_h) elif p[0] == "<=" and p[1][0] == 'VAR' and p[2][0] == 'VAR': c = self.c_bed_a_kleinergleich_b(p, bez_h) elif p[0] == "<" and p[1][0] == 'VAR' and p[2][0] == 'VAR': c = self.c_bed_a_kleiner_b(p, bez_h) elif p[0] == "==" and p[1][0] == 'VAR' and p[2][0] == 'VAR': c = self.c_bed_a_gleich_b(p, bez_h) elif p[0] == "!=" and p[1][0] == 'VAR' and p[2][0] == 'VAR': c = self.c_bed_a_ungleich_b(p, bez_h) return c def c_bed_a_gleich_null(self, p, bez_h): bez_a = p[1][1] # h = 0 c = self.c_zuw_a_gleich_null(bez_h) # h ggf. auf 1 c = c + \ [('tst', bez_a), ('jmp', '(+2)'), ('inc', bez_h),] return c def c_bed_a_ungleich_null(self, p, bez_h): bez_a = p[1][1] # h = 0 c = self.c_zuw_a_gleich_null(bez_h) # h ggf. auf 1 c = c + \ [('tst', bez_a), ('jmp', '(+2)'), ('jmp', '(+2)'), ('inc', bez_h)] return c def c_bed_a_gleich_b(self, p, bez_h): bez_a = p[1][1] bez_b = p[2][1] # Hilfsvariablen erzeugen bez_h_c = self.neueHilfsvariable() # h = 0 c = self.c_zuw_a_gleich_null(bez_h) # 0 < a, b -> a--, b-- c = c + \ [('tst', bez_a), ('jmp', '(+4)'), ('tst', bez_b), ('jmp', '(+10)'), ('jmp', '(+8)'), ('tst', bez_b), ('jmp', '(+2)'), ('jmp', '(+6)'), # a != 0 & b != 0 ('dec', bez_a), ('dec', bez_b), ('inc', bez_h_c), ('jmp', '(-11)'), # a == 0 & b == 0 -> h = 1 ('inc', bez_h)] # h_c -> a, b c = c + self.c_trans_a_nach_b_und_c(bez_h_c, bez_a, bez_b) return c def c_bed_a_ungleich_b(self, p, bez_h): bez_a = p[1][1] bez_b = p[2][1] # Hilfsvariablen erzeugen bez_h_c = self.neueHilfsvariable() # h = 0 c = self.c_zuw_a_gleich_null(bez_h) # 0 < a, b -> a--, b-- c = c + \ [('tst', bez_a), ('jmp', '(+4)'), ('tst', bez_b), ('jmp', '(+9)'), ('jmp', '(+9)'), ('tst', bez_b), ('jmp', '(+2)'), ('jmp', '(+5)'), # h_a != 0 & h_b != 0 ('dec', bez_a), ('dec', bez_b), ('inc', bez_h_c), ('jmp', '(-11)'), # a == 0 & b >= 0 -> h = 1 ('inc', bez_h)] # c -> a, b c = c + self.c_trans_a_nach_b_und_c(bez_h_c, bez_a, bez_b) return c def c_bed_a_kleinergleich_b(self, p, bez_h): bez_a = p[1][1] bez_b = p[2][1] # Hilfsvariablen erzeugen bez_h_c = self.neueHilfsvariable() # h = 0 c = self.c_zuw_a_gleich_null(bez_h) # 0 < a, b -> a--, b-- c = c + \ [('tst', bez_a), ('jmp', '(+4)'), ('tst', bez_b), ('jmp', '(+9)'), ('jmp', '(+8)'), ('tst', bez_b), ('jmp', '(+2)'), ('jmp', '(+6)'), # h_a != 0 & h_b != 0 ('dec', bez_a), ('dec', bez_b), ('inc', bez_h_c), ('jmp', '(-11)'), # a == 0 & b >= 0 -> h = 1 ('inc', bez_h)] # c -> a, b c = c + self.c_trans_a_nach_b_und_c(bez_h_c, bez_a, bez_b) return c def c_bed_a_kleiner_b(self, p, bez_h): bez_a = p[1][1] bez_b = p[2][1] # Hilfsvariablen erzeugen bez_h_c = self.neueHilfsvariable() # h = 0 c = self.c_zuw_a_gleich_null(bez_h) # 0 < a, b -> a--, b-- c = c + \ [('tst', bez_a), ('jmp', '(+4)'), ('tst', bez_b), ('jmp', '(+9)'), ('jmp', '(+9)'), ('tst', bez_b), ('jmp', '(+2)'), ('jmp', '(+6)'), # h_a != 0 & h_b != 0 ('dec', bez_a), ('dec', bez_b), ('inc', bez_h_c), ('jmp', '(-11)'), # a == 0 & b >= 0 -> h = 1 ('inc', bez_h)] # c -> a, b c = c + self.c_trans_a_nach_b_und_c(bez_h_c, bez_a, bez_b) return c def c_while(self, p): # Hilfsvariable fuer das Ergebnis bei der Auswertung der Bedingung erzeugen bez_h = self.neueHilfsvariable() # Code fuer die Bedingung erzeugen bed = p[1] c_bed = self.c_bedingung(bed, bez_h) # Code fuer den Schleifenkoerper erzeugen anwf = p[2] c_anwf = self.c_anweisungsfolge(anwf) # Laenge der relativen Spruenge festlegen m = len(c_anwf) + 2 n = len(c_anwf) + len(c_bed) + 3 jmp_m = '(+'+str(m)+')' jmp_n = '(-'+str(n)+')' # Code fuer die while-Anweisung erzeugen c = c_bed + \ [('tst', bez_h), ('jmp', '(+2)'), ('jmp', jmp_m)] + \ c_anwf + \ [('jmp', jmp_n)] # Hilfsvariable wieder auf 0 setzen c = c + \ [('tst', bez_h), ('jmp', '(+2)'), ('jmp', '(+3)'), ('dec', bez_h), ('jmp', '(-4)')] # Zähler für Hilfsvariablen zurücksetzen self.i = self.i-1 return c def c_if(self, p): # Hilfsvariable fuer das Ergebnis bei der Auswertung der Bedingung erzeugen bez_h = self.neueHilfsvariable() # Code fuer die Bedingung erzeugen bed = p[1] c_bed = self.c_bedingung(bed, bez_h) # Code fuer den True-Fall erzeugen anwTrue = p[2] c_anw_true = self.c_anweisungsfolge(anwTrue) # Code fuer den False-Fall erzeugen anwFalse = p[3] c_anw_false = self.c_anweisungsfolge(anwFalse) # Laenge der relativen Spruenge festlegen m = len(c_anw_true) + 2 n = len(c_anw_false) + 1 jmp_ueber_true = '(+'+str(m)+')' jmp_ueber_false = '(+'+str(n)+')' # Code fuer die while-Anweisung erzeugen c = c_bed + \ [('tst', bez_h), ('jmp', '(+2)'), ('jmp', jmp_ueber_true)] + \ c_anw_true + \ [('jmp', jmp_ueber_false)] + \ c_anw_false # Hilfsvariable wieder auf 0 setzen c = c + \ [('tst', bez_h), ('jmp', '(+2)'), ('jmp', '(+3)'), ('dec', bez_h), ('jmp', '(-4)')] # Zähler für Hilfsvariablen zurücksetzen self.i = self.i-1 return c def uebersetzen(self): self.i = 0 if self.quellcode != None: print('#') c = self.c_programm(self.quellcode) self.programm = c else: self.programm = None def erzeugeBonsaiCode(self): self.bonsai_code = [] laengeProgramm = len(self.programm) z = 0 for anw in self.programm: if anw[0] == 'inc': var = anw[1] var_reg_nr = self.variablenzustand.getIndex(var) anwBonsai = ('inc', var_reg_nr) elif anw[0] == 'dec': var = anw[1] var_reg_nr = self.variablenzustand.getIndex(var) anwBonsai = ('dec', var_reg_nr) elif anw[0] == 'tst': var = anw[1] var_reg_nr = self.variablenzustand.getIndex(var) anwBonsai = ('tst', var_reg_nr) elif anw[0] == 'jmp': relAddr = eval(anw[1]) absAddr = z + relAddr anwBonsai = ('jmp', absAddr) elif anw[0] == 'hlt': anwBonsai = ('hlt', None) self.bonsai_code = self.bonsai_code + [anwBonsai] z = z + 1 for eintrag in self.variablenzustand.variablen: self.bonsai_code = self.bonsai_code + [(eintrag[0], 0)] def erzeugeBonsaiText(self): self.bonsai_text = '' laengeProgramm = len(self.programm) z = 0 while z < laengeProgramm: if self.bonsai_code[z][0] == 'hlt': self.bonsai_text = self.bonsai_text + str(z) + ': ' + \ self.bonsai_code[z][0] + '\n' else: self.bonsai_text = self.bonsai_text + str(z) + ': ' + \ self.bonsai_code[z][0] + ' ' + str(self.bonsai_code[z][1]) + '\n' z = z + 1 for v in self.variablenzustand.variablen: self.bonsai_text = self.bonsai_text + '#0' + '\n'