From 7a8251b625b480bbfcb78ea39d060ce266db114a Mon Sep 17 00:00:00 2001 From: Xun Yang <x299yang@uwaterloo.ca> Date: Mon, 24 Feb 2020 22:07:14 -0500 Subject: [PATCH] expr Nodes --- ExprPrimaryNodes.py | 188 ++++++++++++++++++++++++++++++++++++++++++++ UnitNodes.py | 29 ------- 2 files changed, 188 insertions(+), 29 deletions(-) create mode 100644 ExprPrimaryNodes.py diff --git a/ExprPrimaryNodes.py b/ExprPrimaryNodes.py new file mode 100644 index 0000000..9166198 --- /dev/null +++ b/ExprPrimaryNodes.py @@ -0,0 +1,188 @@ +from AST import ASTNode, getParseTreeNodes, getTypeName +from Environment import Env + +# file containing smaller (lower level nodes) in the AST +# nodes in this file: +# ArgsNode +# ArrayAccessNode +# ArrayCreateNode +# AssignNode +# CastNode +# ClassCreateNode +# ExprNode +# FieldAccessNode +# LiteralNode +# MethodInvNode + +########################################################### + +# parses the expr node in the parse tree to be either ID or CastNode or ExprNode +def makeNodeFromExpr(parseTree): + c = parseTree + while (42): + if c.name == 'primaryAndArray': + return makeNodeFromAllPrimary(c.children[0]) + elif c.name == 'ID' or c.name == 'COMPID': + return c.lex + elif len(c.children) == 1: + c = c.children[0] + elif c.name == 'castExpr': + return CastNode(c) + else: + return ExprNode(c) + +# parses the primaryAndArray/primary/primaryNoArrayAccess node in the parse tree and return corresponding AST nodes +def makeNodeFromAllPrimary(parseTree): + if parseTree.name == 'primaryAndArray': + if parseTree.children[0].name == 'arrayCreationExpr': + return ArrayCreateNode(parseTree.children[0]) + parseTree = parseTree.children[0] + + if parseTree.name == 'primary': + if parseTree.children[0].name == 'arrayAccess': + return ArrayAccessNode(parseTree.children[0]) + parseTree = parseTree.children[0] + + node = parseTree.children[0] + if node.name == 'literal': + return LiteralNode(node) + elif node.name == 'LPAREN': # primaryNoArrayAccess LPAREN expr RPAREN + return makeNodeFromExpr(parseTree.children[1]) + elif node.name == 'classInstanceCreate': + return ClassCreateNode(node) + elif node.name == 'methodInvoc': + return MethodInvNode(node) + elif node.name == 'fieldAccess': + return FieldAccessNode(node) + else: + raise Exception('ERROR: something wrong at primaryNoArrayAccess') + + +########################### Node Definitions ##################################### + +################################################################################### +# args exprs, exprs expr COMMA exprs +class ArgsNode(ASTNode): + # always list all fields in the init method to show the class structure + def __init__(self, parseTree): + self.parseTree = parseTree + + +################################################################################### +# Array Access +class ArrayAccessNode(ASTNode): + # always list all fields in the init method to show the class structure + def __init__(self, parseTree): + self.parseTree = parseTree + self.array = '' # either a variableName, a field, or array access + self.index = '' # expr + self.env = None + self.children = [] + + # input parse tree is either: arrayAccess name LSQRBRACK expr RSQRBRACK + # arrayAccess ID LSQRBRACK expr RSQRBRACK + # arrayAccess primaryNoArrayAccess LSQRBRACK expr RSQRBRACK + self.array = parseTree.children[0] + self.index = parseTree.children[2] + +################################################################################## +# Assignment +class AssignNode(ASTNode): + # always list all fields in the init method to show the class structure + def __init__(self, parseTree): + self.parseTree = parseTree + self.left = '' # either a variableName, a field, or array access + self.value = '' # expr + self.env = None + self.children = [] + + # input parse tree is either: assignment leftHandSide ASSIGN expr + # OR variableDcl ID ASSIGN variableInit + # OR variableDcl name ASSIGN variableInit + self.left = makeNodeFromAllPrimary(parseTree.children[0]) + self.value = makeNodeFromExpr(getParseTreeNodes(['expr'], parseTree.children[2])[0]) + # storing the parse tree node at self.left, waiting to be resolved to point + # to corresponding fieldNode or variable declaration node + +################################################################################# +# condOrExpr +class ExprNode(ASTNode): + # always list all fields in the init method to show the class structure + def __init__(self, parseTree): + self.parseTree = parseTree + self.left = '' + self.op = '' + self.right = None # another expr + self.env = None + self.children = [] + + if parseTree.name == 'unaryNotPlusMinus' or parseTree.name == 'unaryExpr': + self.op = parseTree.children[0] + self.right = parseTree.children[1] + else: + self.left = parseTree.children[0] + self.op = parseTree.children[1] + self.right = parseTree.children[2] + + +################################################################################### +# fieldAccess primary PERIOD ID +class FieldAccessNode(ASTNode): + # always list all fields in the init method to show the class structure + def __init__(self, parseTree): + self.parseTree = parseTree + self.primary = '' # primary that hopefully resolve to a class + self.ID = '' # method/fieldName + self.env = None + self.children = [] + + # input: fieldAccess primary PERIOD ID + self.array = parseTree.children[0] + self.index = parseTree.children[2] + + + +################################################################################# +# literals +class LiteralNode(ASTNode): + toLiType = dict({ + 'LITERALBOOL': 'bool', + 'LITERALCHAR': 'char', + 'LITERALSTRING': 'String', + 'NULL': 'null', + 'NUM': 'int', + 'ZERO': 'int' + }) + # always list all fields in the init method to show the class structure + def __init__(self, parseTree): + self.parseTree = parseTree + self.liType = toLiType.get(parseTree.children[0].name) # type of the literal + self.value = parseTree.children[0].lex # the value + self.env = None + self.children = [] + + if self.liType == 'int': + self.value = int(self.value) + if self.liType == 'LITERALBOOL': + if self.value == 'false': + self.value = False + else: + self.value = True + +################################################################################### +# methodInvoc +class MethodInvNode(ASTNode): + # always list all fields in the init method to show the class structure + def __init__(self, parseTree): + self.parseTree = parseTree + self.primary = '' # can be empty + self.ID = '' # can be either ID or compID + self.args = None + self.env = None + self.children = [] + + # input parse tree is either: arrayAccess name LSQRBRACK expr RSQRBRACK + # arrayAccess ID LSQRBRACK expr RSQRBRACK + # arrayAccess primaryNoArrayAccess LSQRBRACK expr RSQRBRACK + self.array = parseTree.children[0] + self.index = parseTree.children[2] diff --git a/UnitNodes.py b/UnitNodes.py index cac7848..8b13789 100644 --- a/UnitNodes.py +++ b/UnitNodes.py @@ -1,30 +1 @@ -from AST import ASTNode, getParseTreeNodes, getTypeName -from Environment import Env - - -# literals -class LiteralNode(ASTNode): - toLiType = dict({ - 'LITERALBOOL': 'bool', - 'LITERALCHAR': 'char', - 'LITERALSTRING': 'String', - 'NULL': 'null', - 'NUM': 'int', - 'ZERO': 'int' - }) - # always list all fields in the init method to show the class structure - def __init__(self, parseTree): - self.parseTree = parseTree - self.liType = toLiType.get(parseTree.children[0].name) # type of the literal - self.value = parseTree.children[0].lex # the value - self.env = None - self.children = [] - - if self.liType == 'int': - self.value = int(self.value) - if self.liType == 'LITERALBOOL': - if self.value == 'false': - self.value = False - else: - self.value = True -- GitLab