From e9ce5d8d938cf91b038defa5f66a77759bece63f Mon Sep 17 00:00:00 2001 From: weckyy702 Date: Mon, 28 Dec 2020 00:36:38 +0100 Subject: [PATCH] Added function scope support to interpreter --- .gitignore | 5 +- .vscode/launch.json | 2 +- interpreter/interpret_source.py | 67 ++++++++++---- res/input/input.java | 158 ++++++++++++++++---------------- 4 files changed, 133 insertions(+), 99 deletions(-) diff --git a/.gitignore b/.gitignore index 8fe1725..4499268 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ __pycache__/ res/output/ -res/input/* -.vscode/* +res/input/ +.vscode/ *.json *.pyc *.png @@ -9,4 +9,3 @@ debug.py build/ run.spec dist/ -.vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json index 1ded7e8..e80f071 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "name": "Python: Aktuelle Datei", "type": "python", "request": "launch", - "program": "run.py", + "program": "debug.py", "console": "integratedTerminal" } ] diff --git a/interpreter/interpret_source.py b/interpreter/interpret_source.py index c639a0c..421da77 100644 --- a/interpreter/interpret_source.py +++ b/interpreter/interpret_source.py @@ -1,21 +1,28 @@ import logging from os import remove import re -from typing import Callable, List, Tuple +from typing import List, Tuple +from multiprocessing import cpu_count +from multiprocessing.pool import Pool from errors.custom import InterpreterException, JavaSyntaxError, ScopeNotFoundException from draw.Iinstruction import * -COMMENT_REGEX = r"""^//|^#|^COMMENT|^--""" -REMOVE_KEYWORDS = [' ', "public", "private", "void", ';'] -FUNCTION_IDENTIFIERS = ["void", "boolean", "int"] #possible return types of functions +COMMENT_PATTERN = re.compile(r"""^//|^/\*\*|^\*|^--""") +REMOVE_KEYWORDS = [' ', "public", "private", ';'] +FUNCTION_IDENTIFIERS = ["void", "boolean", "int", "float"] WHILE_TAG = "solange " #german for 'while'. Change this depending on your language REPLACE = dict((re.escape(k), '') for k in REMOVE_KEYWORDS) remove_pattern = re.compile("|".join(REPLACE.keys())) -function_pattern = re.compile(r"""(?=.*).*\(\)""".join(FUNCTION_IDENTIFIERS)) +function_regex = "^(" +for kw in FUNCTION_IDENTIFIERS: + function_regex += fr"""{kw}|""" +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 @@ -31,7 +38,7 @@ def load_src(filepath: str) -> List[str]: with open(filepath, encoding="utf-8") as file: for _line in file: line = replace_all_tags(_line.strip()) - if line and not re.match(COMMENT_REGEX, line): + if line and not COMMENT_PATTERN.match(line): lines.append(line) if line.__contains__('{'): brace_open_count += 1 @@ -71,6 +78,17 @@ def get_scope_start_offset(src: List[str], i: int) -> int: return 2 raise ScopeNotFoundException("Unable to find scope start. Is the program ill-formed?") +def get_scope_exit_offset(src: List[str], start_idx: int) -> int: + i = start_idx + 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 + def handle_while(line: str, src: List[str], i: int) -> Tuple[Iinstruction, int]: bracket_idx = line.rindex(')') # throws if while contruct is illformed @@ -162,25 +180,40 @@ def get_instructions_in_scope(src: List[str], start_idx: int = 0) -> Tuple[List[ return outer_scope, i -def get_function_scopes(src: List[str]) -> List[Tuple[int, int]]: +def get_function_scope_spans(src: List[str]) -> List[Tuple[int, int]]: + spans = [] i = 0 - print(function_pattern) while i < len(src): line = src[i] try: - if function_pattern.match(line): - print(line) + if match:= function_pattern.match(line): + groups = match.groups() + function_name = line.removeprefix(groups[0]).removesuffix(groups[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) + i += scope_offset + brace_offset + spans.append(span) - except: + except Exception as e: + logging.error("encountered error in line %i : %s", i, str(e)) raise i += 1 - return [(0, 0)] + return spans -def load_instructions(filepath: str) -> List[Iinstruction]: +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 get_instructions_in_scopes(src: List[str], scope_spans: List[Tuple[int, int]]): + p = Pool(processes=cpu_count()) + instructions = list(map(scope_handler, [(src, scope_span) for scope_span in scope_spans]))#p.map(scope_handler, [(src, scope_span) for scope_span in scope_spans]) + return instructions + + +def load_instructions(filepath: str) -> List[List[Iinstruction]]: src = load_src(filepath) - instructions, i = get_instructions_in_scope(src) - if i != len(src): - raise InterpreterException("Unknown error during source interpretation! Unsupported language constructs or ill-formed source?") - return instructions \ No newline at end of file + scope_spans = get_function_scope_spans(src) + instructions = get_instructions_in_scopes(src, scope_spans) + return instructions diff --git a/res/input/input.java b/res/input/input.java index 99475d1..ece980c 100644 --- a/res/input/input.java +++ b/res/input/input.java @@ -1,83 +1,85 @@ -beforeIf(); -if(if_condition1) { - true_case; - true_case; -} -afterIf(); -beforeIf(); -if(if_condition2) +public void act() { - true_case; - true_case; -} -afterIf(); -beforeIf(); -if(if_else_condition1) { - true_case; - true_case; -} else { - false_case; - false_case; -} -afterIf(); -beforeIf(); -if(if_else_condition2) { - true_case; - true_case; -} -else { - false_case; - false_case; -} -afterIf(); -beforeIf(); -if(if_else_condition3) { - true_case; - true_case; -} -else -{ - false_case; - false_case; -} -afterIf(); -beforeWhile(); -while(while_condition1) { - insideWhile; - insideWhile; -} -beforeWhile(); -while(while_condition2) -{ - insideWhile; - insideWhile; -} -beforeDoWhile(); -do{ - insideDoWhile; - insideDoWhile; -}while(do_while_condition1); -beforeDoWhile(); -do -{ - insideDoWhile; - insideDoWhile; -}while(do_while_condition2); -beforeDoWhile(); -do -{ - insideDoWhile; - insideDoWhile; -} -while(do_while_condition3) - -//since the interpreter ignores all empty lines and spaces, any changes in tabs *should* not have any effect - -void function1() { - + S66Nr3(7); } -boolean function2() +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); +} + +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); } \ No newline at end of file