improvements on AST shape and printing

This commit is contained in:
Lephe 2019-10-01 07:04:02 +02:00
parent 6151144d0a
commit f08f613a17
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
3 changed files with 67 additions and 9 deletions

27
ast.py
View File

@ -51,13 +51,29 @@ class Node:
self.args = args
def __str__(self):
"""Basic text representation without children."""
if self.type == N.CONST:
return str(self.value)
try:
name = N(self.type).name
return f"<Node:{name}>"
except ValueError:
return f"<Node:{hex(self.type)}>"
@property
def value(self):
"""Retrive the value of a CONST node."""
if self.type != N.CONST:
raise Exception("Taking value of non-const node")
return self.args[0]
def constchildren(self):
"""Checks whether all arguments are constants."""
return all(c.type == N.CONST for c in self.args)
def simplify(self):
"""Simplify arithmetic expressions."""
simpl = lambda n: n.simplify() if isinstance(n, Node) else n
self.args = [ simpl(arg) for arg in self.args ]
arity = len(self.args)
@ -66,9 +82,20 @@ class Node:
return Node(N.CONST, 1)
if self.type == N.MUL and arity == 1:
return self.args[0]
if self.type == N.MUL and self.constchildren():
prod = 1
for c in self.args:
prod *= c.value
return Node(N.CONST, prod)
if self.type == N.ADD and arity == 0:
return Node(N.CONST, 0)
if self.type == N.ADD and arity == 1:
return self.args[0]
if self.type == N.ADD and self.constchildren():
return Node(N.CONST, sum(c.value for c in self.args))
if self.type == N.MINUS and self.constchildren():
return Node(N.CONST, -self.args[0].value)
return self

View File

@ -37,7 +37,7 @@ def main(argv):
ast = parser.parse_program()
ast = ast.simplify()
print_ast(ast, lang="fr")
print_ast(ast, lang="ast")
if __name__ == "__main__":
main(sys.argv)

View File

@ -7,9 +7,21 @@ __all__ = ["print_ast"]
# Message definitions
#---
class MessageAST:
forward = "FORWARD {}"
rotate = "ROTATE {}"
orient = "ORIENT {}"
goto = "GOTO {}, {}"
pendown = "PENDOWN"
penup = "PENUP"
class MessageFrench:
multiply = "mul({})"
goto = "goto {}, {}"
forward = "Avancer de {} pixels"
rotate = "Tourner de {} degrés"
orient = "S'orienter à {} degrés"
goto = "Aller à x={}; y={}"
pendown = "Stylo écrit"
penup = "Stylo relevé"
class MessageEnglish:
pass
@ -19,8 +31,14 @@ class MessageEnglish:
#---
def print_ast(n, lang="en", indent=0):
if lang == "fr": lang = MessageFrench
if lang == "en": lang = MessageEnglish
if lang == "fr": lang = MessageFrench
if lang == "en": lang = MessageEnglish
if lang == "ast": lang = MessageAST
if n.type == N.PROGRAM:
for arg in n.args:
print_ast(arg, lang=lang, indent=indent)
return
print(" " * indent, end="")
@ -30,9 +48,22 @@ def print_ast(n, lang="en", indent=0):
if n.type == N.CONST:
print(n.args[0])
elif n.type == N.VAR:
print(f"VAR({n.args[0]})")
return
if n.type == N.VAR:
print(f"{n.args[0]}")
return
id = n.type.name.lower()
if hasattr(lang, id):
print(getattr(lang, id).format(*n.args))
else:
print(f"{n.type.name}")
for arg in n.args:
print_ast(arg, lang=lang, indent=indent+2)
if n.type in [N.FORWARD, N.ROTATE, N.ORIENT, N.GOTO] and \
n.constchildren():
return
for arg in n.args:
print_ast(arg, lang=lang, indent=indent+2)