Implemented interface between NSD and interpreter

This commit is contained in:
weckyy702
2021-01-03 17:12:21 +01:00
parent 522e0d2b38
commit 536cf7958a
5 changed files with 71 additions and 123 deletions

View File

@@ -226,7 +226,7 @@ class Gui:
output_name = secrets.token_hex(16) output_name = secrets.token_hex(16)
nassi(input_path=file_path, output_path=output_path, outputname=output_name, gui=self, nassi(input_path=file_path, output_path=output_path, outputname=output_name, gui=self,
font_filepath=font_filepath, behaviour=exists_choice, types=types, remove_tages=modifier, comments=comments) font_filepath=font_filepath, behaviour=exists_choice, types=types, remove_tags=modifier, comments=comments)
fnames = output(values['-OUTPUT FOLDER-']) fnames = output(values['-OUTPUT FOLDER-'])
sg.popup_annoying('Successfully created!', title='Created', sg.popup_annoying('Successfully created!', title='Created',

View File

@@ -21,7 +21,9 @@ def nassi(input_path: str, output_path: str, outputname: str, types, remove_tags
except: except:
raise raise
NSD.load_from_file(input_path, types, remove_tags, comments) custom_tags = {"comments" : comments, "ignore" : remove_tags, "types" : types}
NSD.load_from_file(input_path, custom_tags)
NSD.convert_to_image(output_directory, on_conflict=behaviour, x_size=750) NSD.convert_to_image(output_directory, on_conflict=behaviour, x_size=750)
return output_directory return output_directory

View File

@@ -1,5 +1,5 @@
from interpreter.interpret_source import Function_scope from interpreter.interpret_source import Function_scope
from typing import List from typing import Dict, List
import logging import logging
from enum import IntEnum from enum import IntEnum
import os.path import os.path
@@ -69,6 +69,7 @@ class NassiShneidermanDiagram:
logging.error(f"Failed to save image {filepath}. Unknown error") logging.error(f"Failed to save image {filepath}. Unknown error")
raise raise
def load_from_file(self, filepath:str): def load_from_file(self, filepath:str, itp_custom_tags: Dict[str, List[str]]):
itp = JavaInterpreter(filepath) itp = JavaInterpreter(filepath)
itp.reset_tags(itp_custom_tags)
self.function_scopes = itp.load_instruction_scopes() self.function_scopes = itp.load_instruction_scopes()

View File

@@ -8,6 +8,7 @@ from draw.Iinstruction import *
logging.warning("""Because the Interpreter is still WIP, some Java language features are not supported. These include: logging.warning("""Because the Interpreter is still WIP, some Java language features are not supported. These include:
*else if statements *else if statements
*for loops *for loops
*Constructors (will be ignored)
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): class Function_scope(Iterable):
@@ -32,8 +33,8 @@ class JavaInterpreter:
with open(filepath) as file: with open(filepath) as file:
if not file.readable(): if not file.readable():
raise InterpreterException(f"Unable to read input file {filepath}") raise InterpreterException(f"Unable to read input file {filepath}")
self.src = file.read() self._src = file.read()
self.lines = [] # to be filled in later self._lines = [] # to be filled in later
self._init_regex() self._init_regex()
self._recompile_regex() self._recompile_regex()
@@ -46,56 +47,63 @@ class JavaInterpreter:
if additional_tags: if additional_tags:
if "comments" in additional_tags.keys(): if "comments" in additional_tags.keys():
self.comment_tags.extend(additional_tags["comments"]) if tags := additional_tags["comments"]:
self._comment_tags.extend(tags)
if "ignore" in additional_tags.keys(): if "ignore" in additional_tags.keys():
self.remove_tags.extend(additional_tags["ignore"]) if tags := additional_tags["ignore"]:
self._remove_tags.extend(tags)
if "types" in additional_tags.keys(): if "types" in additional_tags.keys():
self.type_tags.extend(additional_tags["types"]) if tags := additional_tags["types"]:
self.function_tags.extend(additional_tags["types"]) self._type_tags.extend(tags)
self._function_tags.extend(tags)
else: else:
self._init_regex() self._init_regex()
self._recompile_regex() self._recompile_regex()
def load_instruction_scopes(self):
self._remove_keywords()
return self._get_function_scopes()
def _init_regex(self): def _init_regex(self):
"""Initialize all tag lists to their default state""" """Initialize all tag lists to their default state"""
self.comment_tags = ["//", "#", "--"] #dont ask why a java interpreter supports lua and python style comments self._comment_tags = ["//", "#", "--"] #dont ask why a java interpreter supports lua and python style comments
self.remove_tags = ['\n', "public", "private", "protected", "final"] self._remove_tags = ['\n', "public", "private", "protected", "final"]
self.type_tags = ["byte", "short", "int", "long", "float", "double", "boolean", "char", "String"] self._type_tags = ["byte", "short", "int", "long", "float", "double", "boolean", "char", "String"]
self.function_tags = ["void"] self._function_tags = ["void"]
self.function_tags.extend(self.type_tags) self._function_tags.extend(self._type_tags)
def _recompile_regex(self): def _recompile_regex(self):
"""recompile all regex's using the new tag lists""" """recompile all regex's using the new tag lists"""
comment_regex = r"""^(""" comment_regex = r"""^("""
for tag in self.comment_tags: for tag in self._comment_tags:
comment_regex += fr"""{re.escape(tag)}|""" comment_regex += fr"""{re.escape(tag)}|"""
self.comment_pattern = re.compile(comment_regex[:-1]+").*", flags=re.MULTILINE) self._comment_pattern = re.compile(comment_regex[:-1]+").*", flags=re.MULTILINE)
remove_regex = r"""^(""" remove_regex = r"""^("""
for tag in self.remove_tags: for tag in self._remove_tags:
remove_regex += fr"""{re.escape(tag)}|""" remove_regex+= fr"""{re.escape(tag)}|"""
self.remove_pattern = re.compile(remove_regex[:-1]+')', flags=re.MULTILINE) self._remove_pattern = re.compile(remove_regex[:-1]+')', flags=re.MULTILINE)
variable_regex = r"""^(""" variable_regex = r"""^("""
for tag in self.type_tags: for tag in self._type_tags:
variable_regex += fr"""{re.escape(tag)}|""" variable_regex += fr"""{re.escape(tag)}|"""
self.variable_pattern = re.compile(variable_regex[:-1]+")(.*=|.*;)(.*)", flags=re.MULTILINE) self._variable_pattern = re.compile(variable_regex[:-1]+")(.*=|.*;)(.*)", flags=re.MULTILINE)
function_regex = r"""^(?P<return_type>""" function_regex = r"""^(?P<return_type>"""
for tag in self.function_tags: for tag in self._function_tags:
function_regex += fr"""{re.escape(tag)}|""" function_regex += fr"""{re.escape(tag)}|"""
self.function_pattern = re.compile(function_regex[:-1]+")(?P<name>.*)[(](?P<args>.*)[)][^;]", flags=re.MULTILINE) self._function_pattern = re.compile(function_regex[:-1]+")(?P<name>.*)[(](?P<args>.*)[)][^;]", flags=re.MULTILINE)
def _check_src(self, idx: int, tag: str) -> bool: def _check_src(self, idx: int, tag: str) -> bool:
if idx >= len(self.lines): if idx >= len(self._lines):
return False return False
return tag in self.lines[idx] return tag in self._lines[idx]
def _check_line_start(self, idx: int, tag: str) -> bool: def _check_line_start(self, idx: int, tag: str) -> bool:
if idx >= len(self.lines): if idx >= len(self._lines):
return False return False
return self.lines[idx].startswith(tag) return self._lines[idx].startswith(tag)
def _get_scope_start_offset(self, i: int) -> int: def _get_scope_start_offset(self, i: int) -> int:
if self._check_src(i, "{"): if self._check_src(i, "{"):
@@ -145,12 +153,12 @@ class JavaInterpreter:
instruction_txt = None instruction_txt = None
if self._check_line_start(idx, "}while("): if self._check_line_start(idx, "}while("):
end_line = self.lines[idx] end_line = self._lines[idx]
bracket_index = end_line.rindex(')') #throws if contruct id ill-formed bracket_index = end_line.rindex(')') #throws if contruct id ill-formed
instruction_txt = end_line[7:bracket_index] instruction_txt = end_line[7:bracket_index]
elif self._check_line_start(idx+1, "while("): elif self._check_line_start(idx+1, "while("):
idx += 1 idx += 1
end_line = self.lines[idx] end_line = self._lines[idx]
bracket_index = end_line.rindex(')') bracket_index = end_line.rindex(')')
instruction_txt = end_line[6:bracket_index] instruction_txt = end_line[6:bracket_index]
else: else:
@@ -159,7 +167,7 @@ class JavaInterpreter:
return while_instruction_back(instruction_txt, child_instructions), idx return while_instruction_back(instruction_txt, child_instructions), idx
def _handle_variable(self, line: str, idx: int): def _handle_variable(self, line: str, idx: int):
groups = self.variable_pattern.match(line).groups() groups = self._variable_pattern.match(line).groups()
var_type = groups[0] var_type = groups[0]
var_name = groups[1][:-1] var_name = groups[1][:-1]
var_value = groups[2] var_value = groups[2]
@@ -180,7 +188,7 @@ class JavaInterpreter:
logging.debug("Found do-while construct in line: %i", idx+1) logging.debug("Found do-while construct in line: %i", idx+1)
return self._handle_do_while(line, idx) return self._handle_do_while(line, idx)
elif self.variable_pattern.match(line): elif self._variable_pattern.match(line):
logging.debug("Found variable in line %i", idx+1) logging.debug("Found variable in line %i", idx+1)
return self._handle_variable(line, idx) return self._handle_variable(line, idx)
@@ -191,8 +199,8 @@ class JavaInterpreter:
def _get_instructions_in_scope(self, idx: int=0) -> Tuple[List[Iinstruction], int]: def _get_instructions_in_scope(self, idx: int=0) -> Tuple[List[Iinstruction], int]:
scope: List[Iinstruction] = [] scope: List[Iinstruction] = []
i = idx i = idx
while i < len(self.lines): while i < len(self._lines):
line = self.lines[i] line = self._lines[i]
if self._check_src(i, '}'): if self._check_src(i, '}'):
break break
@@ -204,103 +212,34 @@ class JavaInterpreter:
return scope, i return scope, i
def _remove_keywords(self): def _remove_keywords(self):
self.src = self.src.replace(' ', '') self.src = self._src.replace(' ', '')
self.src = self.comment_pattern.sub('', self.src) self.src = self._comment_pattern.sub('', self.src)
self.src = self.remove_pattern.sub('', self.src) self.src = self._remove_pattern.sub('', self.src)
self.lines = self.src.splitlines() self._lines = self.src.splitlines()
def _get_function_info(self, match: Match[str]) -> Tuple[str, str, List[str]]: def _get_function_info(self, match: Match[str]) -> Tuple[str, str, List[str]]:
groups = match.groupdict() groups = match.groupdict()
ftype = groups["return_type"] ftype = groups["return_type"]
fargs = groups["args"] fargs = groups["args"].split(',')
fname = groups["name"] fname = groups["name"]
return ftype, fname, fargs.split(',') return ftype, fname, fargs
def _get_function_instructions(self, function_header: str) -> List[Iinstruction]: def _get_function_instructions(self, function_header: str) -> List[Iinstruction]:
idx = self.lines.index(function_header) idx = self._lines.index(function_header)
brace_offset = self._get_scope_start_offset(idx) brace_offset = self._get_scope_start_offset(idx)
return self._get_instructions_in_scope(idx+brace_offset)[0] return self._get_instructions_in_scope(idx+brace_offset)[0]
def _get_function_scope(self, match: re.Match[str]):
span = match.span()
header = self.src[span[0]:span[1]].replace('\n', '')
rtype, name, args = self._get_function_info(match)
child_instructions = self._get_function_instructions(header)
return Function_scope(child_instructions, name, rtype, args)
def _get_function_scopes(self) -> List[Function_scope]: def _get_function_scopes(self) -> List[Function_scope]:
scopes = [] matches = self._function_pattern.finditer(self.src)
for match in self.function_pattern.finditer(self.src): return list(map(self._get_function_scope, matches))
span = match.span()
header = self.src[span[0]:span[1]].replace('\n', '')
rtype, name, args = self._get_function_info(match)
child_instructions = self._get_function_instructions(header)
scopes.append(Function_scope(child_instructions, name, rtype, args))
return scopes
def load_instruction_scopes(self):
self._remove_keywords()
return self._get_function_scopes()
# COMMENT_PATTERN = re.compile(r"""^(//|#|--)""")
# REMOVE_KEYWORDS = [' ', "public", "private", "final", "protected"]
# VARIABLE_TAGS = ["byte", "short", "int", "long", "float", "double", "boolean", "char", "String"]
# FUNCTION_IDENTIFIERS = ["void"]
# FUNCTION_IDENTIFIERS.extend(VARIABLE_TAGS)
# 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()), flags=re.MULTILINE)
# variable_regex = "^("
# for kw in VARIABLE_TAGS:
# variable_regex += fr"""{kw}|"""
# variable_pattern = re.compile(variable_regex[0:-1]+")(.*=|.*;)(.*)", flags=re.MULTILINE)
# function_regex = "^(?P<return_type>"
# for kw in FUNCTION_IDENTIFIERS:
# function_regex += fr"""{kw}|"""
# function_regex = function_regex[0:-1]+ ")(?P<name>.*)[(](?P<args>.*)[)][^;]"
# function_pattern = re.compile(function_regex, flags=re.MULTILINE)
# def check_src(src: List[str], line_index: int, tag: str) -> bool:
# if line_index >= len(src):
# return False
# return tag in src[line_index]
# def check_line_start(src: List[str], line_index: int, tag: str) -> bool:
# if line_index >= len(src):
# return False
# return src[line_index].startswith(tag)
# def get_next_occurence_of(src: List[str], start_idx:int, tag:str) -> int:
# """Returns the index of the next occurence of tag in src from start_idx"""
# i = start_idx
# while i < len(src):
# if check_src(src, i, tag):
# break
# i += 1
# return i
# def get_scope_start_offset(src: List[str], i: int) -> int:
# if check_src(src, i, "{"):
# return 1
# elif check_src(src, i+1, "{"):
# return 2
# raise ScopeNotFoundException("Unable to find scope start. Is the program ill-formed?")
# def get_function_scopes(src: str) -> List[Function_scope]:
# scopes = []
# lines = src.splitlines(True)
# for match in function_pattern.finditer(src):
# span = match.span()
# matched_str = src[span[0]:span[1]]
# rtype, name, args = get_function_info(match, matched_str)
# child_instructions = get_function_instructions(lines, matched_str)
# scopes.append(Function_scope(child_instructions, name, rtype, args))
# return scopes

View File

@@ -10,6 +10,12 @@ public class Rover extends Actor
* this function is to be implemented by the user * this function is to be implemented by the user
* depending on the needed actions * depending on the needed actions
*/ */
public Display getDisplay()
{
return anzeige;
}
public void act() public void act()
{ {
S66Nr3(7); S66Nr3(7);