Skip to content

Commit

Permalink
Add unittest, fix typos, update interpreter
Browse files Browse the repository at this point in the history
  • Loading branch information
Satin Wuker committed Sep 11, 2023
1 parent ab0550e commit 39a6e2d
Show file tree
Hide file tree
Showing 17 changed files with 160 additions and 55 deletions.
28 changes: 14 additions & 14 deletions examples/BubbleSort.rickroll
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
gonna BubbleSort arr

give index up 0
give idx up 0

together forever with index < len(arr)
give index up index + 1
give index2 up 0
together forever with index2 < len(arr) - 1

and if u ask me how im feeling arr[index2] > arr[index2 + 1]
give arr[index2], arr[index2 + 1] up arr[index2 + 1], arr[index2]
say goodbye
give index2 up index2 + 1
together forever with idx < len(arr)
give idx up idx + 1
give idx2 up 0
together forever with idx2 < len(arr) - 1

and if u ask me how im feeling arr[idx2] > arr[idx2 + 1]
give arr[idx2], arr[idx2 + 1] up arr[idx2 + 1], arr[idx2]
say goodbye
give idx2 up idx2 + 1

say goodbye
say goodbye

i just wanna tell u how im feeling arr
i just wanna tell u how im feeling arr

say goodbye

say goodbye


take me to ur heart

give arr up [6, 7, 5, 9, 12]
BubbleSort(arr)
gotta BubbleSort(arr)

say goodbye
4 changes: 3 additions & 1 deletion examples/Calculator.rickroll
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ take me to ur heart
when i give my num1 - num2 it will be completely
say goodbye

i just wanna tell u how im feeling "Calculator (each token splits with a space)"

# While True loop to keep the calculator going forever until you kill it (^C)
together forever and never to part

# Ask for input
i just wanna tell u how im feeling "\nCalculate:\n"
i just wanna tell u how im feeling "\n>>>"

give input up sys.stdin.readline()

Expand Down
10 changes: 5 additions & 5 deletions examples/Counting.rickroll
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
take me to ur heart
give index up 0
together forever with index < 99
give index up index + 1
i just wanna tell u how im feeling str(index) + "\n"
say goodbye
give idx up 0
together forever with idx < 100
give idx up idx + 1
i just wanna tell u how im feeling str(idx) + "\n"
say goodbye
say goodbye
4 changes: 2 additions & 2 deletions examples/Factorial.rickroll
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ take me to ur heart

gonna factorial num
and if u ask me how im feeling num == 0
whenigivemy 1, it will be completely
when i give my 1, it will be completely
say goodbye

when i give my factorial(num-1) * num, it will be completely
when i give my factorial(num - 1) * num, it will be completely
say goodbye

give res up factorial(5)
Expand Down
2 changes: 2 additions & 0 deletions examples/FindPrimes.rickroll
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ take me to ur heart
say goodbye

give num up 2
give final_prime up 0
together forever with num <= 40
and if u ask me how im feeling is_prime(num)
i just wanna tell u how im feeling num
i just wanna tell u how im feeling "\n"
give final_prime up num
say goodbye
give num up num + 1
say goodbye
Expand Down
File renamed without changes.
6 changes: 3 additions & 3 deletions examples/LinearSearch.rickroll
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ take me to ur heart
say good bye

give arr up [6, 7, 5, 9, 12]
LinearSearch(arr, 12)
LinearSearch(arr, 7)
LinearSearch(arr, 0)
gotta LinearSearch(arr, 12)
gotta LinearSearch(arr, 7)
gotta LinearSearch(arr, 0)
say goodbye
4 changes: 4 additions & 0 deletions examples/WhileExample.rickroll
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ take me to ur heart
give astleyCounter up 0

together forever and never to part

and if u ask me how im feeling astleyCounter == len(areYouRolling)
desert u
say goodbye

i just wanna tell u how im feeling areYouRolling[astleyCounter] + "\n"
give astleyCounter up astleyCounter + 1

say goodbye

say goodbye
1 change: 1 addition & 0 deletions src/Keywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class KW(Enum):
IMPORT1 = 'weknowthe'
IMPORT2 = "andwe'regonnaplayit"
DEF = 'gonna'
CALL = 'gotta'
RETURN1 = 'whenigivemy'
RETURN2 = 'itwillbecompletely'
TRY = 'thereaintnomistaking'
Expand Down
14 changes: 11 additions & 3 deletions src/Lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from Keywords import *

ALL_KW: Final = "ijustwannatelluhowimfeeling,andifuaskmehowimfeeling,\
give,up,weknowthe,andweregonnaplayit,gonna,whenigivemy,itwillbecompletely,\
give,up,weknowthe,andweregonnaplayit,gonna,gotta,whenigivemy,itwillbecompletely,\
thereaintnomistaking,iftheyevergetudown,takemetourheart,saygoodbye,desertu,\
runaround,togetherforeverandnevertopart,togetherforeverwith,>,<,<=,>=,aint,==,py:"

Expand All @@ -12,20 +12,25 @@ def lexicalize(stmt: str):
current_token = ''
not_in_quote = True
tokens: list[str] = []

for char in stmt:

if char == '"': not_in_quote = not not_in_quote
if char == '#': break
if char in {'~', "'"} and not_in_quote:
continue

if char in SEPARATORS and not_in_quote:

if current_token not in {' ', '\n'}:
# if current_token != '': # this process is moved to order_words()
tokens.append(current_token)

if char not in {' ', '\n'}:
tokens.append(char)

current_token = ''

else: current_token += char

return order_words(tokens)
Expand All @@ -35,23 +40,26 @@ def order_words(tokens: list[str]):
token = ['take', 'me', 'to', 'ur', 'heart']
order_words(token): final token = ['takemetourheart']
"""
# print(tokens)

final_token: Final[list[str]] = []
kw_in_statement = ''
temp = False

for tok in tokens:

if tok in ALL_KW and kw_in_statement + tok in ALL_KW:
kw_in_statement += tok

else:
temp = True

if kw_in_statement != '':
final_token.append(kw_in_statement)

final_token.append(tok)
kw_in_statement = ''

if not temp:
final_token.append(kw_in_statement)

# print(final_token)
return final_token
20 changes: 18 additions & 2 deletions src/Parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,16 @@ def endless_loop_node(Node: list, child_stmts):
def func_node(Node:list, func_name, params, child_stmts):
"""
func_node
/ | \
/ | \
func_name, params, child_stmts
"""
Node.append(["func_node", func_name, params, child_stmts])

def list_node(Node:list, items):
"""
list: items = [expr, ..., expr]
"""
Node.append(["list_node", items])

def call_func(Node:list, func_name, func_params):
"""
Expand Down Expand Up @@ -168,10 +169,25 @@ def parse(self):

AST.endless_loop_node(self.nodes, Parser(child_stmts).nodes)

# Parse 'desert u'
elif self.match(KW.BREAK):
pass

# Parse 'run around'
elif self.match(KW.CONTINUE):
pass

# Parse list
elif self.match('['):
pass

# Skipping end statement
elif self.match(KW.END.value):
pass

else:
print("unknown keyword:", self.tokens[self.pos][0])

# else:
# # Call function
# AST.call_func(self.nodes, self.tokens[self.pos][0], self.tokens[self.pos][1:])
22 changes: 13 additions & 9 deletions src/RickRoll.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
from traceback import format_exc

# Internal modules
import crickroll
import pyrickroll
import interpreter
import CRickroll
import PyRickroll
import Interpreter


def play_audio(src_file_name: str):
import AudioGenerator
from pyrickroll import Token
from PyRickroll import Token
from Lexer import lexicalize

with open(src_file_name, mode='r', encoding='utf-8') as src:
Expand Down Expand Up @@ -52,21 +52,25 @@ def main():

# Convert .rickroll to C++
if args.cpp:
crickroll.run_in_cpp(args.file)
CRickroll.run(args.file)

# Execute .rickroll using the interpreter
elif args.intpr:
interpreter.run_in_interpreter(args.file, debug=args.debug)
Interpreter.run(args.file, debug=args.debug)

# Convert .rickroll to Python
else:
try:
pycode = pyrickroll.run_in_py(args.file)
pycode = PyRickroll.run(args.file)
exec(pycode, globals(), globals())
except Exception:

error_msg = format_exc().split('File "<string>",')[-1]
print(f'Python Exception in{error_msg}')
stdout.write(f'Python Exception in{error_msg}\n')

sp_pycode = pycode.split('\n')
for i in range(len(sp_pycode)):
stdout.write(f'{i + 1}: {sp_pycode[i]}\n')

# Generate audio from source code
if args.audio:
Expand Down
2 changes: 1 addition & 1 deletion src/crickroll.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ def write(self, content: str):
####################################################################################


def run_in_cpp(src_file_name: str):
def run(src_file_name: str):
global current_line

transpiler = TranslateToCpp()
Expand Down
22 changes: 16 additions & 6 deletions src/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,41 +37,50 @@ def evaluate(tokens: str):
i = 0
while i < len(tokens):
if not tokens[i]: return

if tokens[i] == ' ':
i += 1

elif tokens[i] == '(':
ops.append(tokens[i])

elif starts_ends(tokens[i], '"'):
values.append(filter_str(tokens[i]))

elif tokens[i].isdigit():
values.append(int(tokens[i]))

elif tokens[i] == ')':
while len(ops) != 0 and ops[-1] != '(':
val2 = values.pop()
val1 = values.pop()
op = ops.pop()
values.append(apply_op(val1, val2, op))
ops.pop()

elif tokens[i] == '[':
lst = ''
while i < len(tokens):
lst += tokens[i]
i += 1

values.append(lst)

elif tokens[i] in OPERATORS:
while len(ops) != 0 and precedence(ops[-1]) >= precedence(tokens[i]):
val2 = values.pop()
val1 = values.pop()
op = ops.pop()
values.append(apply_op(val1, val2, op))
ops.append(tokens[i])

elif tokens[i] in OP_BUILT_IN_FUNCTIONS:
expr = tokens[i + 2:tokens.index(")")] # from `(` to `)`
if len(expr) == 1:
values.append(apply_u_op(tokens[i], expr[0]))
elif len(expr > 1):
values.append(apply_u_op(tokens[i], evaluate(expr)))

else: # Matched with variable

var_value = str(variables[tokens[i]])
Expand All @@ -84,6 +93,7 @@ def evaluate(tokens: str):
val1 = values.pop()
op = ops.pop()
values.append(apply_op(val1, val2, op))

return values[-1]

variables: Final[dict[str, int | str | None]] = {}
Expand All @@ -103,7 +113,7 @@ def interpret(self, nodes: list | str):
stdout.write(evaluate(node[1]))

elif node[0] == "let_node":
variables.update({node[1]:evaluate(node[2])})
variables.update({node[1]: evaluate(node[2])})

elif node[0] == "if_node":
if evaluate(node[1]) == 'True':
Expand All @@ -113,7 +123,7 @@ def interpret(self, nodes: list | str):
while evaluate(node[1]) == 'True':
self.interpret(node[2])

def run_in_interpreter(src_file_name: str, debug=False):
def run(src_file_name: str, debug=False):

intpr = Interpreter()
Node = []
Expand All @@ -128,14 +138,14 @@ def run_in_interpreter(src_file_name: str, debug=False):
tokens = [lexicalize(stmt) for stmt in content if lexicalize(stmt) != ['']]

if debug:
print("tokens (LEXER):", tokens)
stdout.write(f"tokens (LEXER): {tokens}\n\n")

Node = Parser(tokens).nodes

if debug:
print("nodes (PARSER):")
stdout.write("nodes (PARSER):\n")
for i in range(len(Node)):
print(f'{i} {Node[i]}')
print('-' * len(Node[i]))
stdout.write(f'{i} {Node[i]}\n')
stdout.write('-' * 50)

intpr.interpret(Node)
Loading

0 comments on commit 39a6e2d

Please sign in to comment.