This commit is contained in:
oleting
2020-12-28 23:42:34 +01:00
3 changed files with 32 additions and 74 deletions

2
.vscode/launch.json vendored
View File

@@ -8,7 +8,7 @@
"name": "Python: Aktuelle Datei", "name": "Python: Aktuelle Datei",
"type": "python", "type": "python",
"request": "launch", "request": "launch",
"program": "run.py", "program": "debug.py",
"console": "integratedTerminal" "console": "integratedTerminal"
} }
] ]

View File

@@ -1,3 +1,4 @@
from interpreter.interpret_source import Function_scope
from typing import List from typing import List
import logging import logging
from enum import IntEnum from enum import IntEnum
@@ -19,7 +20,7 @@ OB = Overwrite_behaviour
class NassiShneidermanDiagram: class NassiShneidermanDiagram:
def __init__(self, do_debug: bool): def __init__(self, do_debug: bool):
self.scopes: List[List[Iinstruction]] = [] self.function_scopes: List[Function_scope] = []
self.init_logging(do_debug) self.init_logging(do_debug)
def init_logging(self, debug: bool): def init_logging(self, debug: bool):
@@ -34,7 +35,7 @@ class NassiShneidermanDiagram:
def _get_image_height(self, scope_index: int) -> int: def _get_image_height(self, scope_index: int) -> int:
h = 0 h = 0
for inst in self.scopes[scope_index]: for inst in self.function_scopes[scope_index]:
h += inst.getblksize() h += inst.getblksize()
return int(h) return int(h)
@@ -60,7 +61,7 @@ class NassiShneidermanDiagram:
return filepath return filepath
def convert_to_image(self, output_path: str, filename: str, on_conflict: Overwrite_behaviour=OB.SKIP, x_size: int=200): def convert_to_image(self, output_path: str, filename: str, on_conflict: Overwrite_behaviour=OB.SKIP, x_size: int=200):
for i in range(len(self.scopes)): for i in range(len(self.function_scopes)):
filepath = f"{output_path}/{filename}#{i}" filepath = f"{output_path}/{filename}#{i}"
filepath = self.check_conflicts(filepath, on_conflict) filepath = self.check_conflicts(filepath, on_conflict)
if filepath is not None: if filepath is not None:
@@ -69,11 +70,11 @@ class NassiShneidermanDiagram:
image_y_sz = self._get_image_height(i) image_y_sz = self._get_image_height(i)
with NSD_writer(filepath, x_size, image_y_sz): with NSD_writer(filepath, x_size, image_y_sz):
scope = self.scopes[i] scope = self.function_scopes[i].contents
x, y = 0, 0 x, y = 0, 0
for instruction in scope: for instruction in scope:
x, y = instruction.to_image(x, y, x_size) x, y = instruction.to_image(x, y, x_size)
logging.info("Done!") logging.info("Done!")
def load_from_file(self, filepath:str): def load_from_file(self, filepath:str):
self.scopes = itp.load_instructions(filepath) self.function_scopes = itp.load_scoped_instructions(filepath)

View File

@@ -1,6 +1,7 @@
import logging import logging
from os import remove from os import remove
import re import re
from re import split
from typing import List, Tuple from typing import List, Tuple
from errors.custom import InterpreterException, JavaSyntaxError, ScopeNotFoundException from errors.custom import InterpreterException, JavaSyntaxError, ScopeNotFoundException
@@ -11,6 +12,16 @@ logging.warning("""As the Interpreter is still WIP, some Java language features
*for loops *for loops
Please remove these features from the source code as they will result in incorrect behaviour""") Please remove these features from the source code as they will result in incorrect behaviour""")
class Function_scope(Iterable):
def __init__(self, child_instructions: List[Iinstruction], name: str, return_type: str, args: List[str]) -> None:
self.contents = child_instructions
self.name = name
self.return_type = return_type
self.args = args
def __iter__(self):
return self.contents.__iter__()
COMMENT_PATTERN = re.compile(r"""^//|^/\*\*|^\*|^--""") COMMENT_PATTERN = re.compile(r"""^//|^/\*\*|^\*|^--""")
REMOVE_KEYWORDS = [' ', "public", "private", ';'] REMOVE_KEYWORDS = [' ', "public", "private", ';']
VARIABLE_TAGS = ["byte", "short", "int", "long", "float", "double", "boolean", "char", "String"] VARIABLE_TAGS = ["byte", "short", "int", "long", "float", "double", "boolean", "char", "String"]
@@ -84,20 +95,6 @@ def get_scope_start_offset(src: List[str], i: int) -> int:
return 2 return 2
raise ScopeNotFoundException("Unable to find scope start. Is the program ill-formed?") 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)
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]: def handle_while(line: str, src: List[str], i: int) -> Tuple[Iinstruction, int]:
bracket_idx = line.rindex(')') # throws if while contruct is illformed bracket_idx = line.rindex(')') # throws if while contruct is illformed
@@ -189,63 +186,23 @@ def get_instructions_in_scope(src: List[str], start_idx: int = 0) -> Tuple[List[
return outer_scope, i return outer_scope, i
def get_function_scope_spans(src: List[str]) -> List[Tuple[int, int, str]]: def get_function_scopes(src: List[str]) -> List[Function_scope]:
spans = [] functions = []
i = 0 i = 0
while i < len(src): while i < len(src):
line = src[i] line = src[i]
try: if match:=function_pattern.match(line):
groups = match.groups()
function_return_type = groups[0]
function_args = groups[1]
function_name = line.removeprefix(function_return_type).removesuffix(function_args) #remove return type and argument list to get the function name
if match:= function_pattern.match(line): brace_offset = get_scope_start_offset(src, i)
groups = match.groups() child_instructions, i = get_instructions_in_scope(src, i+brace_offset)
function_name = line.removeprefix(groups[0]).removesuffix(groups[1]) functions.append(Function_scope(child_instructions, function_name, function_return_type, function_args.split(',')))
function_return_type = groups[0] i+=1
function_args = groups[1][1:-1] return functions
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, function_name) def load_scoped_instructions(filepath: str) -> List[Function_scope]:
i += scope_offset + brace_offset
spans.append(span)
except Exception as e:
logging.error("encountered error in line %i : %s", i, str(e))
raise
i += 1
return spans
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 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) src = load_src(filepath)
scope_spans = get_function_scope_spans(src) return get_function_scopes(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