class Parser(): def __init__(self, fn): self.token = Token(fn) self.token.nextToken()
class Parser: def __init__(self, fn, isdebug = 0): self.isdebug = isdebug # 0은 디버깅하지 않겠다는 의미 self.basename = fn[:fn.rfind('.')] self.directive = [] self.token = Token(fn) self.token.nextToken() # Root Symbol Table 등록 self.globalSymbolTable = self.initSymbolTable() self.localSymbolTable = [] # function이나 class앞의 template이나 attribute같은 것들의 정보를 가지고 있는... self.directive = [] # 아무것도 없으면 Root임 self.namespaceStack = [] self.loadedSymbolList = [] self.mustcompile = [] def initSymbolTable(self): symtbl = SymbolTable() symtbl.register({'@type':'namespace','@name':"System"}) symtbl.register({'@type':'namespace','@name':"System.lang"}) symtbl.register({'@type':'namespace','@name':"System.out"}) namespaceObject = "System.lang.Object" namespaceByte = "System.lang.Byte" namespaceChar = "System.lang.Char" namespaceShort = "System.lang.Short" namespaceInt = "System.lang.Integer" namespaceLong = "System.lang.Long" namespaceFloat = "System.lang.Float" namespaceDouble = "System.lang.Double" namespaceString = "System.lang.String" namespaceBoolean = "System.lang.Boolean" namespaceArray = "System.lang.Array" # System.lang.Object symtbl.register({'@type':'class','@name':namespaceObject}) symtbl.register({'@type':'class','@name':namespaceByte}) symtbl.register({'@type':'class','@name':namespaceChar}) symtbl.register({'@type':'class','@name':namespaceShort}) symtbl.register({'@type':'class','@name':namespaceInt}) symtbl.register({ '@type':'native def', '@name':namespaceInt + '.=', '@args':[ASTType(namespaceInt)], '@vtype':ASTType(namespaceInt), '@method':lambda se,dst: ASTNativeMove(se, dst)}) symtbl.register({ '@type':'native def', '@name':'+', '@args':[ASTType(namespaceInt), ASTType(namespaceInt)], '@vtype':ASTType(namespaceInt), '@method':lambda src1,src2: ASTNativeAdd(src1, src2)}) symtbl.register({ '@type':'native def', '@name':'+=', '@args':[ASTType(namespaceInt), ASTType(namespaceInt)], '@vtype':ASTType(namespaceInt), '@method':lambda se,dst: ASTNativeMove(se, ASTNativeAdd(src, dst))}) symtbl.register({'@type':'class','@name':namespaceLong}) symtbl.register({'@type':'class','@name':namespaceFloat}) symtbl.register({'@type':'class','@name':namespaceDouble}) symtbl.register({'@type':'class','@name':namespaceString}) symtbl.register({'@type':'class','@name':namespaceBoolean}) symtbl.register({'@type':'class','@name':namespaceArray}) symtbl.register({ '@type':'def', '@name':"System.lang.Array.length", '@args':None, '@vtype':ASTType(name="System.lang.Integer", templ = None, ranks = None)}) symtbl.register({ '@type':'def', '@name':"System.lang.Array.toRange", '@args':None, '@vtype':ASTType(name="System.lang.Array", templ = None, ranks = None)}) symtbl.register({ '@type':'def', '@name':"System.lang.Array.getNext", '@args':None, '@vtype':ASTType(name="System.lang.Integer", templ = None, ranks = None)}) symtbl.register({ '@type':'def', '@name':"System.lang.Array.end", '@args':None, '@vtype':ASTType(name="System.lang.Boolean", templ = None, ranks = None)}) symtbl.register({'@type':'alias', '@name':"object", '@fullname':namespaceObject}) symtbl.register({'@type':'alias', '@name':"byte", '@fullname':namespaceByte}) symtbl.register({'@type':'alias', '@name':"short", '@fullname':namespaceShort}) symtbl.register({'@type':'alias', '@name':"int", '@fullname':namespaceInt}) symtbl.register({'@type':'alias', '@name':"float", '@fullname':namespaceFloat}) symtbl.register({'@type':'alias', '@name':"double", '@fullname':namespaceDouble}) symtbl.register({'@type':'alias', '@name':"string", '@fullname':namespaceString}) symtbl.register({'@type':'alias', '@name':'bool', '@fullname':namespaceBoolean}) symtbl.register({'@type':'alias', '@name':"string", '@fullname':namespaceString}) symtbl.register({ '@type':'def', '@name':'System.out.println', '@args':[ASTType(name=namespaceString, templ = None, ranks = None)], '@vtype':ASTType(name="void", templ = None, ranks = None)}) return symtbl def nextToken(self): self.token.nextToken() def match(self, word): return self.token.match(word) def same(self, word): return self.token.same(word) def matchType(self, word): return self.token.matchType(word) def sameType(self, word): return self.token.sameType(word) def isEnd(self): return self.token.reachEnd() def getTokValue(self): return self.token.tok.value def getTokType(self): return self.token.tok.type def getName(self): if self.match('_'): return '_' return self.token.matchType('id') def getNames(self): names = [] while not self.isEnd(): names.append(self.getName()) if not self.match('.'): break return ".".join(names) def parse(self): if self.isdebug == 1: print "entering parse" parsingList = [] while not self.isEnd(): tree = None if self.same('namespace'): self.parseNamespace() elif self.same('class'): self.parseClass() raise Exception("parse", "class") elif self.same('template'): result = self.parseTemplate() self.directive.append(result) elif self.same('@'): result = self.parseAttribute() self.directive.append(result) elif self.same('def'): self.parseDef() elif self.same('native'): # 예는 push로.. self.directive.append('native') pass else: break if self.isdebug == 1: print "ending parse" def parseNamespace(self): if not self.match('namespace'): return path = self.getNames() self.namespaceStack.append(path) self.loadedSymbolList.append(set([])) self.parseNamespaceBody() self.loadedSymbolList.pop() self.namespaceStack.pop() # symbol search할때도 사용할예정 def getWorkingPath(self): return ".".join(self.namespaceStack) def parseNamespaceBody(self): if not self.match('{'): return self.parse() self.match('}') def parseClass(self): if not self.match('class'): return names = self.getNames() classname = ".".join(self.namespaceStack + [names]) # 검색 symbol list에 등록만 해놓는다. # 정의가 안되어 있다가 나중에 사용되면 실제 symbol table에 body가 없으므로, # body가 없다고 에러를 내면 된다. # self.loadedSymbolList와 self.namespaceStack은 단지 symbol을 만들때와 symbol참조를 위해서만 쓰인다. self.loadedSymbolList[-1] |= set([classname]) if self.match(';'): return self.namespaceStack.push(name) body = self.parseClassBody() self.namespaceStack.pop() symtbl = self.getRecentSymbolTable() # class의 body는 variable만 있어야 한다. # class의 method들은 symbol로 등록될 것 이다. symtbl.registerSymbol({"@type": "class", "@name": classname, "@attribute": None, "@body": body}) def parseClassBody(self): if not self.match('{'): return body = {} while not self.match('}'): if self.match('val'): # 상수선언 name = self.getName() if body.has_key(name): print "Error) duplicated name :", name raise NameError content = {"@type": "val", "@vtype": ASTType("System.lang.Integer")} if self.match(':'): content['@vtype'] = self.parseType() if self.match('='): content['@init'] = self.parseInitExpr() body[name] = content elif self.match('var'): # 변수선언 name = self.getName() if body.has_key(name): print "Error) duplicated name :", name raise NameError content = {"@type": "var", "@vtype": ASTType("System.lang.Integer")} if self.match(':'): content['@vtype'] = self.parseType() if self.match('='): content['@init'] = self.parseInitExpr() body[name] = content elif self.match('def'): # 함수 name = self.getName() # 인자까지 봐야지 중복인지를 체크할 수 있음 content = {"@type": "def"} if self.match('('): args = self.parseDefArgsList() if not self.match(')'): print "Error) Needed ')'" raise SyntaxError content['@args'] = args if self.match(':'): # return type type = self.parseType() content['@vtype'] = type else: content['@vtype'] = None # return이 없음을 의미 (c의 void) if self.match('='): defbody = self.parseExpr() content['@body'] = defbody elif self.match('{'): defbody = self.parseExprs() if not self.match('}'): print "Error) Needed '}'" raise SyntaxError content['@body'] = defbody else: print "Error) Needed Body" raise SyntaxError # 함수이름을 native symbol로 변경 realn = convertToNativeSymbol(name, content['@args'], content['@vtype']) # TODO : Auto Casting은 일단 지원하지 않는다. if body.has_key(realn): print "Error) Multiple declaration :", fname raise SyntaxError body[realn] = content return body def parseInitExpr(self): # 여긴 상수나 간단한 계산하는 루틴정도? # 아님 배열 raise NotImplementedError def parseAttribute(self): if not self.match('@'): return pass def parseTemplate(self): if not self.match('template'): return None params = self.parseTemplateArguments() if params == None: print "Error) Needs some template parameters" return for param in params: sym.registerTemplateVariable(param.name, param.type) if self.same('class'): target = self.parseClass() elif self.same('def'): target = self.parseDef() self.globalSymbolTable.register({ "@type": 'template def', "@name": target['name'], "@vtype": target['rettype'], "@body": target['body'], "@template args": params}) # TODO : 그리고 먼가 파일로 만드는 코드 추가 else: print "Error) Dont use template in this type" raise Exception("parseTemplate", "wrong type") self.pop() return ASTTemplate(params, target) def parseTemplateArguments(self): if not self.match('<'): return None # 선언할때는 function argument처럼 args = [self.parseTemplateArgument()] while self.match(','): args.append(self.parseTemplateArgument()) if not self.match('>'): return None return args def parseTemplateArgument(self): name = self.getName() type = "typename" # 일단 임시로 if self.match(':'): type = self.getNames() return ASTTemplateArg(name, type) # 함수 선언 형태 # def func(argname1: argtype1, argname2: argtype2, ...) = expr # def func(argname1: argtype1, argname2: argtype2, ...) { exprs } # def func(argname1: argtype1, argname2: argtype2, ...):rettype = expr # def func(argname1: argtype1, argname2: argtype2, ...):rettype { exprs } # 변수 선언 : (Scala처럼 구분하지 않는게 좋을듯) # def variableName; // 이럴 경우 정수형으로 가정 # def variableName:variableType; # def variableName = <initial expr>; // 이거랑 # def variableName:variableType = <initial expr>; // 이거는 함수취급 def makeFullPath(self, fn): return ".".join(self.namespaceStack + [fn]) def parseDefBody(self): if self.isdebug == 1: print "entering parseDefBody" body = None if self.isdebug == 1: print "getTokValue : %s" % (self.getTokValue()) if self.match('='): body = self.parseExpr() elif self.match('{'): body = self.parseExprs() self.match('}') if self.isdebug == 1: print "ending parseDefBody" return body def parseDef(self): if not self.match('def'): return None if self.isdebug == 1: print "entering parseDef" # 이름을 얻습니다. only = self.getNames() fn = ".".join(self.namespaceStack + [only]) #print "Function name : %s" % (fn) # 함수용 local symbol table을 만듭니다. self.localSymbolTable = [{}] # argument가 나오는지 검사합니다. args = self.parseDefArgsList() # check localSymTbl = self.localSymbolTable[-1] for arg in args: if localSymTbl.has_key(arg.name): print "Error) Duplicated Name" raise SyntaxError if not self.globalSymbolTable.findType(arg.type.name): print "Error) Unknown Type" raise SyntaxError localSymTbl[arg.name] = arg.type nativeSymbol = mangling(fn, args) if self.globalSymbolTable.find({'@type': 'def', '@name': fn, '@args': args}): print "Error) Duplicated Name" raise Exception("Error", "Error") #localSymTbl.printDoc() # To parse return type rettype = self.parseReturnType() # To parse body of function body = self.parseDefBody() if body == None: print "Error) Body Empty : in %s" % (nativeSymbol) raise Exception("Error", "Error") if rettype != 'void': if isinstance(body, ASTExprs) or isinstance(body, ASTSimpleExprs): # return을 명시적으로 적지 않았다면, 마지막 expression의 결과를 return값으로 한다. lastExpr = body.exprs[-1] if not isinstance(lastExpr, ASTReturn): body.exprs[-1] = ASTReturn(lastExpr) else: # isinstance(body, ASTExpr): body = ASTExpr(ASTReturn(body)) print "&&=", type(rettype) print "**=", body # 바로전에 template이 선언되었다면 여기도 영향을 받아야만 한다. # 일단 지금은 영향을 받지 않는다고 가정한다. self.globalSymbolTable.register({ "@type": "def", "@name": fn, "@args": args, "@vtype": rettype, "@body": body, "@symbols": self.localSymbolTable}) self.localSymbolTable = [{}] #print "1", nativeSymbol, self.globalSymbolTable[nativeSymbol] self.mustcompile.append((self.globalSymbolTable[nativeSymbol], nativeSymbol)) if self.isdebug == 1: print "ending parseDef" def parseDefArgsList(self): if not self.match('('): return None args = [] while not self.isEnd(): arg = self.parseDefArg() if arg == None: break args.append(arg) if not self.match(','): break if not self.match(')'): print "Error) Needed ')'" return None return args def parseReturnType(self): # if return type is none, if not self.match(':'): return ASTType(name = "System.lang.Integer", templ = None, ranks = None) return self.parseType() def parseDefArg(self): name = self.getName() if name == None: return None typeStr = ASTType(name = "System.lang.Integer", templ = None, ranks = None) if self.match(':'): typeStr = self.parseType() defval = None if self.match('='): defval = self.parseBasicSimpleExpr() # if typeStr == None: makeError return ASTDefArg(name = name, type = typeStr, defval = defval) def parseTemplatePart(self): #raise Exception('parseTemplatePart', 'Not Implemented') return None def matchTemplateInfo(self, typeInfo, templateInfo): #raise Exception('matchTemplateInfo', 'Not Implemented') return True def parseType(self): #if self.isdebug == 1: print "starting parseType" idStr = self.getNames() if self.isdebug == 1: print ".".join(idStr) # 해당 type이 존재하는지 검사합니다. tp = self.globalSymbolTable.findType(idStr) if tp == None: print "Unknown Type : %s" % (idStr) sys.exit(-1) if tp == 'alias': idStr = self.globalSymbolTable.find(idStr) #print "(", idStr #tmpl = self.parseTemplatePart() #if not self.matchTemplateInfo(result, tmpl): # # 일단 현재는 pass # print "Error) Not matched template information" # pass #print "type's full name = %s" % (idStr) #tmpl = self.parseTemplatePart() #ename, body = symbolTable.search(names.array) #if ename == None: # print "doesn't exist symbol : %s" % (".".join(names.array)) # sys.exit(-1) # 일단 죽이고... 나중에 에러처리 생각 #else: # names.array = ename rank = self.parseRankList() if self.isdebug == 1: print "ending parseType" return ASTType(name = idStr, templ = None, ranks = rank) def parseRankList(self): lst = [] while self.match('['): rank = ASTRank(self.parseSimpleExpr()) lst.append(rank) if not self.match(']'): print "Error) Need ']'" return ASTRankList(lst) def parseExprs(self): lst = [] while not self.isEnd(): ret = self.parseExpr() if ret == None: break if isinstance(ret, ASTExprs): lst += ret.exprs elif isinstance(ret, list): lst += ret else: # ?? lst.append(ret) if len(lst) == 0: return None return ASTExprs(lst) def parseExpr(self): ret = None if self.same('if'): ret = self.parseIfStmt() elif self.same('for'): ret = self.parseForStmt() elif self.same('var'): ret = self.parseVar() elif self.same('val'): ret = self.parseVal() elif self.same('{'): ret = self.parseBlockExprs() else: ret = self.parseSimpleExpr1() #print "***",ret self.match(';') #s = raw_input() return ret def parseIfStmt(self): if not self.match('if'): return None cond = self.parseExpr() self.match(':') body = self.parseExpr() return ASTIf(cond, body) def parseForStmt(self): if not self.match('for'): return None cond = self.parseBasicSimpleExpr() if cond == None: print "Error) Needed to identifier" raise SyntaxError if not self.match('<='): print "Error) Needed to <=" raise SyntaxError generator = self.parseSimpleExpr() if generator == None: print "Error) Needed generator" raise SyntaxError body = None if self.match(':'): body = self.parseExpr() elif self.match('{'): body = self.parseExprs() self.match('}') else: print "Error) Needed '{' '}' or '='" raise NotImplementedError return ASTFor(cond, generator, body) def convertToASTType(self, obj): if isinstance(obj, ASTType): return obj elif isinstance(obj, ASTListGenerateType1): return self.convertToASTType(obj.start) elif isinstance(obj, ASTWord) and obj.vtype != None: if isinstance(obj.vtype, ASTType): return obj.vtype # 이건 비정상적인 경우, 이렇게 찾아들어오면 안된다. elif isinstance(obj.vtype, dict): return obj.vtype['@vtype'] else: print "))", obj.vtype raise NotImplementedError elif isinstance(obj, ASTWord) and isinstance(obj.type, ASTType): return obj.type elif isinstance(obj, ASTListGenerateType1): return ASTType('System.lang.Array') elif isinstance(obj, ASTCalleeArgType1): return self.convertToASTType(obj.type) else: print "**", obj raise NotImplementedError def parseVar(self): if not self.match('var'): return None sym = self.localSymbolTable[-1] hist = [] while True: name = self.getName() if sym.has_key(name): print "has duplicated name" raise Exception('Error', 'Duplicated Name') return None type = None if self.match(':'): type = self.parseType() else: type = ASTType(name = 'System.lang.Integer', templ = None, ranks = None) #print "name =", name # 변수 초기화 tree = None if self.match('='): right = self.parseSimpleExpr() query = {"@name": '=', '@type': 'def'} query['@args'] = [type, self.convertToASTType(right)] symbol = self.globalSymbolTable.find(query) #print "2", symbol tree = ASTOperator(ASTWord('id', '='), ASTWord('id', name, type), right) hist.append(tree) sym[name] = {"@type": "var", "@vtype": type} if not self.match(','): break self.match(';') return hist def parseVal(self): if not self.match('val'): return None sym = self.localSymbolTable[-1] hist = [] while True: name = self.getName() if sym.has_key(name): print "has duplicated name" raise Exception('Error', 'Duplicated Name') return None type = None if self.match(':'): type = self.parseType() else: type = ASTType(name = 'System.lang.Integer', templ = None, ranks = None) #print "name =", name # 변수 초기화 tree = None if self.match('='): right = self.parseSimpleExpr() query = {"@name": '=', '@type': 'def'} query['@args'] = [type, self.convertToASTType(right)] symbol = self.globalSymbolTable.find(query) print "3", symbol tree = ASTOperator(ASTWord('id', '='), ASTWord('id', name, type), right) hist.append(tree) sym[name] = {"@type": "var", "@vtype": type} if not self.match(','): break self.match(';') return hist def parseBlockExprs(self): return None def parseSimpleExpr1(self): ret = self.parseSimpleExprs() # not yet! #if self.match('?'): # body = self.parseMatchingCases() # ret = ASTPatternMatch(cond = ret, body = body) return ret def parseSimpleExprs(self): history = [] while not self.isEnd(): tree = self.parseSimpleExpr() if tree == None: break if self.match(','): hist = [tree] while self.match(','): tree = self.parseSimpleExpr() hist.append(tree) tree = ASTSet(hist) history.append(tree) nhist = len(history) print "nhist = ", nhist if nhist == 0: return None elif nhist == 1: return history[0] #self.match(';') # caution!! return ASTSimpleExprs(history) def parseSimpleExpr(self): if self.isdebug == 1: print "entering parseSimpleExpr()" tree = self.parseBasicSimpleExpr() if tree == None: return None while not self.isEnd(): if self.isdebug == 1: print self.getTokValue() if self.match('.'): right = self.parseBasicSimpleExpr() if isinstance(tree, ASTWord): if isinstance(right, ASTWord): tree = ASTNames([tree.value, right.value]) elif isinstance(right, ASTFuncCall): tree = ASTFuncCall(ASTNames([tree.value, right.name.value]), right.body) elif isinstance(right, ASTIndexing): tree = ASTIndexing(ASTNames([tree.value, right.name.value]), right.history) elif isinstance(tree, ASTNames): if isinstance(right, ASTWord): tree = ASTNames(tree.array + [right.value]) elif isinstance(right, ASTFuncCall): tree = ASTFuncCall(ASTNames(tree.array + [right.name.value]), right.args) elif isinstance(right, ASTIndexing): tree = ASTIndexing(ASTNames(tree.array + [right.name.value]), right.history) else: tok = self.token.tok # Global Operator 함수로 첫번째 찾는다. (C++의 operator + (left, right)라는 식..) content = {'@type': 'def', '@name': tok.value} content['@args'] = [self.convertToASTType(tree), self.convertToASTType(right)] symbol = self.globalSymbolTable.find(content) if symbol == None: # 없다면, left.type의 operator로 찾는다. (C++의 someclass::operator + (right)...) content = {'@type': 'def', '@name': self.convertToASTType(tree).name + "." + tok.value} content['@args'] = [self.convertToASTType(right)] symbol = self.globalSymbolTable.find(content) print "4", symbol, content if symbol != None: if symbol['@type'] == 'native def': raise NotImplementedError else: tree = ASTFuncCall(content['@name'], tree, right) elif symbol == None: tree = ASTOperator(ASTWord(tok.type, tok.value), tree, right) # array elif self.sameType('id'): #if isinstance(tree, ASTSet): # #if len(tree.lst) != 1: # # print "error!!" # make error!! # if self.checktype(tree.lst[0]): # tree = ASTCasting(tree.lst[0], ASTWord(tok.type, tok.value)) tokVal = self.getTokValue() tokType = self.getTokType() mid = ASTWord(tokType, tokVal) self.token.nextToken() right = self.parseBasicSimpleExpr() #print "here : ", mid, tree, right if right != None: content = {'@type': 'def', '@name': tokVal} content['@args'] = [self.convertToASTType(tree), self.convertToASTType(right)] symbol = self.globalSymbolTable.find(content) if symbol == None: # 없다면, left.type의 operator로 찾는다. (C++의 someclass::operator + (right)...) content = {'@type': 'def', '@name': self.convertToASTType(tree).name + "." + tokVal} content['@args'] = [self.convertToASTType(right)] symbol = self.globalSymbolTable.find(content) if symbol != None: if symbol['@type'] == 'native def': raise NotImplementedError else: tree = ASTFuncCall(content['@name'], [tree, right]) else: tree = ASTOperator(mid, tree, right) else: # for example, 'a++' or 'a+' tree = ASTUnary(tree, mid) else: break if isinstance(tree, ASTFuncCall): candidates = set([]) path = None if isinstance(tree, ASTNames): path = ".".join(tree.array) elif isinstance(tree.name, ASTNames): path = ".".join(tree.name.array) else: path = tree.name ret = self.globalSymbolTable.find({'@type':'def', '@name':path, '@args':map(lambda x: self.convertToASTType(x), tree.args)}) if ret == None: print "Error) Not Symbol :", path, map(lambda x: self.convertToASTType(x), tree.args) raise SyntaxError if self.isdebug == 1: print "ending parseSimpleExpr()" return tree def parseBasicSimpleExpr(self): tok = self.token.tok if tok == None: return None #print "calling parseBasicSimpleExpr" #print "value =", tok.value, tok.type if self.matchType('stringLiteral'): return ASTWord(ASTType('System.lang.String'), tok.value) elif self.matchType('integerLiteral'): return ASTWord(ASTType('System.lang.Integer'), tok.value) elif self.matchType('floatLiteral'): return ASTWord(ASTType('System.lang.Float'), tok.value) elif self.match('true'): return ASTWord(ASTType('System.lang.Boolean'), '1') elif self.match('false'): return ASTWord(ASTType('System.lang.Boolean'), '0') elif self.match('return'): #print "entering return" expr = self.parseSimpleExpr() #print "@@", expr return ASTReturn(expr) #elif self.match('def'): # ret = self.parseDefInnerFunc() #if len(ret.name) != 1: # print "don't use namespace!" # sys.exit(-1) #realname = ret.name[0] #if realname == '_': # realname = self.genTemporaryName() #if self.findAt(tbl = self.local_symtbl, target = ret.name): # print "already defined!" # sys.exit(-1) #typename = convertType(ret.ret) #if not self.validateType(typename): # print "not declare type" # sys.exit(-1) #self.local_symtbl[realname] = { # "attribute": ["lambda"], # "args": ret.args, # "type": typename, # "body": ret.body} #return ret elif self.matchType('id'): if self.same('['): history = [] while self.match('['): history.append(self.parseSimpleExpr()) self.match(']') return ASTIndexing(ASTWord(tok.type, tok.value), history) elif self.match('('): # TODO 함수의 그것인지 아닌지에 대한 구분이 필요하다. args = self.parseDefArgListForFuncCall() if not self.match(')'): print "Error) Need ')'" # TODO: 호출하려는 function에 대한 정보를 얻어서 입력된 argument들의 type과 비교하여, # 현재 symbol table에 호출할 수 있는 function이 있는지를 찾는 코드가 있어야 한다. # 몇번의 try가 필요할지도...(auto casting때문에...) # 예를 들어, 호출하려는 함수의 인자중에 char*를 갖는데, 해당 함수의 인자에는 char*를 사용하지 않고 System.lang.String만 사용하는 경우는 # 자동으로 char*를 String으로 auto casting해주어야 한다. # 그 반대의 경우는 String을 char*로 casting해주어야 한다. # 단, 해당 class에 해당 변환을 지원해준다는 가정이 필요하다.(즉, 해당 casting을 지원해주는지 여부를 체크해야만 한다.) # 알고리즘 # 1. 현재의 argument들의 type들로 구성된 function을 찾는다. # 2. 만일 없다면, argument들의 갯수가 동일한 함수.... (이건 내일 생각) return ASTFuncCall(ASTWord(tok.type, tok.value), args) elif self.match('...'): right = self.parseSimpleExpr() return ASTListGenerateType1(ASTWord(tok.type, tok.value), right) # 여기서 빠진 것은 Arrya<T이어야 한다는 사실(Type이 빠졌다는 소리) else: vtype = None for symbolTable in reversed(self.localSymbolTable): if symbolTable.has_key(tok.value): vtype = symbolTable[tok.value] break if vtype == None: vtype = self.globalSymbolTable.findType(tok.value) return ASTWord(tok.type, tok.value, vtype) elif self.match('_'): return ASTWord('v', tok.value) elif self.match('['): history = [] tree = self.parseSimpleExpr() if self.match('...'): right = self.parseSimpleExpr() self.match(']') return ASTListGenerateType1(tree, right) elif self.match(','): history.append(tree) while self.match(','): item = self.parseSimpleExpr() history.append(item) self.match(']') return ASTListValue(history) self.match(']') return ASTListValue([tree]) elif self.match('('): tree = self.parseSimpleExpr1() self.match(')') return ASTWrap(tree) #else: # print tok # raise Exception("parseBasicSimpleExpr", "Not implemented") return None def parseDefArgListForFuncCall(self): args = [] while True: arg = self.parseSimpleExpr() if isinstance(arg, ASTWord): if arg.type == 'id': symtbl = self.localSymbolTable[-1] if not symtbl.has_key(arg.value): print "Error) Not found :", arg.value raise SyntaxError args.append(ASTCalleeArgType1(value = arg, type = symtbl[arg.value])) else: args.append(ASTCalleeArgType1(value = arg, type = arg.type)) else: print arg raise NotImplementedError if not self.match(','): break return args