Added function scope support to interpreter

This commit is contained in:
weckyy702
2020-12-28 00:36:38 +01:00
parent 00a897a897
commit e9ce5d8d93
4 changed files with 133 additions and 99 deletions

5
.gitignore vendored
View File

@@ -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

2
.vscode/launch.json vendored
View File

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

View File

@@ -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]:
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?")
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)
scope_spans = get_function_scope_spans(src)
instructions = get_instructions_in_scopes(src, scope_spans)
return instructions

View File

@@ -1,83 +1,85 @@
beforeIf();
if(if_condition1) {
true_case;
true_case;
}
afterIf();
beforeIf();
if(if_condition2)
public void act()
{
true_case;
true_case;
S66Nr3(7);
}
afterIf();
beforeIf();
if(if_else_condition1) {
true_case;
true_case;
private void fahreUmHuegel(String richtung)
{
String pri;
String sec;
if(richtung.equals("Hoch")) {
pri = "links";
sec = "rechts";
} else {
false_case;
false_case;
if (richtung.equals("Runter")){
pri = "rechts";
sec = "links";
} else {
nachricht("JUNGE DU SPAST!");
return;
}
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() {
drehe(pri);
fahre();
drehe(sec);
fahre();
fahre();
drehe(sec);
fahre();
drehe(pri);
}
boolean function2()
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);
}