diff --git a/draw/Iinstruction.py b/draw/Iinstruction.py index 3cacee9..51d525e 100644 --- a/draw/Iinstruction.py +++ b/draw/Iinstruction.py @@ -2,8 +2,6 @@ from typing import Iterable, List from abc import abstractmethod from draw import code_to_image as cti - - class Iinstruction: """Base class for all instructions""" @@ -18,6 +16,10 @@ class Iinstruction: def getblksize(self) -> float: return self._getblksize() + @abstractmethod + def __str__(self) -> str: + pass + def _getblksize(self) -> float: return cti.get_text_size(self.instruction_text)[1] @@ -31,7 +33,8 @@ class generic_instruction(Iinstruction): def to_image(self, x:int, y:int, x_sz: int) -> Iterable[float]: return cti.draw_generic_instruction(self.instruction_text, x, y, x_sz, self.getblksize()) - + def __str__(self) -> str: + return self.instruction_text class if_instruction(Iinstruction): """Conditional structure @@ -79,6 +82,18 @@ class if_instruction(Iinstruction): for instruction in self.false_case: x, y = instruction.to_image(x, y, x_sz) + def __str__(self) -> str: + res = f"if({self.instruction_text}) {'{'}\n" + for inst in self.true_case: + res += '\t'+str(inst)+";\n" + res += "}" + if self.false_case: + res += " else {" + for inst in self.true_case: + res += '\t'+str(inst)+";\n" + res += "}" + return res + #TODO # class switch_instruction(Iinstruction): # """Switch structure""" @@ -124,6 +139,13 @@ class while_instruction_front(Iinstruction): x, y = inst.to_image(x, y, x_sz) return self.get_children_size() + def __str__(self) -> str: + res = "while(" + self.instruction_text + "){\n" + for inst in self.child_instructions: + res += '\t'+str(inst)+";\n" + res += '}' + return res + class while_instruction_back(while_instruction_front): def __init__(self, condition: str, instructions: List[Iinstruction]) -> None: @@ -132,4 +154,11 @@ class while_instruction_back(while_instruction_front): def to_image(self, x:int, y:int, x_sz: int): children_x, children_y, children_sz_x = cti.draw_while_loop_back(self.instruction_text, x, y, x_sz, self.getblksize()) self.draw_children(children_x, children_y, children_sz_x) - return x, y + self.getblksize() \ No newline at end of file + return x, y + self.getblksize() + + def __str__(self) -> str: + res = "do{\n" + for inst in self.child_instructions: + res += '\t' +str(inst) + ";\n" + res += f"{'}'}while({self.instruction_text});" + return res \ No newline at end of file diff --git a/interpreter/NassiShneidermann.py b/interpreter/NassiShneidermann.py index ad85873..2a99b0d 100644 --- a/interpreter/NassiShneidermann.py +++ b/interpreter/NassiShneidermann.py @@ -29,6 +29,15 @@ class NassiShneidermanDiagram: h += inst.getblksize() return int(h) + def _save_scope(self, scope_name: str, scope_instructions: List[Iinstruction]): + """DEBUGING ONLY""" + image_y_sz = 1000 + x, y, = 0, 0 + with NSD_writer(f"./{scope_name}", 1000, image_y_sz): + x, y = 0, 0 + for instruction in scope_instructions: + x, y = instruction.to_image(x, y, 1000) + def convert_to_image(self, output_path: str, filename: str, x_size: int=200): for i in range(len(self.scopes)): filepath = f"{output_path}/{filename}#{i}" diff --git a/interpreter/interpret_source.py b/interpreter/interpret_source.py index 62df4b7..c037fab 100644 --- a/interpreter/interpret_source.py +++ b/interpreter/interpret_source.py @@ -6,6 +6,11 @@ from typing import List, Tuple from errors.custom import InterpreterException, JavaSyntaxError, ScopeNotFoundException from draw.Iinstruction import * +logging.warning("""As the Interpreter is still WIP, some Java language features are not supported. These include: + *else if statements + *for loops +Please remove these features from the source code as they will result in incorrect behaviour""") + COMMENT_PATTERN = re.compile(r"""^//|^/\*\*|^\*|^--""") REMOVE_KEYWORDS = [' ', "public", "private", ';'] VARIABLE_TAGS = ["byte", "short", "int", "long", "float", "double", "boolean", "char", "String"] @@ -29,10 +34,6 @@ function_regex = function_regex[0:-1]+ r""").*([(].*[)].*)""" function_pattern = re.compile(function_regex) -logging.warn("""The Interpreter is WIP and cannot interpret classes or function definitions -as those do not exist in Nass-Shneidermann Diagrams. A fix is in the making -""") - def replace_all_tags(org: str): return remove_pattern.sub(lambda m: REPLACE[re.escape(m.group(0))], org) @@ -45,9 +46,9 @@ def load_src(filepath: str) -> List[str]: line = replace_all_tags(_line.strip()) if line and not COMMENT_PATTERN.match(line): lines.append(line) - if line.__contains__('{'): + if '{' in line: brace_open_count += 1 - if line.__contains__('}'): + if '}' in line: brace_closed_count += 1 except: raise FileNotFoundError(f"File {filepath} was not found!") @@ -60,7 +61,7 @@ def load_src(filepath: str) -> List[str]: def check_src(src: List[str], line_index: int, tag: str) -> bool: if line_index >= len(src): return False - return src[line_index].__contains__(tag) + return tag in src[line_index] def check_line_start(src: List[str], line_index: int, tag: str) -> bool: if line_index >= len(src): @@ -88,11 +89,13 @@ def get_scope_exit_offset(src: List[str], start_idx: int) -> int: while i < len(src): line = src[i] - if "{" in line: - i+= get_scope_exit_offset(src, i+1) - elif "}" in line: - return i-start_idx - i+=1 + if '{' in line: + i += get_scope_exit_offset(src, i+1) + line = src[i+1] + if '}' in line: + return i - start_idx + i += 1 + raise ScopeNotFoundException("Unable to find scope end. Is the program ill-formed?") def handle_while(line: str, src: List[str], i: int) -> Tuple[Iinstruction, int]: @@ -170,7 +173,7 @@ def get_instructions_in_scope(src: List[str], start_idx: int = 0) -> Tuple[List[ line = src[i] try: - if check_src(src, i, "}"): #We exited this scope, return it + if check_src(src, i, '}'): #We exited this scope, return it break instruction, i = handle_instruction(line, src, i) @@ -186,7 +189,7 @@ def get_instructions_in_scope(src: List[str], start_idx: int = 0) -> Tuple[List[ return outer_scope, i -def get_function_scope_spans(src: List[str]) -> List[Tuple[int, int]]: +def get_function_scope_spans(src: List[str]) -> List[Tuple[int, int, str]]: spans = [] i = 0 while i < len(src): @@ -196,9 +199,13 @@ def get_function_scope_spans(src: List[str]) -> List[Tuple[int, int]]: if match:= function_pattern.match(line): groups = match.groups() function_name = line.removeprefix(groups[0]).removesuffix(groups[1]) + function_return_type = groups[0] + function_args = groups[1][1:-1] brace_offset = get_scope_start_offset(src, i) scope_offset = get_scope_exit_offset(src, i+brace_offset) - span = (i+brace_offset, i+brace_offset+scope_offset) + + span = (i+brace_offset, i+brace_offset+scope_offset, function_name) + i += scope_offset + brace_offset spans.append(span) @@ -209,16 +216,36 @@ def get_function_scope_spans(src: List[str]) -> List[Tuple[int, int]]: return spans -def scope_handler (int_info: Tuple[List[str], Tuple[int, int]]) -> List[Iinstruction]: - return get_instructions_in_scope(int_info[0][int_info[1][0]: int_info[1][1]])[0] +def scope_handler(inst_info: Tuple[List[str], List[int]]) -> List[Iinstruction]: + src = inst_info[0] + scope_start = inst_info[1][0] + scope_end = inst_info[1][1] + return get_instructions_in_scope(src[scope_start: scope_end])[0] -def get_instructions_in_scopes(src: List[str], scope_spans: List[Tuple[int, int]]): - instructions = list(map(scope_handler, [(src, scope_span) for scope_span in scope_spans])) +def named_scope_handler(inst_info: Tuple[List[str], Tuple[int, int, str]]) -> Tuple[str, List[Iinstruction]]: + src = inst_info[0] + scope_start = inst_info[1][0] + scope_end = inst_info[1][1] + function_name = inst_info[1][2] + function_instructions, _ = get_instructions_in_scope(src[scope_start: scope_end]) + return (function_name, function_instructions) + +def get_instructions_in_scopes(src: List[str], scope_spans: List[Tuple[int, int, str]]) -> List[List[Iinstruction]]: + instructions = list(map(scope_handler, [(src, span[0:2]) for span in scope_spans])) return instructions +def get_instructions_in_named_scopes(src: List[str], scope_spans: List[Tuple[int, int, str]]) -> List[Tuple[str, List[Iinstruction]]]: + instructions = list(map(named_scope_handler, [(src, span) for span in scope_spans])) + return instructions def load_instructions(filepath: str) -> List[List[Iinstruction]]: src = load_src(filepath) scope_spans = get_function_scope_spans(src) instructions = get_instructions_in_scopes(src, scope_spans) return instructions + +def load_scoped_instructions(filepath: str) -> List[Tuple[str, List[Iinstruction]]]: + src = load_src(filepath) + scope_spans = get_function_scope_spans(src) + instructions = get_instructions_in_named_scopes(src, scope_spans) + return instructions diff --git a/res/input/input.java b/res/input/input.java index ece980c..70f7ae2 100644 --- a/res/input/input.java +++ b/res/input/input.java @@ -1,85 +1,326 @@ -public void act() -{ - S66Nr3(7); -} +//import greenfoot.*; // (World, Actor, GreenfootImage, Greenfoot and MouseInfo) -private void fahreUmHuegel(String richtung) -{ - String pri; - String sec; - if(richtung.equals("Hoch")) { - pri = "links"; - sec = "rechts"; - } else { - if (richtung.equals("Runter")){ - pri = "rechts"; - sec = "links"; - } else { - nachricht("JUNGE DU SPAST!"); - return; - } - } - drehe(pri); - fahre(); - drehe(sec); - fahre(); - fahre(); - drehe(sec); - fahre(); - drehe(pri); -} +// public class Rover extends Actor +// { +// private Display anzeige; -private void fahreBisHuegel() -{ - while(!huegelVorhanden("vorne")) +// /** +// * this function is to be implemented by the user +// * depending on the needed actions +// */ + public void act() { + S66Nr3(7); + } + + private void fahreUmHuegel(String richtung) + { + String pri; + String sec; + if(richtung.equals("Hoch")) { + pri = "links"; + sec = "rechts"; + } else { + if (richtung.equals("Runter")) { + pri = "rechts"; + sec = "links"; + } else { + nachricht("JUNGE DU SPAST!"); + return; + } + } + drehe(pri); fahre(); - } -} - -private void fahreZeileDreheHoch() -{ - fahreBisHuegel(); - fahreUmHuegel("Hoch"); - fahreBisHuegel(); - drehe("um"); - - fahreBisHuegel(); - fahreUmHuegel("Runter"); - fahreBisHuegel(); - drehe("rechts"); - fahre(); - drehe("rechts"); -} - -private void fahreZeileDreheRunter(boolean geheInNächsteZeile) -{ - fahreBisHuegel(); - fahreUmHuegel("Runter"); - fahreBisHuegel(); - drehe("um"); - - fahreBisHuegel(); - fahreUmHuegel("Hoch"); - fahreBisHuegel(); - if(geheInNächsteZeile) { - drehe("rechts"); + drehe(sec); fahre(); - drehe("rechts"); - } else { - drehe("um"); + fahre(); + drehe(sec); + fahre(); + drehe(pri); } -} -private void S66Nr3(int anzahlZeilen) -{ - if(anzahlZeilen < 3) { - nachricht("Ich muss mindestens drei Zeilen fahren! :("); - return; - } - fahreZeileDreheHoch(); - for(int i = 1; i < anzahlZeilen-1; i++) { - fahreZeileDreheRunter(true); - } - fahreZeileDreheRunter(false); -} \ No newline at end of file +// private void fahreBisHuegel() +// { +// while(!huegelVorhanden("vorne")) +// { +// fahre(); +// } +// } + +// private void fahreZeileDreheHoch() +// { +// fahreBisHuegel(); +// fahreUmHuegel("Hoch"); +// fahreBisHuegel(); +// drehe("um"); + +// fahreBisHuegel(); +// fahreUmHuegel("Runter"); +// fahreBisHuegel(); +// drehe("rechts"); +// fahre(); +// drehe("rechts"); +// } + +// private void fahreZeileDreheRunter(boolean geheInNächsteZeile) +// { +// fahreBisHuegel(); +// fahreUmHuegel("Runter"); +// fahreBisHuegel(); +// drehe("um"); + +// fahreBisHuegel(); +// fahreUmHuegel("Hoch"); +// fahreBisHuegel(); +// if(geheInNächsteZeile) { +// drehe("rechts"); +// fahre(); +// drehe("rechts"); +// } else { +// drehe("um"); +// } +// } + +// private void S66Nr3(int anzahlZeilen) +// { +// if(anzahlZeilen < 3) { +// nachricht("Ich muss mindestens drei Zeilen fahren! :("); +// return; +// } +// fahreZeileDreheHoch(); +// //for(int i = 1; i < anzahlZeilen-1; i++) { +// fahreZeileDreheRunter(true); +// //} +// fahreZeileDreheRunter(false); +// } + +// // /** +// // * Der Rover bewegt sich ein Feld in Fahrtrichtung weiter. +// // * Sollte sich in Fahrtrichtung ein Objekt der Klasse Huegel befinden oder er sich an der Grenze der Welt befinden, +// // * dann erscheint eine entsprechende Meldung auf dem Display. +// // */ +// // public void fahre() +// // { +// // int posX = getX(); +// // int posY = getY(); + +// // if(huegelVorhanden("vorne")) +// // { +// // nachricht("Zu steil!"); +// // } +// // else if(getRotation()==270 && getY()==1) +// // { +// // nachricht("Ich kann mich nicht bewegen"); +// // } +// // else +// // { +// // move(1); +// // Greenfoot.delay(1); +// // } + +// // if(posX==getX()&&posY==getY()&&!huegelVorhanden("vorne")) +// // { +// // nachricht("Ich kann mich nicht bewegen"); +// // } +// // } + +// // /** +// // * Der Rover dreht sich um 90 Grad in die Richtung, die mit richtung (ᅵlinksᅵ oder ᅵrechtsᅵ) ᅵbergeben wurde. +// // * Sollte ein anderer Text (String) als "rechts" oder "links" ᅵbergeben werden, dann erscheint eine entsprechende Meldung auf dem Display. +// // */ +// // public void drehe(String richtung) +// // { +// // if(richtung.equals("rechts")){ +// // setRotation(getRotation()+90); +// // }else if(richtung.equals("links")){ +// // setRotation(getRotation()-90); +// // } else if(richtung.equals("um")) { +// // setRotation(getRotation()+180); +// // }else { +// // nachricht("Keinen Korrekte Richtung gegeben!"); +// // } +// // } + +// // /** +// // * Der Rover gibt durch einen Wahrheitswert (true oder false )zurᅵck, ob sich auf seiner Position ein Objekt der Klasse Gestein befindet. +// // * Eine entsprechende Meldung erscheint auch auf dem Display. +// // */ +// // public boolean gesteinVorhanden() +// // { +// // if(getOneIntersectingObject(Gestein.class)!=null) +// // { +// // nachricht("Gestein gefunden!"); +// // return true; + +// // } + +// // return false; +// // } + +// // /** +// // * Der Rover ᅵberprᅵft, ob sich in richtung ("rechts", "links", oder "vorne") ein Objekt der Klasse Huegel befindet. +// // * Das Ergebnis wird auf dem Display angezeigt. +// // * Sollte ein anderer Text (String) als "rechts", "links" oder "vorne" ᅵbergeben werden, dann erscheint eine entsprechende Meldung auf dem Display. +// // */ +// // public boolean huegelVorhanden(String richtung) +// // { +// // int rot = getRotation(); + +// // if (richtung=="vorne" && rot==0 || richtung=="rechts" && rot==270 || richtung=="links" && rot==90) +// // { +// // if(getOneObjectAtOffset(1,0,Huegel.class)!=null && ((Huegel)getOneObjectAtOffset(1,0,Huegel.class)).getSteigung() >30) +// // { +// // return true; +// // } +// // } + +// // if (richtung=="vorne" && rot==180 || richtung=="rechts" && rot==90 || richtung=="links" && rot==270) +// // { +// // if(getOneObjectAtOffset(-1,0,Huegel.class)!=null && ((Huegel)getOneObjectAtOffset(-1,0,Huegel.class)).getSteigung() >30) +// // { +// // return true; +// // } +// // } + +// // if (richtung=="vorne" && rot==90 || richtung=="rechts" && rot==0 || richtung=="links" && rot==180) +// // { +// // if(getOneObjectAtOffset(0,1,Huegel.class)!=null && ((Huegel)getOneObjectAtOffset(0,1,Huegel.class)).getSteigung() >30) +// // { +// // return true; +// // } + +// // } + +// // if (richtung=="vorne" && rot==270 || richtung=="rechts" && rot==180 || richtung=="links" && rot==0) +// // { +// // if(getOneObjectAtOffset(0,-1,Huegel.class)!=null && ((Huegel)getOneObjectAtOffset(0,-1,Huegel.class)).getSteigung() >30) +// // { +// // return true; +// // } + +// // } + +// // if(richtung!="vorne" && richtung!="links" && richtung!="rechts") +// // { +// // nachricht("Befehl nicht korrekt!"); +// // } + +// // return false; +// // } + +// // /** +// // * Der Rover ermittelt den Wassergehalt des Gesteins auf seiner Position und gibt diesen auf dem Display aus. +// // * Sollte kein Objekt der Klasse Gestein vorhanden sein, dann erscheint eine entsprechende Meldung auf dem Display. +// // */ +// // public void analysiereGestein() +// // { +// // if(gesteinVorhanden()) +// // { +// // nachricht("Gestein untersucht! Wassergehalt ist " + ((Gestein)getOneIntersectingObject(Gestein.class)).getWassergehalt()+"%."); +// // Greenfoot.delay(1); +// // removeTouching(Gestein.class); +// // } +// // else +// // { +// // nachricht("Hier ist kein Gestein"); +// // } +// // } + +// // /** +// // * Der Rover erzeugt ein Objekt der Klasse ᅵMarkierungᅵ auf seiner Position. +// // */ +// // public void setzeMarke() +// // { +// // getWorld().addObject(new Marke(), getX(), getY()); +// // } + +// // /** +// // * *Der Rover gibt durch einen Wahrheitswert (true oder false )zurᅵck, ob sich auf seiner Position ein Objekt der Marke befindet. +// // * Eine entsprechende Meldung erscheint auch auf dem Display. +// // */ +// // public boolean markeVorhanden() +// // { +// // if(getOneIntersectingObject(Marke.class)!=null) +// // { +// // return true; +// // } + +// // return false; +// // } + +// // public void entferneMarke() +// // { +// // if(markeVorhanden()) +// // { +// // removeTouching(Marke.class); +// // } +// // } + +// // private void nachricht(String pText) +// // { +// // if(anzeige!=null) +// // { +// // anzeige.anzeigen(pText); +// // Greenfoot.delay(1); +// // anzeige.loeschen(); +// // } +// // } + +// // private void displayAusschalten() +// // { +// // getWorld().removeObject(anzeige); + +// // } + +// // protected void addedToWorld(World world) +// // { + +// // setImage("images/rover.png"); +// // world = getWorld(); +// // anzeige = new Display(); +// // anzeige.setImage("images/nachricht.png"); +// // world.addObject(anzeige, 7, 0); +// // if(getY()==0) +// // { +// // setLocation(getX(),1); +// // } +// // anzeige.anzeigen("Ich bin bereit"); + +// // } + +// // class Display extends Actor +// // { +// // GreenfootImage bild; + +// // public Display() +// // { +// // bild = getImage(); +// // } + +// // public void act() +// // { + +// // } + +// // public void anzeigen(String pText) +// // { +// // loeschen(); +// // getImage().drawImage(new GreenfootImage(pText, 25, Color.BLACK, new Color(0, 0, 0, 0)),10,10); + +// // } + +// // public void loeschen() +// // { +// // getImage().clear(); +// // setImage("images/nachricht.png"); +// // } + +// // } + +// // public class Direction { +// // Direction(int val){ +// // this.value = val; +// // } +// // final int value; +// // }; +// // }