improved interpreter

This commit is contained in:
weckyy702
2020-12-27 15:42:43 +01:00
parent de7a71b15b
commit 317387e24d
3 changed files with 187 additions and 203 deletions

View File

@@ -40,9 +40,8 @@ class NassiShneidermanDiagram:
cti.NSD_save(filename) cti.NSD_save(filename)
def load_from_file(self, filepath:str): def load_from_file(self, filepath:str):
src_code = itp.load_src(filepath) instructions = itp.load_instructions(filepath)
global_scope = itp.get_instructions_in_scope(src_code)[0] self.add_instructions_from_scope(instructions)
self.add_instructions_from_scope(global_scope)
def add_instructions_from_scope(self, scope: List[Iinstruction]): def add_instructions_from_scope(self, scope: List[Iinstruction]):
for inst in scope: for inst in scope:

View File

@@ -1,17 +1,12 @@
import logging import logging
from os import remove from os import remove
import re import re
from typing import List, Text, Tuple from typing import Callable, List, Tuple
from draw.Iinstruction import * from draw.Iinstruction import *
COMMENT_REGEX = r"""^//|^#|^COMMENT|^--""" class InterpreterError(Exception):
REMOVE_KEYWORDS = [' ', "public", "private", "void"] pass
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()))
class JavaSyntaxError(Exception): class JavaSyntaxError(Exception):
pass pass
@@ -19,6 +14,14 @@ class JavaSyntaxError(Exception):
class ScopeNotFoundException(Exception): class ScopeNotFoundException(Exception):
pass pass
COMMENT_REGEX = r"""^//|^#|^COMMENT|^--"""
REMOVE_KEYWORDS = [' ', "public", "private", "void", ';']
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()))
def replace_all_tags(org: str): def replace_all_tags(org: str):
return remove_pattern.sub(lambda m: REPLACE[re.escape(m.group(0))], org) return remove_pattern.sub(lambda m: REPLACE[re.escape(m.group(0))], org)
@@ -43,80 +46,126 @@ def load_src(filepath: str) -> List[str]:
return lines return lines
def check_src(src: List[str], line_index: int, tag: str) -> bool:
if line_index >= len(src):
return False
return src[line_index].__contains__(tag)
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: 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 i = start_idx
while i < len(src): while i < len(src):
if src[i].__contains__(tag): if check_src(src, i, tag):
return i break
i += 1 i += 1
return i
def get_scope_start_offset(src: List[str], start_idx: int) -> int: def get_scope_start_offset(src: List[str], i: int) -> int:
i = get_next_occurence_of(src, start_idx, '{') if check_src(src, i, "{"):
if i != len(src): return 1
return i + 1 elif check_src(src, i+1, "{"):
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 handle_while(line: str, src: List[str], i: int) -> Tuple[Iinstruction, int]:
def get_instructions_in_scope(src: List[str], start_idx: int = 0) -> Tuple[List[Iinstruction], int]:
outer_scope: List[Iinstruction] = []
i = start_idx
while i < len(src):
line = src[i]
try:
if line.__contains__('}'): #We exited this scope, return it
return outer_scope, i
if line.startswith("while("):
logging.debug("Found while construct in line: %i", i+1)
bracket_idx = line.rindex(')') # throws if while contruct is illformed bracket_idx = line.rindex(')') # throws if while contruct is illformed
instruction_txt = line[6:bracket_idx] instruction_txt = line[6:bracket_idx]
brace_offset = get_scope_start_offset(src, i) brace_offset = get_scope_start_offset(src, i)
child_instructions, i = get_instructions_in_scope(src, i+brace_offset) child_instructions, i = get_instructions_in_scope(src, i+brace_offset)
return while_instruction_front((WHILE_TAG + instruction_txt), child_instructions), i
outer_scope.append(while_instruction_front((WHILE_TAG + instruction_txt), child_instructions)) def handle_else(src: List[str], i: int) -> Tuple[List[Iinstruction], int]:
brace_offset = get_scope_start_offset(src, i)
elif line.startswith("if("): return get_instructions_in_scope(src, i+brace_offset)
logging.debug("Found if construct in line: %i", i+1)
def handle_if(line: str, src: List[str], i: int) -> Tuple[Iinstruction, int]:
bracket_idx = line.rindex(')') # throws if the contruct is illformed bracket_idx = line.rindex(')') # throws if the contruct is illformed
instruction_txt = line[3:bracket_idx] instruction_txt = line[3:bracket_idx]
brace_offset = get_scope_start_offset(src, i) brace_offset = get_scope_start_offset(src, i)
true_instructions, i = get_instructions_in_scope(src, i+brace_offset) true_instructions, i = get_instructions_in_scope(src, i+brace_offset)
false_instructions = None false_instructions = None
#if there is an else statement, check it
if src[i].__contains__("else"): #check for else statements
if check_line_start(src, i, "}else"):
logging.debug("found else construct in line: %i", i+1) logging.debug("found else construct in line: %i", i+1)
brace_offset = get_scope_start_offset(src, i) false_instructions, i = handle_else(src, i)
false_instructions, i = get_instructions_in_scope(src, i+brace_offset)
elif src[i+1].__contains__("else"): elif check_line_start(src, i+1, "else"):
logging.debug("found else construct in line: %i", i+2) logging.debug("found else construct in line: %i", i+2)
brace_offset = get_scope_start_offset(src, i+1) false_instructions, i = handle_else(src, i+1)
false_instructions, i = get_instructions_in_scope(src, i+1+brace_offset)
return if_instruction(instruction_txt, true_instructions, false_instructions), i
outer_scope.append(if_instruction(instruction_txt, true_instructions, false_instructions)) def handle_do_while(line: str, src: List[str], i: int) -> Tuple[Iinstruction, int]:
elif line.startswith("do"):
logging.debug("Found start of do-while construct in line: %i", i+1)
brace_offset = get_scope_start_offset(src, i) brace_offset = get_scope_start_offset(src, i)
child_instructions, i = get_instructions_in_scope(src, i+brace_offset) child_instructions, i = get_instructions_in_scope(src, i+brace_offset)
instruction_txt = None
if check_line_start(src, i, "}while("):
end_line = src[i] end_line = src[i]
bracket_idx = end_line.rindex(");") bracket_index = end_line.rindex(')') #throws if contruct id ill-formed
instruction_txt = end_line[7: bracket_idx] instruction_txt = end_line[7:bracket_index]
elif check_line_start(src, i+1, "while("):
i += 1 #make sure we return the correct value for i
end_line = src[i]
bracket_index = end_line.rindex(')')
instruction_txt = end_line[6:bracket_index]
else:
raise JavaSyntaxError("Ill-formed do-while construct!")
outer_scope.append(while_instruction_back((WHILE_TAG + instruction_txt), child_instructions)) return while_instruction_back(instruction_txt, child_instructions), i
def handle_instruction(line: str, src: List[str], i: int) -> Tuple[Iinstruction, int]:
if line.startswith("while("):
logging.debug("Found while construct in line: %i", i+1)
return handle_while(line, src, i)
elif line.startswith("if("):
logging.debug("Found if construct in line: %i", i+1)
return handle_if(line, src, i)
elif line.startswith("do"):
logging.debug("Found do-while construct in line: %i", i+1)
return handle_do_while(line, src, i)
else: else:
logging.debug("Found generic instruction in line: %i", i+1) logging.debug("found generic instruction in line %i", i+1)
outer_scope.append(generic_instruction(line)) return generic_instruction(line), i
def get_instructions_in_scope(src: List[str], start_idx: int = 0) -> Tuple[List[Iinstruction], int]:
outer_scope: List[Iinstruction] = []
i = start_idx
while i < len(src):
line = src[i]
try:
if check_src(src, i, "}"): #We exited this scope, return it
break
instruction, i = handle_instruction(line, src, i)
outer_scope.append(instruction)
except Exception as e:
logging.error("Encountered error in line %i: %s", i+1, str(e))
raise
except: except:
logging.error("Encountered error in line: %i", i+1) logging.fatal("Encountered unexpected error in line: %i", i+1)
raise # rethrow raise
i += 1 i += 1
return outer_scope, 0
return outer_scope, i
def load_instructions(filepath: str) -> List[Iinstruction]:
src = load_src(filepath)
instructions, i = get_instructions_in_scope(src)
if i != len(src):
raise InterpreterError("Unknown error during source interpretation! Unsupported language constructs or ill-formed?")
return instructions

View File

@@ -1,133 +1,37 @@
// // fahre1(); beforeIf();
// // fahre2(); if(if_condition1) {
// // while(shouldNiet()) true_case;
true_case;
}
// // { afterIf();
// // niet4(); beforeIf();
// // niet5(); if(if_condition2)
// // if(if6) {
// // { true_case;
// // niet7(); true_case;
// // niet8(); }
// // } else afterIf();
// // { beforeIf();
// // niet10(); if(if_else_condition1) {
// // niet11(); true_case;
// // } true_case;
// // niet13(); } else {
// // } false_case;
// // niet15(); false_case;
// // niet16(); }
afterIf();
// // do{ beforeIf();
// // niet21(); if(if_else_condition2) {
// // niet22(); true_case;
// // }while(bool23); true_case;
}
// //the following code was heavily distorted in order to test the interpreter. Sorry to everyone who has to read this else {
false_case;
// void false_case;
}
// private void afterIf();
beforeIf();
if(if_else_condition3) {
// drehe("links");
// while(huegelVorhanden("rechts"))
// {
// gesteinSammeln();
// fahre();
// }
// drehe("rechts");
// gesteinSammeln();
// fahre();
// while(huegelVorhanden("rechts"))
// {
// gesteinSammeln();
// fahre();
// }
// drehe("rechts");
// gesteinSammeln();
// fahre();
// while(huegelVorhanden("rechts"))
// {
// gesteinSammeln();
// if(!huegelVorhanden("vorne"))
// {
// fahre();
// }
// else
// {
// fahre();
// }
// }
// drehe("rechts");
// do
// {
// insideDoWhile();
// insideDoWhile();
// insideDoWhile();
// insideDoWhile();
// }
// while( !huegelVorhanden( "vorne" ) ) ;
if(bool) {
true_case; true_case;
true_case; true_case;
} }
@@ -136,3 +40,35 @@ else
false_case; false_case;
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