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