Skip to content

Commit

Permalink
refacored names and made proper syntax tree preprocessing and further…
Browse files Browse the repository at this point in the history
… processing on the AST
  • Loading branch information
Felienne committed May 1, 2020
1 parent 871c3c7 commit c2222b2
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 44 deletions.
2 changes: 2 additions & 0 deletions grammars/level1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ command: "print" (" " text)? -> print

_EOL: "\r"?"\n"


text: /([^\n]+)/ -> text //anything can be parsed except for a newline
textwithoutspaces: /([^\n *+-\/]+)/ -> text //anything can be parsed except for spaces (plus: a newline)

SPACE: " "

%import common.LETTER // imports from terminal library
%import common.DIGIT // imports from terminal library
Expand Down
73 changes: 31 additions & 42 deletions hedy.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,43 +41,29 @@ def __init__(self, message, **arguments):



class AllCommands(Transformer):
#creates a list of all commands in a tree for further processing
# it removes command and program nodes
def program(self, args):
commands = []
for c in args:
commands.append(c)
return commands
def repeat(self, args):
commands = args[2:-1]
return commands
def command(self, args):
return args
def text(self, args):
return Tree('text', ''.join([str(c) for c in args]))
def var(self, args):
return Tree('var', ''.join([str(c) for c in args]))
def punctuation(self, args):
return Tree('punctuation', ''.join([str(c) for c in args]))

class FlattenText(Transformer):
#flattens arguments of text, var and punctuation for more easy debugging
class ExtractAST(Transformer):
# simplyfies the tree: f.e. flattens arguments of text, var and punctuation for further processing
def text(self, args):
return Tree('text', ''.join([str(c) for c in args]))

#level 2
def var(self, args):
return Tree('var', ''.join([str(c) for c in args]))
def punctuation(self, args):
return Tree('punctuation', ''.join([str(c) for c in args]))
def index(self, args):
return ''.join([str(c) for c in args])
def list_access(self, args):
if type(args[1]) == Tree:
return Tree('list_access', [args[0], 'random'])
else:
return Tree('list_access', [args[0], args[1]])

#level 5
def number(self, args):
return Tree('number', ''.join([str(c) for c in args]))
#level 6 (and up)
def repeat(self, args):
commands = args[2:-1]
return Tree('repeat times' + str(args[0]), commands)
def indent(self, args):
return ''
def dedent(self, args):
Expand All @@ -98,8 +84,10 @@ def flatten(args):
flattened_args.append(a)
return flattened_args

class AllAssignmentCommands(FlattenText):
#returns only assignments
class AllAssignmentCommands(ExtractAST):
# returns only variable assignments AND places where variables are accessed
# so these can be excluded when printing

def program(self, args):
return flatten(args)

Expand All @@ -123,6 +111,8 @@ def list_access_var(self, args):
return args[0].children
def var_access(self,args):
return args[0].children

#list access is accessing a variable, so must be escaped
def list_access(self, args):
if type(args[1]) == Tree:
return 'random.choice(' + args[0].children + ')'
Expand All @@ -131,12 +121,10 @@ def list_access(self, args):
def print(self, args):
return args

def all_commands(tree):
commands = AllCommands().transform(tree)
return commands


def all_assignments(tree):
flat = FlattenText().transform(tree)
flat = ExtractAST().transform(tree)
assignments = AllAssignmentCommands().transform(tree)
return assignments #leeg dus als er geen assignments gevonden zijn

Expand Down Expand Up @@ -328,7 +316,6 @@ def invalid(self, args):
return False, args[0][1]



class ConvertToPython_1(Transformer):
def __init__(self, punctuation_symbols, lookup):
self.punctuation_symbols = punctuation_symbols
Expand Down Expand Up @@ -359,7 +346,8 @@ def wrap_non_var_in_quotes(argument, lookup):

class ConvertToPython_2(ConvertToPython_1):
def var(self, args):
return ''.join(["_" + str(c) if c in reserved_words else str(c) for c in args])
name = ''.join(args)
return "_" + name if name in reserved_words else name
def print(self, args):
all_arguments_converted = []
i = 0
Expand All @@ -385,10 +373,11 @@ def assign_list(self, args):
return parameter + " = [" + ", ".join(values) + "]"

def list_access(self, args):
if args[1].data == 'random':
if args[1] == 'random':
return 'random.choice(' + args[0] + ')'
else:
return args[0] + '[' + args[1].children[0] + ']'
return args[0] + '[' + args[1] + ']'



#TODO: lookuptable and punctuation chars not be needed for level2 and up anymore, could be removed
Expand Down Expand Up @@ -682,7 +671,7 @@ def transpile_inner(input_string, level):
try:
program_root = parser.parse(input_string+ '\n').children[0] # getting rid of the root could also be done in the transformer would be nicer
lookup_table = all_assignments(program_root)
flattened_tree = FlattenText().transform(program_root)
abstract_syntaxtree = ExtractAST().transform(program_root)
except Exception as e:
# TODO: if all else fails, here we could translate Lark error messages into more sensible texts!
raise HedyException('Parse', level=level, parse_error=e.args[0])
Expand Down Expand Up @@ -711,35 +700,35 @@ def transpile_inner(input_string, level):


if level == 1:
python = ConvertToPython_1(punctuation_symbols, lookup_table).transform(program_root)
python = ConvertToPython_1(punctuation_symbols, lookup_table).transform(abstract_syntaxtree)
return python
elif level == 2:
python = 'import random\n'
python += ConvertToPython_2(punctuation_symbols, lookup_table).transform(program_root)
python += ConvertToPython_2(punctuation_symbols, lookup_table).transform(abstract_syntaxtree)
return python
elif level == 3:
python = 'import random\n'
python += ConvertToPython_3(punctuation_symbols, lookup_table).transform(program_root)
python += ConvertToPython_3(punctuation_symbols, lookup_table).transform(abstract_syntaxtree)
return python
elif level == 4:
python = 'import random\n'
python += ConvertToPython_4(punctuation_symbols, lookup_table).transform(program_root)
python += ConvertToPython_4(punctuation_symbols, lookup_table).transform(abstract_syntaxtree)
return python
elif level == 5:
python = 'import random\n'
python += ConvertToPython_5(punctuation_symbols, lookup_table).transform(program_root)
python += ConvertToPython_5(punctuation_symbols, lookup_table).transform(abstract_syntaxtree)
return python
elif level == 6:
python = 'import random\n'
python += ConvertToPython_6(punctuation_symbols, lookup_table).transform(program_root)
python += ConvertToPython_6(punctuation_symbols, lookup_table).transform(abstract_syntaxtree)
return python

#todo: we need to be able to 'valid check' levels 6 and 8+ also, skipping for now (requires changes to grammar)
elif level >= 7:
parser = Lark(create_grammar(level), parser='lalr', postlex=BasicIndenter(), debug=True)
punctuation_symbols = ['!', '?', '.']
program_root = parser.parse(input_string + '\n').children[0] # TODO: temporary fix, statements have to end with _EOL
flattened_tree = FlattenText().transform(program_root)
abstract_syntaxtree = ExtractAST().transform(program_root)
lookup_table = all_assignments(program_root)
if level == 7:
try:
Expand Down
2 changes: 0 additions & 2 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ def test_print_with_list_var_random(self):
# self.assertEqual(str(context.exception), 'VarUndefined')
# print('Passed at level ', i)



class TestsLevel1(unittest.TestCase):

def test_transpile_other(self):
Expand Down

0 comments on commit c2222b2

Please sign in to comment.