From 4e415a863c0a25f71de86aa6c6cabaf63dba6263 Mon Sep 17 00:00:00 2001 From: jooapa Date: Wed, 10 Jan 2024 17:41:45 +0200 Subject: [PATCH] indent capibability, for loop, bug fixes --- README.md | 45 ++++++++++++++++++++++-------- "example.n\303\266ff" | 20 +++++++------- interpeter/error.py | 40 +++++++++++++++++++++++++++ interpeter/for_loop.py | 56 ++++++++++++++++++++++++++++++++++++++ interpeter/if_statement.py | 30 +++++++++----------- interpeter/interpret.py | 12 ++++++-- interpeter/oink.py | 4 +-- interpeter/pig.py | 11 ++++++-- interpeter/slingshot.py | 7 +++-- interpeter/start.py | 38 ++++++++++++++++++++------ interpeter/variable.py | 24 +++++++++++----- 11 files changed, 222 insertions(+), 65 deletions(-) create mode 100644 interpeter/for_loop.py diff --git a/README.md b/README.md index df54876..0963c15 100644 --- a/README.md +++ b/README.md @@ -115,10 +115,10 @@ nilf $num1 == $num2 : slingshot possu3 ``` ### Creating a pig (function) -You can create a line receiver by using the `pig` keyword. +You can create a line receiver by using the `pig` keyword. Use `gip` to end the function. ```bash pig possu -oink "Hello World!" + oink "Hello World!" gip ``` @@ -130,12 +130,21 @@ slingshot possu ### For loops -For loops can be created by using the `nör` keyword. and the second parameter is the times the loop will run. Use `når` to end the loop. +For loops can be created by using the `nör` keyword. Second parameter is for the loop name. and the third parameter is the times the loop will run. Use `når` to end the loop. + +Be careful, you cannot use the same loop name twice. ```bash -nör 5 -oink "oinking 5 times" -når // to end the loop +nör oink 5 + oink "oinking 5 times" +når + +``` +```bash +nöf times = 5 + nör oink $times + oink "oinking $times times" +når ``` @@ -205,10 +214,10 @@ slingshot cubic_root_num1 // function to cubic root the num1 pig cubic_root_num1 -multiply $num1 $num2 -power $num1 0.333 + multiply $num1 $num2 + power $num1 0.333 -oink "$num1" + oink "$num1" gip @@ -225,15 +234,27 @@ nilf $num1 < $num2 : slingshot possu2 nilf $num1 == $num2 : slingshot possu3 pig possu1 -oink "num1 is bigger than num2" + oink "$num1 is bigger than $num2" gip pig possu2 -oink "num1 is smaller than num2" + oink "$num1 is smaller than $num2" gip pig possu3 -oink "num1 is equal to num2" + oink "$num1 is equal to $num2" gip ``` +## Simple for loop Example +```bash +nöff my_program + +nöf num1 = 16 +nöf num2 = 2 + +nör oink 5 + oink "oinking 5 times" +når + +``` diff --git "a/example.n\303\266ff" "b/example.n\303\266ff" index 5b011bb..739e271 100644 --- "a/example.n\303\266ff" +++ "b/example.n\303\266ff" @@ -1,15 +1,15 @@ -nöff my_program +nöff complex_program -nöf num1 = 16 -nöf num2 = d +nöf count = 0 +nöf limit = 5 -slingshot cubic_root_num1 +nör main_loop $limit + oink "Current count: $count" + add $count 1 +når -// function to cubic root the num1 -pig cubic_root_num1 - -divide num1 1 - -oink "$num1" +niff $count == $limit : slingshot end_program +pig end_program +oink "Program finished with count: $count" gip diff --git a/interpeter/error.py b/interpeter/error.py index f8044fd..a36f2db 100644 --- a/interpeter/error.py +++ b/interpeter/error.py @@ -56,4 +56,44 @@ def last_line_not_empty(): def not_number(value): print("Error: \"" + value + "\" is not a number") line_error() + exit() + +def invalid_for_loop(): + print("Error: Invalid for loop") + line_error() + exit() + +def loop_not_found(loop): + print("Error: Loop \"" + loop + "\" not found") + line_error() + exit() + +def no_variable_value(): + print("Error: No variable value") + line_error() + exit() + +def invalid_if_statement(): + print("Error: Invalid if statement") + line_error() + exit() + +def no_variable_name(): + print("Error: No variable name") + line_error() + exit() + +def invalid_slingshot(): + print("Error: Invalid slingshot") + line_error() + exit() + +def invalid_pig(): + print("Error: Invalid pig") + line_error() + exit() + +def nothing_to_gip(): + print("Error: Nothing to gip") + line_error() exit() \ No newline at end of file diff --git a/interpeter/for_loop.py b/interpeter/for_loop.py new file mode 100644 index 0000000..3f0eeaa --- /dev/null +++ b/interpeter/for_loop.py @@ -0,0 +1,56 @@ +import start, error, variable + + +def start_loop(): + loop_name = get_loop_name_from_start_for_loops(start.line_number) + try: + only_loop_name = loop_name.split(" ", 2)[0] + except: + error.invalid_for_loop() + + loop_number = loop_name.split(" ", 2)[1] + + if variable.is_variable(loop_number): + loop_number = variable.get_variable_value(loop_number) + loop_number = int(loop_number) + + loop_number -= 1 + change_loop_name(start.for_loops, start.line_number, + only_loop_name + " " + str(loop_number)) + +def end_loop(): + # get the start line number by the giving the end line number + try: + start_line, loop_name = get_start_line(start.for_loops, + start.line_number) + loop_number = loop_name.split(" ", 2)[1] + except: + error.invalid_for_loop() + + if variable.is_variable(loop_number): + loop_number = variable.get_variable_value(loop_number) + loop_number = int(loop_number) + + if int(loop_number) <= 0: + pass + else: + start.goto_number = start_line + +def get_start_line(loops, end_line): + for loop_name, (start_line, loop_end_line) in loops.items(): + if loop_end_line == end_line: + return start_line, loop_name + return None + +def change_loop_name(loops, start_line, new_name): + for loop_name, (loop_start_line, end_line) in list(loops.items()): + if loop_start_line == start_line: + loops[new_name] = loops.pop(loop_name) + return + error.loop_not_found(start_line) + +def get_loop_name_from_start_for_loops(start_line): + for loop_name, (loop_start_line, end_line) in start.for_loops.items(): + if loop_start_line == start_line: + return loop_name + return None \ No newline at end of file diff --git a/interpeter/if_statement.py b/interpeter/if_statement.py index 80ab4c6..f0ae90a 100644 --- a/interpeter/if_statement.py +++ b/interpeter/if_statement.py @@ -1,29 +1,25 @@ -import start, error, slingshot, pig +import start, error, slingshot, pig, variable if_statement_was_True = False def if_statement(): global if_statement_was_True - - value1 = start.full_line.split(" ", 2)[1] + try: + value1 = start.full_line.split(" ", 2)[1] + except: + error.invalid_if_statement() + operator = start.full_line.split(" ", 3)[2] value2 = start.full_line.split(" ", 4)[3] goto_function = start.full_line.split(" ", 5)[5] - if value1.startswith("$"): - value1 = value1.replace("$", "") - if value1 in start.variables: - value1 = start.variables[value1] - else: - error.variable_not_found(value1) - - if value2.startswith("$"): - value2 = value2.replace("$", "") - if value2 in start.variables: - value2 = start.variables[value2] - else: - error.variable_not_found(value2) - + if variable.is_variable(value1): + value1 = variable.get_variable_value(value1) + if variable.is_variable(value2): + value2 = variable.get_variable_value(value2) + value1 = variable.convert_to_number(value1) + value2 = variable.convert_to_number(value2) + if operator == ">": if value1 > value2: if_statement_was_True = True diff --git a/interpeter/interpret.py b/interpeter/interpret.py index 17361b4..5f3a1c2 100644 --- a/interpeter/interpret.py +++ b/interpeter/interpret.py @@ -1,4 +1,4 @@ -import sys, os, start +import sys, os, start, textwrap from error import invalid_extension @@ -28,12 +28,20 @@ def interpret(args): klinoff_file = get_absolute_path(args[0]) klinoff_content = get_contents(klinoff_file) + # remove indentations + no_indent_klinoff_content = "" + for line in klinoff_content.split("\n"): + no_indent_klinoff_content += textwrap.dedent(line) + "\n" + + # remove last \n + no_indent_klinoff_content = no_indent_klinoff_content[:-1] + for arg in args: if arg == "--debug" or arg == "-d": start.Debug_mode = True os.system("cls") - start.start(klinoff_content) + start.start(no_indent_klinoff_content) if __name__ == "__main__": interpret(sys.argv[1::]) \ No newline at end of file diff --git a/interpeter/oink.py b/interpeter/oink.py index b8ecd9f..a91d494 100644 --- a/interpeter/oink.py +++ b/interpeter/oink.py @@ -1,8 +1,6 @@ import start, error def say(): - has_squigel = False - if start.full_line == "oink": print("") return @@ -27,9 +25,9 @@ def say(): for word in words: if word.startswith("$"): if "§" in word: - has_squigel = True word = word.split("§")[0] word = word.replace("§", " ") + word = word.replace("$", "") if word in start.variables: variable = start.variables[word] diff --git a/interpeter/pig.py b/interpeter/pig.py index 8b3910d..da7ec3b 100644 --- a/interpeter/pig.py +++ b/interpeter/pig.py @@ -2,7 +2,10 @@ def pig(): - function_variable = start.full_line.split(" ", 1)[1] + try: + function_variable = start.full_line.split(" ", 1)[1] + except: + error.invalid_pig() start_line, end_line = start.functions[function_variable] start.goto_number = end_line + 1 @@ -11,8 +14,10 @@ def pig(): def gip(): lines = start.full_code.split("\n") - - start.goto_number = start.last_came[-1] + try: + start.goto_number = start.last_came[-1] + except: + error.nothing_to_gip() # print(if_statement.if_statement_was_True) if if_statement.start.coming_from_if and if_statement.if_statement_was_True: if_statement.start.coming_from_if = False diff --git a/interpeter/slingshot.py b/interpeter/slingshot.py index a64ffa5..94d3d3e 100644 --- a/interpeter/slingshot.py +++ b/interpeter/slingshot.py @@ -1,8 +1,11 @@ -import start +import start, error def slingshot(line): - slingshot_variable = line.split(" ", 1)[1] + try: + slingshot_variable = line.split(" ", 1)[1] + except: + error.invalid_slingshot() start.last_came.append(start.line_number + 1) start.goto_number = start.functions[slingshot_variable][0] + 1 \ No newline at end of file diff --git a/interpeter/start.py b/interpeter/start.py index 586ab8b..0adca6b 100644 --- a/interpeter/start.py +++ b/interpeter/start.py @@ -1,5 +1,5 @@ import sys, os -import error, oink, variable, if_statement, slingshot, pig +import error, oink, variable, if_statement, slingshot, pig, for_loop # nöff start of program # nöf create variable # oink print @@ -16,6 +16,9 @@ functions = { # "function_name": [start_line, end_line] } +for_loops = { + # "for_loop_name 4": [start_line, end_line] +} program_name = "" line_number = 0 # current line number @@ -55,7 +58,24 @@ def setup_functions(lines): if last_function_name is not None: functions[last_function_name][1] = line_number last_function_name = None - + +def setup_for_loops(lines): + # add every for loop to the for_loops dictionary with the line number + # for the start and end of the for loop, for loop starts with nör and ends with når + global for_loops + line_number = 0 + last_for_loop_name = None + for line in lines: + line_number += 1 + if line.startswith("nör ") and len(line.split()) > 1: + for_loop_name = line.split(" ", 1)[1] + for_loops[for_loop_name] = [line_number, 0] + last_for_loop_name = for_loop_name + elif line.startswith("når"): + if last_for_loop_name is not None: + for_loops[last_for_loop_name][1] = line_number + last_for_loop_name = None + def debugger(): if Debug_mode: input() @@ -80,11 +100,11 @@ def detect_keywords(): elif first_word == "nilf": if_statement.if_statement() elif first_word == "nör": - pass + for_loop.start_loop() elif first_word == "når": - pass + for_loop.end_loop() elif first_word == "modify": - variable.modify() + variable.modify(full_line) elif first_word == "add": variable.do_operator("add") elif first_word == "sub": @@ -126,7 +146,7 @@ def start(content): error.invalid_file() else: program_name = content.split("\n")[0].replace("nöff ", "") - print("Program name: " + program_name) + print("Program: " + program_name) # read every line lines = content.split("\n") @@ -134,8 +154,9 @@ def start(content): # last line should be empty if lines[-1] != "": error.last_line_not_empty() - + setup_functions(lines) + setup_for_loops(lines) i = 1 while i <= len(lines): # if goto_number is not -1, start reading from goto_number down @@ -143,7 +164,6 @@ def start(content): i = goto_number goto_number = -1 continue - full_line = lines[i-1] line_number = i @@ -158,4 +178,4 @@ def start(content): detect_keywords() i += 1 - \ No newline at end of file + \ No newline at end of file diff --git a/interpeter/variable.py b/interpeter/variable.py index b6cd17f..4f7d981 100644 --- a/interpeter/variable.py +++ b/interpeter/variable.py @@ -1,16 +1,22 @@ -import sys, os, start +import sys, os, start, error def create(): variable_name = start.full_line.split(" ")[1] # value is the rest of the line - variable_value = start.full_line.split(" ", 3)[3] + try: + variable_value = start.full_line.split(" ", 3)[3] + except: + error.no_variable_value() start.variables[variable_name] = variable_value def modify(line): variable_name = line.split(" ")[1] # value is the rest of the line - variable_value = line.split(" ", 2)[2] + try: + variable_value = line.split(" ", 2)[2] + except: + error.no_variable_name() if is_variable(variable_value): variable_value = get_variable_value(variable_value) # remove $ from variable name @@ -48,9 +54,12 @@ def convert_to_number(number): start.error.invalid_number(number) def do_operator(operator): - value1 = start.full_line.split(" ")[1] - variable = value1 - value2 = start.full_line.split(" ")[2] + try: + value1 = start.full_line.split(" ")[1] + variable = value1 + value2 = start.full_line.split(" ")[2] + except: + error.no_variable_name() # check if value1 is a variable if is_variable(value1): @@ -83,5 +92,6 @@ def do_operator(operator): result = float(value1) % float(value2) elif operator == "power": result = float(value1) ** float(value2) + modify("modify " + str(variable) + " " + str(result)) - + \ No newline at end of file