class Test_myStack(unittest.TestCase): def setUp(self): self.testStack = MyStack() def test_pop_emptyStackCase(self): with self.assertRaises(StackEmptyException): self.testStack.pop() def test_pop_done(self): self.testStack.push('abc') self.testStack.push('xyz') self.testStack.push('123') self.testStack.pop() self.assertEqual(self.testStack.data, ['abc', 'xyz']) def test_peek(self): with self.assertRaises(StackEmptyException): self.testStack.peek() def test_push_typeErrorCase(self): with self.assertRaises(TypeError): self.testStack.push(10) def test_push_done(self): self.testStack.push('abc') self.testStack.push('xyz') self.testStack.push('123') self.testStack.push('456') self.assertEqual(self.testStack.data, ['abc', 'xyz', '123', '456']) def test_contain(self): self.testStack.push('abc') self.assertTrue(self.testStack.contains('abc'), 'Must be True')
def is_balanced(exp): stack = MyStack() parenthese = {'}': '{', ']': '[', ')': '('} for c in exp: if c in parenthese and not stack.is_empty() \ and stack.top() == parenthese[c]: stack.pop() else: stack.push(c) return stack.is_empty()
def evaluate_post_fix(exp): stack = MyStack() operators = ['+', '-', '*', '/'] for i in exp: if i.isdigit(): stack.push(int(i)) elif i in operators: operand1 = stack.pop() operand2 = stack.pop() res = operate(operand2, operand1, i) stack.push(res) return stack.pop()
def next_greater_element(lst): res = [-1 for x in lst] stack = MyStack() for i in range(len(lst) - 1, -1, -1): while not stack.is_empty() and stack.top() <= lst[i]: stack.pop() if not stack.is_empty(): res[i] = stack.top() stack.push(lst[i]) return res
def evaluate_post_fix(exp): ops = ["+", "*", "-", "/"] stack = MyStack() for el in exp: if el == " ": continue elif el in ops: v1, v2 = stack.pop(), stack.pop() res = eval(f"{v2} {el} {v1}") stack.push(res) else: stack.push(el) final_num = int(stack.pop()) return final_num
def next_greater_element(lst): stack = MyStack() res = [None] * len(lst) for i in range(len(lst) - 1, -1, -1): # iterate backwards while not stack.is_empty() and stack.peek() <= lst[i]: stack.pop() if not stack.is_empty(): # use the top element as nge if available res[i] = stack.peek() else: res[i] = -1 stack.push(lst[i]) return res
def sort_stack(stack): temp_stack = MyStack() while not stack.is_empty(): value = stack.pop() # if value is not none and larger, push it at the top of temp_stack if temp_stack.peek() is not None and value >= temp_stack.peek(): temp_stack.push(value) else: while not temp_stack.is_empty(): stack.push(temp_stack.pop()) # place value as the smallest element in temp_stack temp_stack.push(value) # Transfer from temp_stack => stack while not temp_stack.is_empty(): stack.push(temp_stack.pop()) return stack
def sort_stack(stack): sub_stack = MyStack() if stack.is_empty(): return stack while not stack.is_empty(): if sub_stack.is_empty() or stack.top() >= sub_stack.top(): sub_stack.push(stack.pop()) continue val = stack.pop() while not sub_stack.is_empty(): stack.push(sub_stack.pop()) sub_stack.push(val) while not sub_stack.is_empty(): stack.push(sub_stack.pop()) return stack
def reverse_queue(queue, k): stack = MyStack() if k > queue.size() or k <= 0: return None lst_reverse = queue.queue_list[0:k] stack.stack_list = lst_reverse result = [] for i in range(stack.size()): result.append(stack.pop()) return result + queue.queue_list[k:]
def is_balanced(exp): if len(exp) == 0: return True stack = MyStack() braces = {"{": "}", "[": "]", "(": ")"} for ch in exp: if ch in braces: stack.push(ch) else: # closers if braces[stack.pop()] != ch: return False return True
class MinStack: # Constructor def __init__(self): self.main_stack = MyStack() self.min_stack = MyStack() def pop(self): if self.main_stack.is_empty(): return -1 self.min_stack.pop() return self.main_stack.pop() def push(self, value): self.main_stack.push(value) if self.min_stack.is_empty() or self.min_stack.top() > value: self.min_stack.push(value) else: self.min_stack.push(self.min_stack.top()) def min(self): if not self.min_stack.is_empty(): return self.min_stack.top()
def reverseK(queue, k): if k > queue.size() or k < 0 or queue.is_empty(): return None stack = MyStack() for i in range(k): stack.push(queue.dequeue()) for i in range(k): queue.enqueue(stack.pop()) for i in range(queue.size() - k): queue.enqueue(queue.dequeue()) return queue
def dfs(g, vertex): num_of_vertices = g.vertices vertices_reached = 0 visited = [False for _ in range(num_of_vertices)] visited[vertex] = True stack = MyStack() stack.push(vertex) while not stack.is_empty(): current_node = stack.pop() temp = g.array[current_node].head_node while temp is not None: if not visited[temp.data]: stack.push(temp.data) visited[temp.data] = True vertices_reached += 1 temp = temp.next_element return vertices_reached + 1
def reverseK(queue, k): if k > queue.size() or k < 0 or queue.is_empty(): return None stack = MyStack() new_q = MyQueue() for i in range(k): v = queue.dequeue() stack.push(v) while not stack.is_empty(): v = stack.pop() new_q.enqueue(v) while not queue.is_empty(): v = queue.dequeue() new_q.enqueue(v) return new_q
def analyze(self): self.ERROR = False self.head = node() self.head.setData('head') stack = MyStack() self.lex = LexAn(self.string) endNode = node() endNode.setData('#') stack.push(endNode) startNode = node() startNode.setData(self.start) startNode.setParent(self.head) self.head.addChildren(startNode) stack.push(startNode) self.pointer = 0 self.lineCounter = 1 word, label, now = self.advance() outResult = '' ErrorResult = '' while (True): '''遇注释号跳过''' if label == '注释号': word, label, now = self.advance() continue '''文件读完,未完成语法分析''' if word == -1: ErrorResult += ('line %d:' % self.lineCounter + ' 语法分析错误结束\n') outResult += '\n' break '''遇非法字符''' if label == 'ERROR': ErrorResult += ('line %d:' % self.lineCounter + ' 跳过非法词%s\n' % word) outResult += '\n' word, label, now = self.advance() continue out = ('line %d: ' % self.lineCounter + word + ',' + label) outResult = outResult + out.ljust(20, ' ') proResult = False topNode = stack.pop() X = topNode.data if X in self.Terminals: if X == now: if X == "标识符": topNode.addAttributes("idName", word) if X == "num": topNode.addAttributes("NumValue", word) topNode.addAttributes("lineNum", self.lineCounter) word, label, now = self.advance() else: ErrorResult += ('line %d:' % self.lineCounter + ' 期待%s\n' % (X)) outResult += '\n' continue elif X == '#': if X == now: break else: ErrorResult += ('line %d:' % self.lineCounter + ' 检查%s附近\n' % (word)) outResult += '\n' break elif X in self.Virables and self.Table.table[X][now] not in [ ' ', 'synch' ]: if self.Table.table[X][now].right == ['NULL']: newNode = node() newNode.setParent(topNode) newNode.setData('NULL') topNode.addChildren(newNode) pass else: k = len(self.Table.table[X][now].right) - 1 while (k >= 0): newNode = node() newNode.setParent(topNode) newNode.setData(self.Table.table[X][now].right[k]) topNode.addChildren(newNode) stack.push(newNode) k -= 1 topNode.reverseChildren() out = ('产生式: ' + self.Table.table[X][now].left + '-->' + ' '.join(self.Table.table[X][now].right)) outResult += out.ljust(40, ' ') proResult = True else: if len(stack.s) == 1 or self.Table.table[X][now] == ' ': newNode = node() newNode.setData(X) stack.push(newNode) ErrorResult += ('line %d:' % self.lineCounter + ' 跳过%s, 检查%s附近\n' % (word, word)) word, label, now = self.advance() if word == -1: ErrorResult += ('line %d:' % self.lineCounter + ' 语法分析错误结束\n') outResult += '\n' break elif self.Table.table[X][now] == 'synch': ErrorResult += ('line %d:' % self.lineCounter + ' %s出栈, 检查%s附近\n' % (X, word)) outResult += '\n' continue if not proResult: outResult += ' '.ljust(40) outResult += (('栈: ' + stack.show()).ljust(40) + '\n') if ErrorResult == '': return ErrorResult, outResult else: self.ERROR = True return ErrorResult, outResult
def analyze(self): self.ERROR = False self.head = node() self.head.setData('head') stack = MyStack() self.lex = LexAn(self.string) endNode = node() endNode.setData('#') stack.push(endNode) startNode = node() startNode.setData(self.start) startNode.setParent(self.head) self.head.addChildren(startNode) stack.push(startNode) self.pointer = 0 self.lineCounter = 1 word, label, now = self.advance() outResult = '' while (True): '''遇注释号跳过''' if label == '注释号': word, label, now = self.advance() continue '''文件读完,未完成语法分析''' if word == -1: self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' no end token #\n') outResult += '\n' break '''遇非法字符''' if label == 'ERROR': self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' skip %s\n' % word) outResult += '\n' break out = ('line %d: ' % self.lineCounter + word + ',' + label) outResult = outResult + out.ljust(20, ' ') proResult = False topNode = stack.pop() X = topNode.data if X in self.Terminals: if X == now: if X == "标识符": topNode.parent.addAttributes('place', word) if topNode.parent.parent.data == '参数': symbol = {} symbol['type'] = topNode.parent.parent.children[ 0].data symbol['idName'] = word symbol['label'] = 'formal' symbol["domain"] = self.domain code = self.genCode(op='pop', result={'reg': self.newTmp()}) symbol['reg'] = code['result']['reg'] self.symbolList.append(symbol) self.funCode[self.domain].append(code) if topNode.parent.parent.data == '内部变量声明': symbol = {} symbol['type'] = topNode.parent.parent.children[ 0].data symbol['idName'] = word symbol['offset'] = self.offset self.offset += 4 symbol['label'] = 'data' symbol['domain'] = self.domain self.symbolList.append(symbol) if X == "num": topNode.parent.addAttributes('place', {'Imme': word}) if X == ';': if topNode.parent.data == '赋值语句': symbolIndex, tag = self.lookUpSymbol( topNode.parent.children[0].attributes['place'], self.domain) if symbolIndex < 0 or (tag != self.domain and tag != "global"): self.errorReason += ( "Line%d: undeclared identifier %s\n" % (self.lineCounter, topNode.parent. children[0].attributes['place'])) break if self.symbolList[symbolIndex][ 'label'] == 'formal': code = self.genCode( op=':=', arg1=topNode.parent.children[2]. attributes['place'], result={ 'reg': self.symbolList[symbolIndex]['reg'] }) elif self.symbolList[symbolIndex][ 'label'] == 'data': code = self.genCode( op=':=', arg1=topNode.parent.children[2]. attributes['place'], result={'symbolIndex': symbolIndex}) self.funCode[self.domain].append(code) elif topNode.parent.data == '返回值': self.haveReturn[self.domain] = True if topNode.parent.children[0].data == '表达式': symbolIndex, _ = self.lookUpSymbol( self.domain, self.domain) if self.symbolList[symbolIndex][ 'type'] == 'void': self.errorReason += 'Line%d: void %s can not have a return value.\n ' % ( self.lineCounter, self.domain) break self.funCode[self.domain].append( self.genCode( op='push', result=topNode.parent.children[0]. attributes['place'])) else: symbolIndex, _ = self.lookUpSymbol( self.domain, self.domain) if self.symbolList[symbolIndex][ 'type'] == 'int': self.errorReason += 'Line%d: int %s has no return value.\n ' % ( self.lineCounter, self.domain) break self.funCode[self.domain].append( self.genCode(op='jr', result='$ra')) self.domain = 'global' if X == ')': if topNode.parent.data == 'if语句': self.funCode[self.domain].append( self.genCode( op='j' + topNode.parent.children[2]. children[1].children[0].children[0].data, arg1=topNode.parent.children[2]. children[0].attributes['place'], arg2=topNode.parent.children[2].children[1] .children[1].attributes['place'], result=2)) self.funCode[self.domain].append( self.genCode(op='j', result=0)) topNode.parent.attributes['false'] = len( self.funCode[self.domain]) - 1 elif topNode.parent.data == 'while语句': self.funCode[self.domain].append( self.genCode( op='j' + topNode.parent.children[2]. children[1].children[0].children[0].data, arg1=topNode.parent.children[2]. children[0].attributes['place'], arg2=topNode.parent.children[2].children[1] .children[1].attributes['place'], result=2)) self.funCode[self.domain].append( self.genCode(op='j', result=0)) topNode.parent.attributes['end'] = len( self.funCode[self.domain]) - 1 elif topNode.parent.data == '因子': topNode.parent.attributes[ 'place'] = topNode.parent.children[ 1].attributes['place'] if X == '}': if topNode.parent.data == '语句块': if topNode.parent.parent.data == 'if语句': self.funCode[self.domain].append( self.genCode(op='j', result=0)) false = topNode.parent.parent.attributes[ 'false'] self.funCode[ self.domain][false]['result'] = len( self.funCode[self.domain]) - false topNode.parent.parent.attributes['end'] = len( self.funCode[self.domain]) - 1 elif topNode.parent.parent.data == 'else语句': end = topNode.parent.parent.parent.attributes[ 'end'] self.funCode[self.domain][end]['result'] = len( self.funCode[self.domain]) - end elif topNode.parent.parent.data == 'while语句': end = topNode.parent.parent.attributes['end'] self.funCode[self.domain].append( self.genCode( op='j', result=end - len(self.funCode[self.domain]) - 1)) self.funCode[self.domain][end]['result'] = len( self.funCode[self.domain]) - end topNode.addAttributes('lineNum', self.lineCounter) word, label, now = self.advance() else: self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' expect %s\n' % (X)) outResult += '\n' break elif X == '#': if X == now: break else: self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' please check near %s\n' % (word)) outResult += '\n' break elif X in self.Virables and self.Table.table[X][now] not in [ ' ', 'synch' ]: if self.Table.table[X][now].right == ['NULL']: newNode = node() newNode.setParent(topNode) newNode.setData('NULL') topNode.addChildren(newNode) else: k = len(self.Table.table[X][now].right) - 1 while (k >= 0): newNode = node() newNode.setParent(topNode) newNode.setData(self.Table.table[X][now].right[k]) topNode.addChildren(newNode) stack.push(newNode) k -= 1 topNode.reverseChildren() if X == '变量声明': symbol = {} symbol['type'] = topNode.parent.parent.children[0].data symbol['idName'] = topNode.parent.parent.children[ 1].attributes['place'] symbol['offset'] = self.offset self.offset += 4 symbol['label'] = 'data' symbol['domain'] = self.domain self.symbolList.append(symbol) elif X == '函数声明' and topNode.parent.data == '声明类型': symbol = {} symbol['type'] = topNode.parent.parent.children[0].data symbol['idName'] = topNode.parent.parent.children[ 1].attributes['place'] self.domain = symbol['idName'] self.funCode[self.domain] = [] symbol['label'] = 'func' symbol['domain'] = self.domain symbol['offset'] = self.offset self.offset += 4 self.haveReturn[self.domain] = False self.symbolList.append(symbol) elif X == '函数声明' and topNode.parent.data == '声明': symbol = {} symbol['type'] = topNode.parent.children[0].data symbol['idName'] = topNode.parent.children[1].attributes[ 'place'] self.domain = symbol['idName'] self.funCode[self.domain] = [] symbol['label'] = 'func' symbol['domain'] = self.domain self.haveReturn[self.domain] = True self.symbolList.append(symbol) if X == '加法表达式': self.tmpAddNodeList.push([]) elif X == '加法表达式1': top = self.tmpAddNodeList.top() top.append(topNode) elif X == '项': self.tmpMulNodeList.push([]) elif X == '项1': top = self.tmpMulNodeList.top() top.append(topNode) if X == '加法表达式1' and topNode.children[0].data == 'NULL': topAddNode = self.tmpAddNodeList.top() self.tmpAddNodeList.pop() if topNode.parent.data == '加法表达式': topNode.parent.attributes[ 'place'] = topNode.parent.children[0].attributes[ 'place'] del topAddNode[-1] for k in range(len(topAddNode)): addNode = topAddNode[len(topAddNode) - k - 1] if addNode.children[0].data == '-': addNode.children[0].data = '减' newTmp = self.newTmp() self.funCode[self.domain].append( self.genCode(op='+', arg1={'reg': 0}, arg2=addNode.children[1]. attributes['place'], result={'reg': newTmp})) self.funCode[self.domain].append( self.genCode(op='uminus', result={'reg': newTmp})) addNode.children[1].attributes['place'] = { 'reg': newTmp } if addNode.parent.children[0].data == '-': addNode.parent.children[0].data = '减' newTmp = self.newTmp() self.funCode[self.domain].append( self.genCode(op='+', arg1={'reg': 0}, arg2=addNode.parent.children[1]. attributes['place'], result={'reg': newTmp})) self.funCode[self.domain].append( self.genCode(op='uminus', result={'reg': newTmp})) addNode.parent.children[1].attributes['place'] = { 'reg': newTmp } newTmp = self.newTmp() if addNode.parent.data == '加法表达式': code = self.genCode( '+', addNode.parent.children[0].attributes['place'], addNode.children[1].attributes['place'], {'reg': newTmp}) addNode.parent.addAttributes( 'place', {'reg': newTmp}) else: code = self.genCode( '+', addNode.parent.children[1].attributes['place'], addNode.children[1].attributes['place'], {'reg': newTmp}) addNode.parent.children[1].addAttributes( 'place', {'reg': newTmp}) self.funCode[self.domain].append(code) elif X == '项1' and topNode.children[0].data == 'NULL': topMulNode = self.tmpMulNodeList.top() self.tmpMulNodeList.pop() if topNode.parent.data == '项': topNode.parent.attributes[ 'place'] = topNode.parent.children[0].attributes[ 'place'] del topMulNode[-1] for k in range(len(topMulNode)): mulNode = topMulNode[len(topMulNode) - k - 1] newTmp = self.newTmp() if mulNode.parent.data == '项': code = self.genCode( mulNode.children[0].data, mulNode.parent.children[0].attributes['place'], mulNode.children[1].attributes['place'], {'reg': newTmp}) mulNode.parent.addAttributes( 'place', {'reg': newTmp}) else: code = self.genCode( mulNode.children[0].data, mulNode.parent.children[1].attributes['place'], mulNode.children[1].attributes['place'], {'reg': newTmp}) mulNode.parent.children[1].addAttributes( 'place', {'reg': newTmp}) self.funCode[self.domain].append(code) elif X == '表达式1' and topNode.children[0].data == 'NULL': if topNode.parent.data != '表达式1': topNode.parent.addAttributes( 'place', topNode.parent.children[0].attributes['place']) if topNode.parent.parent.data == '因子': topNode.parent.parent.addAttributes( 'place', topNode.parent.children[0].attributes['place']) if topNode.parent.parent.data in ['实参列表', '实参列表1']: top = self.tmpParam.top() top.append(topNode.parent.attributes['place']) elif X == 'FTYPE' and topNode.children[0].data == 'NULL': symbolIndex, tag = self.lookUpSymbol( topNode.parent.children[0].attributes['place'], self.domain) if symbolIndex < 0 or (tag != self.domain and tag != "global"): self.errorReason += ( "Line%d: undeclared identifier %s\n" % (self.lineCounter, topNode.parent.children[0].attributes['place'])) break if self.symbolList[symbolIndex]['label'] == 'formal': topNode.parent.addAttributes( 'place', {'reg': self.symbolList[symbolIndex]['reg']}) elif self.symbolList[symbolIndex]['label'] == 'data': topNode.parent.addAttributes( 'place', {'symbolIndex': symbolIndex}) elif X == 'call': symbolIndex, tag = self.lookUpSymbol( topNode.parent.parent.children[0].attributes['place'], self.domain) if symbolIndex < 0: self.errorReason += ( "Line%d: undeclared function %s\n" % (self.lineCounter, topNode.parent.parent. children[0].attributes['place'])) break self.tmpSymbolIndex.push(symbolIndex) self.tmpParam.push([]) self.tmpCallNode.push(topNode.parent.parent) elif X in ['实参列表', '实参列表1' ] and topNode.children[0].data == 'NULL': paramCount = 0 for s in self.symbolList: if s['domain'] == self.symbolList[self.tmpSymbolIndex.top()]['idName'] \ and s['label'] == 'formal': paramCount += 1 topParam = self.tmpParam.top() topSymbolIndex = self.tmpSymbolIndex.top() self.tmpParam.pop() self.tmpSymbolIndex.pop() if paramCount != len(topParam): self.errorReason += ( "Line%d: %s function doesn't accept %d parameters\n" % (self.lineCounter, self.symbolList[topSymbolIndex]['idName'], len(topParam))) break for i in range(len(topParam)): self.funCode[self.domain].append( self.genCode( op='push', result=topParam[len(topParam) - i - 1], )) self.funCode[self.domain].append( self.genCode( op='jal', result='to_%s' % (self.symbolList[topSymbolIndex]['idName']), )) topCallNode = self.tmpCallNode.top() self.tmpCallNode.pop() newTmp = self.newTmp() self.funCode[self.domain].append( self.genCode(op='pop', result={'reg': newTmp})) topCallNode.addAttributes("place", {'reg': newTmp}) out = ('产生式: ' + self.Table.table[X][now].left + '-->' + ' '.join(self.Table.table[X][now].right)) outResult += out.ljust(40, ' ') proResult = True else: if len(stack.s) == 1 or self.Table.table[X][now] == ' ': newNode = node() newNode.setData(X) stack.push(newNode) self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' skip %s , check near %s\n' % (word, word)) word, label, now = self.advance() if word == -1: self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' meet the end token # before finishing analysis or no end token #\n' ) outResult += '\n' break break elif self.Table.table[X][now] == 'synch': self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' pop %s from the stack, check near %s\n' % (X, word)) break outResult += '\n' continue if not proResult: outResult += ' '.ljust(40) outResult += (('栈: ' + stack.show()).ljust(40) + '\n') if self.errorReason == '' and 'main' not in self.funCode.keys(): self.errorReason += 'No main function defined.\n ' if self.errorReason == '': for key in self.funCode.keys(): if key == 'global': continue self.funCode[key][0]['entry'] = key if self.haveReturn[key] == False: self.errorReason += 'int %s must have a return value.\n' % ( key) self.arrangeAddr() return self.errorReason, self.codeList, self.symbolList else: return self.errorReason, None, None
class SDTAnalysis: def __init__(self, InputPro): self.InputPro = InputPro self.Terminals = [] self.TerAndEnd = [] self.Virables = [] self.start = '' self.pList = ProductionList() self.First = {} self.Follow = {} self.string = '' self.ERROR = False self.symbolList = [] self.offset = 0 self.domain = 'global' self.funCode = {} self.funCode['global'] = [] self.TmpCount = 7 self.errorReason = '' self.tmpAddNodeList = MyStack() self.tmpMulNodeList = MyStack() self.tmpParam = MyStack() self.tmpSymbolIndex = MyStack() self.tmpCallNode = MyStack() self.haveReturn = {} '''设置起始符号''' def setStart(self, s): self.start = s '''构造产生式表''' def buildProList(self): for p in self.InputPro: self.pList.add(Production(p[0], p[1])) if p[0] not in self.Virables: self.Virables.append(p[0]) for p in self.InputPro: for t in p[1]: if t not in self.Virables and t not in self.Terminals and t != 'NULL': self.Terminals.append(t) self.TerAndEnd = self.Terminals.copy() self.TerAndEnd.append('#') '''消除非终结符p的直接左递归''' def delDirectRecur(self, p): v = p vPList = self.pList.getVirablePro(v) isLeftRecur = False for p in vPList: if p.left == p.right[0]: isLeftRecur = True if isLeftRecur == True: new_v = v + '1' assert new_v not in self.Virables self.Virables.append(new_v) for p in vPList: if p.left == p.right[0]: self.pList.delete(p) p.right.remove(p.left) p.right.append(new_v) self.pList.add(Production(new_v, p.right)) else: if p.right == ['NULL']: p.right = [new_v] else: p.right.append(new_v) self.pList.add(Production(v, p.right)) self.pList.add(Production(new_v, ['NULL'])) '''消除左递归''' def delLeftRecur(self): for v in self.Virables: self.delDirectRecur(v) '''求FIRST集合''' def getFirst(self): first = {} for v in self.Virables: first[v] = [] while (True): Modify = False for p in self.pList: if p.right[0] in self.Terminals: if p.right[0] not in first[p.left]: first[p.left].append(p.right[0]) Modify = True elif p.right == ['NULL']: if 'NULL' not in first[p.left]: first[p.left].append('NULL') Modify = True else: for i in range(len(p.right)): if p.right[i] in self.Virables and i == 0: for t in first[p.right[i]]: if t not in first[p.left]: first[p.left].append(t) Modify = True if p.right[i] in self.Virables and i >= 1 \ and p.right[i-1] in self.Virables \ and 'NULL' in first[p.right[i-1]]: for t in first[p.right[i]]: if t not in first[p.left]: first[p.left].append(t) Modify = True if i == len(p.right) - 1 and \ 'NULL' in first[p.right[i]]: if 'NULL' not in first[p.left]: first[p.left].append('NULL') Modify = True if p.right[i] in self.Terminals and i >= 1 \ and p.right[i - 1] in self.Virables \ and 'NULL' in first[p.right[i - 1]]: if p.right[i] not in first[p.left]: first[p.left].append(p.right[i]) Modify = True break if not Modify: self.First = first break '''求FOLLOW集合''' def getFollow(self): follow = {} for v in self.Virables: follow[v] = [] if v == self.start: follow[v].append('#') while (True): Modify = False for p in self.pList: i = len(p.right) - 1 rightNull = True while (i >= 0): if p.right[i] in self.Terminals: rightNull = False if p.right[i] in self.Virables: if rightNull == True: for t in follow[p.left]: if t not in follow[p.right[i]]: follow[p.right[i]].append(t) Modify = True if 'NULL' not in self.First[p.right[i]]: rightNull = False if i < len(p.right) - 1 and p.right[ i + 1] in self.Terminals: if p.right[i + 1] not in follow[p.right[i]]: follow[p.right[i]].append(p.right[i + 1]) Modify = True if i < len(p.right) - 1 and p.right[ i + 1] in self.Virables: for t in self.First[p.right[i + 1]]: if t not in follow[p.right[i]] and t != 'NULL': follow[p.right[i]].append(t) Modify = True i -= 1 if not Modify: self.Follow = follow break '''求产生式的FIRST集合,之前须调用getFirst()''' def getProFirst(self, pro): first = [] i = 0 AllNull = True while (i < len(pro.right)): if pro.right[i] in self.Terminals: if pro.right[i] not in first: first.append(pro.right[i]) AllNull = False break elif pro.right[i] == 'NULL': break else: for t in self.First[pro.right[i]]: if t not in first: first.append(t) if 'NULL' not in self.First[pro.right[i]]: AllNull = False break else: i += 1 if AllNull: first.append('NULL') return first '''判断是否为LL1文法''' def isLL1(self): for v in self.Virables: pro = self.pList.getVirablePro(v) for p in pro: for q in pro: if p != q: first_p = self.getProFirst(p) first_q = self.getProFirst(q) for t in first_p: if t in first_q: print(p.right, q.right) return False if 'NULL' in self.First[v]: for t in self.First[v]: if t in self.Follow[v]: print(self.First[v]) print(self.Follow[v]) print(v) return False return True '''构造LL1分析表''' def buildLL1Table(self): self.Table = LL1Table(self.Virables) for p in self.pList: first_p = self.getProFirst(p) for t in first_p: self.Table.add(p.left, t, p) if 'NULL' in first_p: for k in self.Follow[p.left]: self.Table.add(p.left, k, p) for v in self.Virables: for t in self.TerAndEnd: if t not in self.Table.table[v]: if t in self.Follow[v]: self.Table.table[v][t] = 'synch' else: self.Table.table[v][t] = ' ' def showLL1Table(self): for v in self.Virables: for t in self.TerAndEnd: if self.Table.table[v][t] == ' ' or self.Table.table[v][ t] == 'synch': print(v, t, self.Table.table[v][t]) else: print(v, t, self.Table.table[v][t].left, self.Table.table[v][t].right) '''读取待分析文件''' def readFile(self, fileName): f = open(fileName, 'r') self.string = f.read() f.close() '''读取待分析字符串''' def getString(self, s): self.string = s '''读取下一个词''' def advance(self): while (self.pointer < len(self.string)): if self.string[self.pointer] in ['\n', '\t', ' ']: if self.string[self.pointer] == '\n': self.lineCounter += 1 self.pointer += 1 else: end, label = self.lex.lex_analyze(self.pointer) word = self.string[self.pointer:end + 1] self.pointer = end + 1 if label == '标识符': now = '标识符' elif label == '数值': now = 'num' else: now = word return word, label, now return -1, -1, -1 #越界 '''产生一行中间代码''' def genCode(self, op=None, arg1=None, arg2=None, result=None): code = {} code['addr'] = 0 code['op'] = op if arg1 != None: code['arg1'] = arg1 if arg2 != None: code['arg2'] = arg2 code['result'] = result return code '''查询符号表''' def lookUpSymbol(self, name, domain): for i in range(len(self.symbolList)): if self.symbolList[i]["idName"] == name and self.symbolList[i][ "domain"] == domain: return i, self.symbolList[i]["domain"] for i in range(len(self.symbolList)): if self.symbolList[i]["idName"] == name: return i, self.symbolList[i]["domain"] return -1, "NULL" '''申请新的变量''' def newTmp(self): if self.TmpCount == 24: self.TmpCount = 7 self.TmpCount += 1 return self.TmpCount '''完成翻译后分配地址''' def arrangeAddr(self): codeList = [] unknownList = [] funAddr = {} counter = 0 funAddr['main'] = 100 self.funCode['main'][-1]['result'] = 'end' for c in self.funCode['main']: c['addr'] = 100 + counter if c['op'][0] == 'j': try: if c['result'][:3] == 'to_': c['result'] = c['result'][3:] unknownList.append(counter) except: c['result'] = 100 + counter + c['result'] codeList.append(c) counter += 1 for key in self.funCode: if key != "main": funAddr[key] = 100 + counter for c in self.funCode[key]: c['addr'] = 100 + counter if c['op'][0] == 'j': try: if c['result'][:3] == 'to_': c['result'] = c['result'][3:] unknownList.append(counter) except: c['result'] = 100 + counter + c['result'] codeList.append(c) counter += 1 for u in unknownList: if codeList[u]['result'] == "end": codeList[u]['result'] = len(codeList) + 100 else: codeList[u]['result'] = funAddr[codeList[u]['result']] self.codeList = codeList '''语法制导翻译''' def analyze(self): self.ERROR = False self.head = node() self.head.setData('head') stack = MyStack() self.lex = LexAn(self.string) endNode = node() endNode.setData('#') stack.push(endNode) startNode = node() startNode.setData(self.start) startNode.setParent(self.head) self.head.addChildren(startNode) stack.push(startNode) self.pointer = 0 self.lineCounter = 1 word, label, now = self.advance() outResult = '' while (True): '''遇注释号跳过''' if label == '注释号': word, label, now = self.advance() continue '''文件读完,未完成语法分析''' if word == -1: self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' no end token #\n') outResult += '\n' break '''遇非法字符''' if label == 'ERROR': self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' skip %s\n' % word) outResult += '\n' break out = ('line %d: ' % self.lineCounter + word + ',' + label) outResult = outResult + out.ljust(20, ' ') proResult = False topNode = stack.pop() X = topNode.data if X in self.Terminals: if X == now: if X == "标识符": topNode.parent.addAttributes('place', word) if topNode.parent.parent.data == '参数': symbol = {} symbol['type'] = topNode.parent.parent.children[ 0].data symbol['idName'] = word symbol['label'] = 'formal' symbol["domain"] = self.domain code = self.genCode(op='pop', result={'reg': self.newTmp()}) symbol['reg'] = code['result']['reg'] self.symbolList.append(symbol) self.funCode[self.domain].append(code) if topNode.parent.parent.data == '内部变量声明': symbol = {} symbol['type'] = topNode.parent.parent.children[ 0].data symbol['idName'] = word symbol['offset'] = self.offset self.offset += 4 symbol['label'] = 'data' symbol['domain'] = self.domain self.symbolList.append(symbol) if X == "num": topNode.parent.addAttributes('place', {'Imme': word}) if X == ';': if topNode.parent.data == '赋值语句': symbolIndex, tag = self.lookUpSymbol( topNode.parent.children[0].attributes['place'], self.domain) if symbolIndex < 0 or (tag != self.domain and tag != "global"): self.errorReason += ( "Line%d: undeclared identifier %s\n" % (self.lineCounter, topNode.parent. children[0].attributes['place'])) break if self.symbolList[symbolIndex][ 'label'] == 'formal': code = self.genCode( op=':=', arg1=topNode.parent.children[2]. attributes['place'], result={ 'reg': self.symbolList[symbolIndex]['reg'] }) elif self.symbolList[symbolIndex][ 'label'] == 'data': code = self.genCode( op=':=', arg1=topNode.parent.children[2]. attributes['place'], result={'symbolIndex': symbolIndex}) self.funCode[self.domain].append(code) elif topNode.parent.data == '返回值': self.haveReturn[self.domain] = True if topNode.parent.children[0].data == '表达式': symbolIndex, _ = self.lookUpSymbol( self.domain, self.domain) if self.symbolList[symbolIndex][ 'type'] == 'void': self.errorReason += 'Line%d: void %s can not have a return value.\n ' % ( self.lineCounter, self.domain) break self.funCode[self.domain].append( self.genCode( op='push', result=topNode.parent.children[0]. attributes['place'])) else: symbolIndex, _ = self.lookUpSymbol( self.domain, self.domain) if self.symbolList[symbolIndex][ 'type'] == 'int': self.errorReason += 'Line%d: int %s has no return value.\n ' % ( self.lineCounter, self.domain) break self.funCode[self.domain].append( self.genCode(op='jr', result='$ra')) self.domain = 'global' if X == ')': if topNode.parent.data == 'if语句': self.funCode[self.domain].append( self.genCode( op='j' + topNode.parent.children[2]. children[1].children[0].children[0].data, arg1=topNode.parent.children[2]. children[0].attributes['place'], arg2=topNode.parent.children[2].children[1] .children[1].attributes['place'], result=2)) self.funCode[self.domain].append( self.genCode(op='j', result=0)) topNode.parent.attributes['false'] = len( self.funCode[self.domain]) - 1 elif topNode.parent.data == 'while语句': self.funCode[self.domain].append( self.genCode( op='j' + topNode.parent.children[2]. children[1].children[0].children[0].data, arg1=topNode.parent.children[2]. children[0].attributes['place'], arg2=topNode.parent.children[2].children[1] .children[1].attributes['place'], result=2)) self.funCode[self.domain].append( self.genCode(op='j', result=0)) topNode.parent.attributes['end'] = len( self.funCode[self.domain]) - 1 elif topNode.parent.data == '因子': topNode.parent.attributes[ 'place'] = topNode.parent.children[ 1].attributes['place'] if X == '}': if topNode.parent.data == '语句块': if topNode.parent.parent.data == 'if语句': self.funCode[self.domain].append( self.genCode(op='j', result=0)) false = topNode.parent.parent.attributes[ 'false'] self.funCode[ self.domain][false]['result'] = len( self.funCode[self.domain]) - false topNode.parent.parent.attributes['end'] = len( self.funCode[self.domain]) - 1 elif topNode.parent.parent.data == 'else语句': end = topNode.parent.parent.parent.attributes[ 'end'] self.funCode[self.domain][end]['result'] = len( self.funCode[self.domain]) - end elif topNode.parent.parent.data == 'while语句': end = topNode.parent.parent.attributes['end'] self.funCode[self.domain].append( self.genCode( op='j', result=end - len(self.funCode[self.domain]) - 1)) self.funCode[self.domain][end]['result'] = len( self.funCode[self.domain]) - end topNode.addAttributes('lineNum', self.lineCounter) word, label, now = self.advance() else: self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' expect %s\n' % (X)) outResult += '\n' break elif X == '#': if X == now: break else: self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' please check near %s\n' % (word)) outResult += '\n' break elif X in self.Virables and self.Table.table[X][now] not in [ ' ', 'synch' ]: if self.Table.table[X][now].right == ['NULL']: newNode = node() newNode.setParent(topNode) newNode.setData('NULL') topNode.addChildren(newNode) else: k = len(self.Table.table[X][now].right) - 1 while (k >= 0): newNode = node() newNode.setParent(topNode) newNode.setData(self.Table.table[X][now].right[k]) topNode.addChildren(newNode) stack.push(newNode) k -= 1 topNode.reverseChildren() if X == '变量声明': symbol = {} symbol['type'] = topNode.parent.parent.children[0].data symbol['idName'] = topNode.parent.parent.children[ 1].attributes['place'] symbol['offset'] = self.offset self.offset += 4 symbol['label'] = 'data' symbol['domain'] = self.domain self.symbolList.append(symbol) elif X == '函数声明' and topNode.parent.data == '声明类型': symbol = {} symbol['type'] = topNode.parent.parent.children[0].data symbol['idName'] = topNode.parent.parent.children[ 1].attributes['place'] self.domain = symbol['idName'] self.funCode[self.domain] = [] symbol['label'] = 'func' symbol['domain'] = self.domain symbol['offset'] = self.offset self.offset += 4 self.haveReturn[self.domain] = False self.symbolList.append(symbol) elif X == '函数声明' and topNode.parent.data == '声明': symbol = {} symbol['type'] = topNode.parent.children[0].data symbol['idName'] = topNode.parent.children[1].attributes[ 'place'] self.domain = symbol['idName'] self.funCode[self.domain] = [] symbol['label'] = 'func' symbol['domain'] = self.domain self.haveReturn[self.domain] = True self.symbolList.append(symbol) if X == '加法表达式': self.tmpAddNodeList.push([]) elif X == '加法表达式1': top = self.tmpAddNodeList.top() top.append(topNode) elif X == '项': self.tmpMulNodeList.push([]) elif X == '项1': top = self.tmpMulNodeList.top() top.append(topNode) if X == '加法表达式1' and topNode.children[0].data == 'NULL': topAddNode = self.tmpAddNodeList.top() self.tmpAddNodeList.pop() if topNode.parent.data == '加法表达式': topNode.parent.attributes[ 'place'] = topNode.parent.children[0].attributes[ 'place'] del topAddNode[-1] for k in range(len(topAddNode)): addNode = topAddNode[len(topAddNode) - k - 1] if addNode.children[0].data == '-': addNode.children[0].data = '减' newTmp = self.newTmp() self.funCode[self.domain].append( self.genCode(op='+', arg1={'reg': 0}, arg2=addNode.children[1]. attributes['place'], result={'reg': newTmp})) self.funCode[self.domain].append( self.genCode(op='uminus', result={'reg': newTmp})) addNode.children[1].attributes['place'] = { 'reg': newTmp } if addNode.parent.children[0].data == '-': addNode.parent.children[0].data = '减' newTmp = self.newTmp() self.funCode[self.domain].append( self.genCode(op='+', arg1={'reg': 0}, arg2=addNode.parent.children[1]. attributes['place'], result={'reg': newTmp})) self.funCode[self.domain].append( self.genCode(op='uminus', result={'reg': newTmp})) addNode.parent.children[1].attributes['place'] = { 'reg': newTmp } newTmp = self.newTmp() if addNode.parent.data == '加法表达式': code = self.genCode( '+', addNode.parent.children[0].attributes['place'], addNode.children[1].attributes['place'], {'reg': newTmp}) addNode.parent.addAttributes( 'place', {'reg': newTmp}) else: code = self.genCode( '+', addNode.parent.children[1].attributes['place'], addNode.children[1].attributes['place'], {'reg': newTmp}) addNode.parent.children[1].addAttributes( 'place', {'reg': newTmp}) self.funCode[self.domain].append(code) elif X == '项1' and topNode.children[0].data == 'NULL': topMulNode = self.tmpMulNodeList.top() self.tmpMulNodeList.pop() if topNode.parent.data == '项': topNode.parent.attributes[ 'place'] = topNode.parent.children[0].attributes[ 'place'] del topMulNode[-1] for k in range(len(topMulNode)): mulNode = topMulNode[len(topMulNode) - k - 1] newTmp = self.newTmp() if mulNode.parent.data == '项': code = self.genCode( mulNode.children[0].data, mulNode.parent.children[0].attributes['place'], mulNode.children[1].attributes['place'], {'reg': newTmp}) mulNode.parent.addAttributes( 'place', {'reg': newTmp}) else: code = self.genCode( mulNode.children[0].data, mulNode.parent.children[1].attributes['place'], mulNode.children[1].attributes['place'], {'reg': newTmp}) mulNode.parent.children[1].addAttributes( 'place', {'reg': newTmp}) self.funCode[self.domain].append(code) elif X == '表达式1' and topNode.children[0].data == 'NULL': if topNode.parent.data != '表达式1': topNode.parent.addAttributes( 'place', topNode.parent.children[0].attributes['place']) if topNode.parent.parent.data == '因子': topNode.parent.parent.addAttributes( 'place', topNode.parent.children[0].attributes['place']) if topNode.parent.parent.data in ['实参列表', '实参列表1']: top = self.tmpParam.top() top.append(topNode.parent.attributes['place']) elif X == 'FTYPE' and topNode.children[0].data == 'NULL': symbolIndex, tag = self.lookUpSymbol( topNode.parent.children[0].attributes['place'], self.domain) if symbolIndex < 0 or (tag != self.domain and tag != "global"): self.errorReason += ( "Line%d: undeclared identifier %s\n" % (self.lineCounter, topNode.parent.children[0].attributes['place'])) break if self.symbolList[symbolIndex]['label'] == 'formal': topNode.parent.addAttributes( 'place', {'reg': self.symbolList[symbolIndex]['reg']}) elif self.symbolList[symbolIndex]['label'] == 'data': topNode.parent.addAttributes( 'place', {'symbolIndex': symbolIndex}) elif X == 'call': symbolIndex, tag = self.lookUpSymbol( topNode.parent.parent.children[0].attributes['place'], self.domain) if symbolIndex < 0: self.errorReason += ( "Line%d: undeclared function %s\n" % (self.lineCounter, topNode.parent.parent. children[0].attributes['place'])) break self.tmpSymbolIndex.push(symbolIndex) self.tmpParam.push([]) self.tmpCallNode.push(topNode.parent.parent) elif X in ['实参列表', '实参列表1' ] and topNode.children[0].data == 'NULL': paramCount = 0 for s in self.symbolList: if s['domain'] == self.symbolList[self.tmpSymbolIndex.top()]['idName'] \ and s['label'] == 'formal': paramCount += 1 topParam = self.tmpParam.top() topSymbolIndex = self.tmpSymbolIndex.top() self.tmpParam.pop() self.tmpSymbolIndex.pop() if paramCount != len(topParam): self.errorReason += ( "Line%d: %s function doesn't accept %d parameters\n" % (self.lineCounter, self.symbolList[topSymbolIndex]['idName'], len(topParam))) break for i in range(len(topParam)): self.funCode[self.domain].append( self.genCode( op='push', result=topParam[len(topParam) - i - 1], )) self.funCode[self.domain].append( self.genCode( op='jal', result='to_%s' % (self.symbolList[topSymbolIndex]['idName']), )) topCallNode = self.tmpCallNode.top() self.tmpCallNode.pop() newTmp = self.newTmp() self.funCode[self.domain].append( self.genCode(op='pop', result={'reg': newTmp})) topCallNode.addAttributes("place", {'reg': newTmp}) out = ('产生式: ' + self.Table.table[X][now].left + '-->' + ' '.join(self.Table.table[X][now].right)) outResult += out.ljust(40, ' ') proResult = True else: if len(stack.s) == 1 or self.Table.table[X][now] == ' ': newNode = node() newNode.setData(X) stack.push(newNode) self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' skip %s , check near %s\n' % (word, word)) word, label, now = self.advance() if word == -1: self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' meet the end token # before finishing analysis or no end token #\n' ) outResult += '\n' break break elif self.Table.table[X][now] == 'synch': self.errorReason += ( 'Syntax error, line %d:' % self.lineCounter + ' pop %s from the stack, check near %s\n' % (X, word)) break outResult += '\n' continue if not proResult: outResult += ' '.ljust(40) outResult += (('栈: ' + stack.show()).ljust(40) + '\n') if self.errorReason == '' and 'main' not in self.funCode.keys(): self.errorReason += 'No main function defined.\n ' if self.errorReason == '': for key in self.funCode.keys(): if key == 'global': continue self.funCode[key][0]['entry'] = key if self.haveReturn[key] == False: self.errorReason += 'int %s must have a return value.\n' % ( key) self.arrangeAddr() return self.errorReason, self.codeList, self.symbolList else: return self.errorReason, None, None
class SematicAnalysis(): def __init__(self, head): self.symbolList = [] self.codeList = [] self.treeHead = head self.offset = 0 self.domain = "global" self.error = False self.errorReason = [] self.regCount = 7 self.codeStack = MyStack() self.paramStack = MyStack() self.funCode = {} self.haveReturn = True def newReg(self): if self.regCount == 24: self.regCount = 7 self.regCount += 1 return self.regCount def lookUpSymbol(self, name, domain): for i in range(len(self.symbolList)): if self.symbolList[i]["idName"] == name and self.symbolList[i]["domain"] == domain: return i, self.symbolList[i]["domain"] for i in range(len(self.symbolList)): if self.symbolList[i]["idName"] == name: return i, self.symbolList[i]["domain"] return -1, "NULL" def arrangeAddr(self): codeList = [] unknownList = [] funAddr = {} counter = 0 funAddr['main'] = 100 self.funCode['main'][-1]['result'] = 'end' for c in self.funCode['main']: c['addr'] = 100 + counter if c['op'][0] == 'j': try: if c['result'][:3] == 'to_': c['result'] = c['result'][3:] unknownList.append(counter) except: c['result'] = 100 + counter + c['result'] codeList.append(c) counter += 1 for key in self.funCode: if key != "main": funAddr[key] = 100 + counter for c in self.funCode[key]: c['addr'] = 100 + counter if c['op'][0] == 'j': try: if c['result'][:3] == 'to_': c['result'] = c['result'][3:] unknownList.append(counter) except: c['result'] = 100 + counter + c['result'] codeList.append(c) counter += 1 for u in unknownList: if codeList[u]['result'] == "end": codeList[u]['result'] = len(codeList)+ 100 else: codeList[u]['result'] = funAddr[codeList[u]['result']] self.codeList = codeList def genCode(self, op=None, arg1=None, arg2=None, result=None): code = {} code['addr'] = 0 code['op'] = op if arg1 != None: code['arg1'] = arg1 if arg2 != None: code['arg2'] = arg2 code['result'] = result return code def expDFS(self, p): if self.error: return if p.data == "因子": if len(p.children) > 1 \ and p.children[1].data == "FTYPE"\ and p.children[1].children[0].data == "call": #过程调用 symbolIndex, _ = self.lookUpSymbol( p.children[0].children[0].attributes['idName'], self.domain ) if symbolIndex < 0: self.error = True self.errorReason.append("line %d: 未声明的函数 %s" % ( p.children[0].children[0].attributes['lineNum'], p.children[0].children[0].attributes['idName'] )) return tmpCode = [] tmpParam = [] self.codeStack.push(tmpCode) self.paramStack.push(tmpParam) self.expDFS(p.children[1].children[0].children[1]) if self.error: return tmpCode = self.codeStack.pop() tmpParam = self.paramStack.pop() paramCount = 0 for s in self.symbolList: if s['domain'] == self.symbolList[symbolIndex]['idName']\ and s['label'] == 'formal': paramCount += 1 if paramCount != len(tmpParam): #参数个数不匹配 self.error = True self.errorReason.append("line %d: %s函数不接受%d个参数"%( p.children[0].children[0].attributes['lineNum'], self.symbolList[symbolIndex]['idName'], len(tmpParam) )) for i in range(len(tmpParam)): tmpCode.append(self.genCode( op='push', result=tmpParam[i], )) tmpCode.append(self.genCode( op='jal', result="to_" + self.symbolList[symbolIndex]['idName'] )) if self.symbolList[symbolIndex]['label'] == 'formal': p.addAttributes( "place", {'reg': self.symbolList[symbolIndex]['reg']} ) elif self.symbolList[symbolIndex]['label'] == 'func': code = self.genCode(op='pop', result={'reg':self.newReg()}) tmpCode.append(code) p.addAttributes( "place", code['result'] ) else: p.addAttributes( "place", {'symbolIndex':symbolIndex} ) self.codeStack.top().extend(tmpCode) return if p.children[0].data == "ID": symbolIndex, tag = self.lookUpSymbol( p.children[0].children[0].attributes['idName'], self.domain ) if symbolIndex < 0 or (tag != self.domain and tag != "global"): self.error = True self.errorReason.append("line %d: 未声明的标识符 %s"%( p.children[0].children[0].attributes['lineNum'], p.children[0].children[0].attributes['idName'] )) return if p.children[0].children[0].attributes['idName'][0] == '-': if self.symbolList[symbolIndex]['label'] == 'formal': p.addAttributes( "place", {'reg': -self.symbolList[symbolIndex]['reg']} ) else: p.addAttributes( "place", {'symbolIndex':-symbolIndex} ) else: if self.symbolList[symbolIndex]['label'] == 'formal': p.addAttributes( "place", {'reg': self.symbolList[symbolIndex]['reg']} ) else: p.addAttributes( "place", {'symbolIndex':symbolIndex} ) if p.children[0].data == "num": p.addAttributes( "place", {'Imme':p.children[0].attributes['NumValue']} ) for i in range(len(p.children)): self.expDFS(p.children[i]) if self.error: return if p.data == '项' or p.data == '加法表达式': if 'place' in p.children[0].attributes and 'place' not in p.children[1].attributes: p.addAttributes('place', p.children[0].attributes['place']) if 'place' in p.children[0].attributes and 'place' in p.children[1].attributes: if p.children[1].children[0].data == '-': p.children[1].children[0].data = '+' p.addAttributes('place', {'reg':self.newReg()}) self.codeStack.top().append(self.genCode( op = p.children[1].children[0].data, arg1 = p.children[0].attributes['place'], arg2 = p.children[1].attributes['place'], result = p.attributes['place'] )) if p.data == '项1' or p.data == '加法表达式1': if p.children[0].data == 'NULL': return if p.children[0].data == '-': if 'Imme' in p.children[1].attributes['place']: new = self.newReg() code = self.genCode( op='+', arg1={'reg':0}, arg2=p.children[1].attributes['place'], result={'reg':new} ) self.codeStack.top().append(code) p.children[1].attributes['place'] = {'reg':new} code = self.genCode( op='uminus', result=p.children[1].attributes['place'] ) self.codeStack.top().append(code) if 'place' in p.children[1].attributes and 'place' not in p.children[2].attributes: p.addAttributes('place', p.children[1].attributes['place']) if 'place' in p.children[1].attributes and 'place' in p.children[2].attributes: if p.children[2].children[0].data == '-': p.children[2].children[0].data = '+' p.addAttributes('place', {'reg':self.newReg()}) code = self.genCode( op = p.children[2].children[0].data, arg1 = p.children[1].attributes['place'], arg2 = p.children[2].attributes['place'], result = p.attributes['place'] ) p.addAttributes('code', code) self.codeStack.top().append(code) if p.data == "表达式" and 'place' in p.children[0].attributes: p.addAttributes('place', p.children[0].attributes['place']) if p.data == "表达式1" and p.children[0].data == 'relop': if 'place' in p.children[1].attributes: p.addAttributes('place', p.children[1].attributes['place']) if p.data == "因子": if 'place' not in p.attributes: p.addAttributes('place', p.children[1].attributes['place']) if p.data == "实参列表": self.paramStack.top().append(p.children[0].attributes['place']) if p.data == "实参列表1" and p.children[0].data != 'NULL': self.paramStack.top().append(p.children[1].attributes['place']) def DFS(self, p): if self.error: return if p.data == "声明": symbol = {} symbol["type"] = p.children[0].data symbol["idName"] = p.children[1].children[0].attributes["idName"] if symbol["type"] == "int": symbol["offset"] = self.offset if p.children[2].children[0].data == "变量声明": symbol['label'] = 'data' symbol["domain"] = self.domain self.offset += 4 if p.children[2].children[0].data == "函数声明": #非void型 self.domain = symbol["idName"] symbol['label'] = 'func' symbol["domain"] = symbol["idName"] self.haveReturn = False if p.children[2].data == "函数声明": #void型 symbol['label'] = 'func' self.domain = symbol["idName"] self.haveReturn = True symbol['domain'] = symbol["idName"] self.symbolList.append(symbol) if p.data == "内部变量声明": symbol = {} symbol["type"] = p.children[0].data symbol["idName"] = p.children[1].children[0].attributes["idName"] if symbol["type"] == "int": symbol["offset"] = self.offset self.offset += 4 if symbol["type"] == "double": symbol["offset"] = self.offset self.offset += 8 symbol['label'] = 'data' symbol["domain"] = self.domain self.symbolList.append(symbol) if p.data == "参数": symbol = {} symbol["type"] = p.children[0].data symbol["idName"] = p.children[1].children[0].attributes["idName"] if symbol["type"] == "int": symbol["offset"] = self.offset if symbol["type"] == "double": symbol["offset"] = self.offset symbol['label'] = "formal" symbol["domain"] = self.domain code = self.genCode(op='pop', result={'reg':self.newReg()}) p.addAttributes('code', [code]) symbol['reg'] = code['result']['reg'] self.symbolList.append(symbol) if p.data == "赋值语句": tmpCode = [] self.codeStack.push(tmpCode) self.expDFS(p.children[2]) if self.error: return symbolIndex, tag = self.lookUpSymbol( p.children[0].children[0].attributes['idName'], self.domain ) if symbolIndex < 0 or (tag != self.domain and tag != "global"): self.error = True self.errorReason.append("line %d: 未声明的标识符 %s" % ( p.children[0].children[0].attributes['lineNum'], p.children[0].children[0].attributes['idName'] )) return if self.symbolList[symbolIndex]['label'] == 'formal': result = {'reg': self.symbolList[symbolIndex]['reg']} else: result = {'symbolIndex': symbolIndex} self.codeStack.top().append(self.genCode( op = ':=', arg1 = p.children[2].attributes['place'], result = result )) p.addAttributes('code', self.codeStack.pop()) elif p.data == "if语句": tmpCode = [] self.codeStack.push(tmpCode) self.expDFS(p.children[2]) if self.error: return ifcode = self.codeStack.pop() ifcode.append(self.genCode( op = 'j' + p.children[2].children[1].children[0].children[0].data, arg1 = p.children[2].attributes['place'], arg2 = p.children[2].children[1].attributes['place'], result = 2 )) Unknown = len(ifcode) ifcode.append(self.genCode(op='j', result=-1)) self.DFS(p.children[4]) #搜索if条件成立的语句块 if self.error:return ifcode.extend(p.children[4].attributes['code']) self.DFS(p.children[5]) #搜索else下的语句块 if self.error:return code = self.genCode(op='j') ifcode.append(code) ifcode[Unknown]['result'] = len(p.children[4].attributes['code'])+2 if 'code' in p.children[5].attributes: code['result'] = len(p.children[5].attributes['code']) + 1 ifcode.extend(p.children[5].attributes['code']) else: code['result'] = 1 p.addAttributes('code', ifcode.copy()) elif p.data == 'while语句': tmpCode = [] self.codeStack.push(tmpCode) self.expDFS(p.children[2]) if self.error: return whilecode = self.codeStack.pop() whilecode.append(self.genCode( op = 'j'+p.children[2].children[1].children[0].children[0].data, arg1 = p.children[2].attributes['place'], arg2 = p.children[2].children[1].attributes['place'], result = 2 )) Unknown = len(whilecode) whilecode.append(self.genCode(op='j',result=-1)) self.DFS(p.children[4]) #搜索while条件成立的语句块 if self.error:return whilecode.extend(p.children[4].attributes['code']) whilecode.append(self.genCode(op='j', result=-len(whilecode))) whilecode[Unknown]['result'] = len(whilecode)-Unknown p.addAttributes('code', whilecode) elif p.data == "return语句": if self.haveReturn == False: self.haveReturn = True tmpCode = [] if p.children[1].children[0].data != ";": #有返回值 symbolIndex, _ = self.lookUpSymbol(self.domain, self.domain) if self.symbolList[symbolIndex]['type'] == 'void': # 函数必须有返回值,报错 self.error = True self.errorReason.append('line %d: %s函数不能有返回值' % ( p.children[0].attributes['lineNum'], self.domain)) return self.codeStack.push(tmpCode) self.expDFS(p.children[1].children[0]) if self.error: return tmpCode = self.codeStack.pop() code = self.genCode(op='push', result=p.children[1].children[0].attributes['place']) tmpCode.append(code) else: #无返回值 symbolIndex, _ = self.lookUpSymbol(self.domain, self.domain) if self.symbolList[symbolIndex]['type'] != 'void': #函数必须有返回值,报错 self.error = True self.errorReason.append('line %d: %s函数必须有返回值'%( p.children[0].attributes['lineNum'], self.domain )) tmpCode.append(self.genCode(op='jr', result='$ra')) p.addAttributes('code', tmpCode) else: for i in range(len(p.children)): self.DFS(p.children[i]) if self.error: return if p.data == "语句" and 'code' in p.children[0].attributes: p.addAttributes('code', p.children[0].attributes['code']) if p.data == "语句串": p.addAttributes('code', p.children[0].attributes['code']) if 'code' in p.children[1].attributes: p.attributes['code'].extend(p.children[1].attributes['code']) if p.data == "语句串1" and 'code' in p.children[0].attributes: p.addAttributes('code', p.children[0].attributes['code']) if 'code' in p.children[1].attributes: p.attributes['code'].extend(p.children[1].attributes['code']) if p.data == "语句块" : p.addAttributes('code', p.children[2].attributes['code']) if p.data == 'else语句' and p.children[0].data != 'NULL' and 'code' in p.children[1].attributes: p.addAttributes('code', p.children[1].attributes['code']) if p.data == "形参" and 'code' in p.children[0].attributes: p.addAttributes('code', p.children[0].attributes['code']) if p.data == "参数列表" and 'code' in p.children[0].attributes: p.addAttributes('code', p.children[0].attributes['code']) if 'code' in p.children[1].attributes: p.attributes['code'].extend(p.children[1].attributes['code']) if p.data == "参数列表1" and p.children[0].data != "NULL" and 'code' in p.children[1].attributes: p.addAttributes('code', p.children[1].attributes['code']) if 'code' in p.children[2].attributes: p.attributes['code'].extend(p.children[2].attributes['code']) if p.data == "函数声明": if self.haveReturn == False: self.error = 1 self.errorReason.append('%s必须返回一个值'%self.domain) return self.domain = "global" if 'code' in p.children[1].attributes: p.addAttributes('code', p.children[1].attributes['code']) else: p.addAttributes('code',[]) p.attributes['code'].extend(p.children[-1].attributes['code']) if p.parent.data == "声明类型": idName = p.parent.parent.children[1].children[0].attributes['idName'] self.funCode[idName] = p.attributes['code'] else: idName = p.parent.children[1].children[0].attributes['idName'] self.funCode[idName] = p.attributes['code'] self.funCode[idName][0]['entry'] = idName if p.data == "Program": if 'main' not in self.funCode: self.error = True self.errorReason.append("未定义主函数") return self.arrangeAddr() def analyse(self): self.DFS(self.treeHead) return self.symbolList, self.codeList, '\n'.join(self.errorReason)+'\n'
if __name__ == "__main__": # Creating and populating the stack stack = MyStack() stack.push(2) stack.push(97) stack.push(4) stack.push(42) stack.push(12) stack.push(60) stack.push(23) # Sorting the stack stack = sort_stack(stack) # Printing the sorted stack print("Stack after sorting") print([stack.pop() for i in range(stack.size())]) class MyStack: def __init__(self): self.stack_list = [] self.stack_size = 0 def is_empty(self): return self.stack_size == 0 def peek(self): if self.is_empty(): return None return self.stack_list[-1]