From d996f1e3e9c53f4c689cb086dc4b4d27fbfcd898 Mon Sep 17 00:00:00 2001 From: Xun Yang <x299yang@uwaterloo.ca> Date: Mon, 24 Feb 2020 23:33:00 -0500 Subject: [PATCH] add more lower level nodes --- AST.py | 16 -------------- MemberNodes.py | 27 ++++++++++------------- UnitNodes.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 31 deletions(-) diff --git a/AST.py b/AST.py index 88e71d0..3e89f96 100644 --- a/AST.py +++ b/AST.py @@ -73,19 +73,3 @@ def getParseTreeNodes(names, tree, terminateList = []): else: result.extend(getParseTreeNodes(names, n)) return result - - -# input: a parse tree node with its name == 'type' -# output: (isPrimitiveType: Bool, typeName: String) of a type -def getTypeName(node): - isPrimType = False - typeName = '' - nameNodes = getParseTreeNodes(['BOOLEAN', 'BYTE', 'CHAR', 'INT', 'SHORT'], node) - if nameNodes: - isPrimType = True - else: - # get refType - nameNodes = getParseTreeNodes(['ID', 'COMPID'], node) - for n in nameNodes: - typeName = n.lex - return (isPrimType, typeName) diff --git a/MemberNodes.py b/MemberNodes.py index 6a212d7..13e0270 100644 --- a/MemberNodes.py +++ b/MemberNodes.py @@ -1,6 +1,6 @@ -from AST import ASTNode, getParseTreeNodes, getTypeName +from AST import ASTNode, getParseTreeNodes from LineNodes import BlockNode -from WordNodes import makeNodeFromExpr +from ExprPrimaryNodes import makeNodeFromExpr, TypeNode from Environment import Env from collections import OrderedDict @@ -13,7 +13,6 @@ class FieldNode(ASTNode): self.fieldType = '' self.fieldInit = None self.mods = [] - self.isPrimType = False # easy boolean flag, can be optimize later self.env = None self.children = [] @@ -24,7 +23,7 @@ class FieldNode(ASTNode): self.mods.append(m.lex) elif node.name == 'type': - self.isPrimType, self.fieldType = getTypeName(node) + self.fieldType = TypeNode(node) elif node.name == 'variableDcl': nameNodes = getParseTreeNodes(['ID', 'COMPID'], node, ['variableInit']) @@ -46,11 +45,10 @@ class MethodNode(ASTNode): self.parseTree = parseTree self.name = '' self.methodType = '' - self.params = OrderedDict() # a dictionary {paramName -> (isPrimType, typeName)}, after type linking: {paramName -> typeNode} + self.params = [] # a list of tuples (paramName, typeNode) self.mods = [] self.body = None - self.isPrimType = False # easy boolean flag, can be optimize later - self.paramTypes = '' # a string of param types for easy type checking against arguments + self.paramTypes = '' # a string of param types (signature) for easy type checking against arguments self.env = None self.children = [] @@ -66,19 +64,18 @@ class MethodNode(ASTNode): paramType = '' for c in n.children: if c.name == 'type': - paramType = getTypeName(c) + paramType = TypeNode(c) elif c.name == 'ID': paramName = c.lex - self.params[paramName] = paramType - self.paramTypes += paramType[1] + "," + self.params.append(paramName, paramType) + self.paramTypes += paramType.name + "," nameNodes = getParseTreeNodes(['type', 'VOID'], parseTree, ['methodBody', 'params']) for n in nameNodes: if n.name == 'VOID': - self.isPrimType = True - self.methodType = n.lex + self.methodType = TypeNode('VOID') else: - self.isPrimType, self.methodType = getTypeName(n) + self.methodType = TypeNode(n) for node in parseTree.children: if node.name == 'methodMod': @@ -96,8 +93,8 @@ class MethodNode(ASTNode): def buildEnv(self, parentEnv): env = Env(parentEnv) i = 0 - for k, v in self.params: - key = (k, 'expr') + for p in self.params: + key = (p[0], 'expr') if key in env.map: raise Exception('ERROR: Declaration of {} is already in current Environment'.format(node.name)) env.map[key] = (True, i) diff --git a/UnitNodes.py b/UnitNodes.py index 8b13789..2514144 100644 --- a/UnitNodes.py +++ b/UnitNodes.py @@ -1 +1,61 @@ +from AST import ASTNode, getParseTreeNodes +from Environment import Env +# LiteralNode +# TypeNode +# param + + +################################################################################# +# 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 + + +################################################################################## +# type: primitiveType, ArrayType, RefType +class TypeNode(ASTNode): + # always list all fields in the init method to show the class structure + def __init__(self, parseTree): + self.parseTree = parseTree + self.name = '' + self.isArray = False + self.isPrimitive = False + self.env = None + self.children = [] + + if parseTree == 'VOID': + self.name = 'void' + self.isPrimitive = True + else: + nameNodes = getParseTreeNodes(['BOOLEAN', 'BYTE', 'CHAR', 'INT', 'SHORT'], parseTree) + if nameNodes: + self.isPrimType = True + else: + self.name = getParseTreeNodes(['ID', 'COMPID'], parseTree)[0].lex + + nameNodes = getParseTreeNodes(['LSQRBRACK'], parseTree) + if nameNodes: + self.isArray = True -- GitLab