Added function scope support to interpreter
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,7 +1,7 @@
|
|||||||
__pycache__/
|
__pycache__/
|
||||||
res/output/
|
res/output/
|
||||||
res/input/*
|
res/input/
|
||||||
.vscode/*
|
.vscode/
|
||||||
*.json
|
*.json
|
||||||
*.pyc
|
*.pyc
|
||||||
*.png
|
*.png
|
||||||
@@ -9,4 +9,3 @@ debug.py
|
|||||||
build/
|
build/
|
||||||
run.spec
|
run.spec
|
||||||
dist/
|
dist/
|
||||||
.vscode/launch.json
|
|
||||||
|
|||||||
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,21 +1,28 @@
|
|||||||
import logging
|
import logging
|
||||||
from os import remove
|
from os import remove
|
||||||
import re
|
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 errors.custom import InterpreterException, JavaSyntaxError, ScopeNotFoundException
|
||||||
from draw.Iinstruction import *
|
from draw.Iinstruction import *
|
||||||
|
|
||||||
COMMENT_REGEX = r"""^//|^#|^COMMENT|^--"""
|
COMMENT_PATTERN = re.compile(r"""^//|^/\*\*|^\*|^--""")
|
||||||
REMOVE_KEYWORDS = [' ', "public", "private", "void", ';']
|
REMOVE_KEYWORDS = [' ', "public", "private", ';']
|
||||||
FUNCTION_IDENTIFIERS = ["void", "boolean", "int"] #possible return types of functions
|
FUNCTION_IDENTIFIERS = ["void", "boolean", "int", "float"]
|
||||||
|
|
||||||
WHILE_TAG = "solange " #german for 'while'. Change this depending on your language
|
WHILE_TAG = "solange " #german for 'while'. Change this depending on your language
|
||||||
|
|
||||||
REPLACE = dict((re.escape(k), '') for k in REMOVE_KEYWORDS)
|
REPLACE = dict((re.escape(k), '') for k in REMOVE_KEYWORDS)
|
||||||
remove_pattern = re.compile("|".join(REPLACE.keys()))
|
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
|
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
|
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:
|
with open(filepath, encoding="utf-8") as file:
|
||||||
for _line in file:
|
for _line in file:
|
||||||
line = replace_all_tags(_line.strip())
|
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)
|
lines.append(line)
|
||||||
if line.__contains__('{'):
|
if line.__contains__('{'):
|
||||||
brace_open_count += 1
|
brace_open_count += 1
|
||||||
@@ -71,6 +78,17 @@ 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)
|
||||||
|
elif "}" in line:
|
||||||
|
return i-start_idx
|
||||||
|
i+=1
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -162,25 +180,40 @@ 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_scopes(src: List[str]) -> List[Tuple[int, int]]:
|
def get_function_scope_spans(src: List[str]) -> List[Tuple[int, int]]:
|
||||||
|
spans = []
|
||||||
i = 0
|
i = 0
|
||||||
print(function_pattern)
|
|
||||||
while i < len(src):
|
while i < len(src):
|
||||||
line = src[i]
|
line = src[i]
|
||||||
try:
|
try:
|
||||||
|
|
||||||
if function_pattern.match(line):
|
if match:= function_pattern.match(line):
|
||||||
print(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
|
raise
|
||||||
i += 1
|
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)
|
src = load_src(filepath)
|
||||||
instructions, i = get_instructions_in_scope(src)
|
scope_spans = get_function_scope_spans(src)
|
||||||
if i != len(src):
|
instructions = get_instructions_in_scopes(src, scope_spans)
|
||||||
raise InterpreterException("Unknown error during source interpretation! Unsupported language constructs or ill-formed source?")
|
return instructions
|
||||||
return instructions
|
|
||||||
|
|||||||
@@ -1,83 +1,85 @@
|
|||||||
beforeIf();
|
public void act()
|
||||||
if(if_condition1) {
|
|
||||||
true_case;
|
|
||||||
true_case;
|
|
||||||
}
|
|
||||||
afterIf();
|
|
||||||
beforeIf();
|
|
||||||
if(if_condition2)
|
|
||||||
{
|
{
|
||||||
true_case;
|
S66Nr3(7);
|
||||||
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() {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user