Пример #1
0
    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
Пример #2
0
    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