Esempio n. 1
0
    def search_address_of(self, token: Token,
                          block_number_stack: Stack) -> int:
        """심볼 테이블에서 변수의 주소를 검색하는 메서드

        Args:
            token: 검색할 토큰
            block_number_stack: 해당 토큰이 속한 블록 스택

        Returns: 심볼 테이블에서 탐색한 변수의 주소

        Raises:
            NoVariableDeclarationError: 선언되지 않은 변수를 사용할 때 발생한다.
        """
        while True:
            block_number = block_number_stack.pop()
            search_result = self._symbol_table[
                self._symbol_table['identifier'] == token.token_string
                and self._symbol_table['block_number'] == block_number]

            if len(search_result) > 1:
                # 같은 범위에 같은 식별자의 변수가 중복됨.
                raise RuntimeError("Compiler >> redundant variable")
            elif len(search_result) == 1:
                # 찾은 경우
                return search_result[0][4]
            else:
                # 찾지 못한 경우
                if not block_number_stack.is_empty():
                    # 스택에 블록 넘버가 남은 경우
                    continue
                else:
                    # 스택이 빈 경우 -> 정의된 변수가 없음
                    raise NoVariableDeclarationError(self._source_code, token)
def revString(item):
    astack = Stack()
    revstring = ""
    for i in item:
        astack.push(i)
    for j in range(len(item)):
        revstring += astack.pop()
    return revstring
def DecimalToBinary(decNum):
    binString = ""
    binStack = Stack()
    while decNum > 0:
        binNum = decNum % 2
        binStack.push(binNum)
        decNum = decNum // 2
    while not binStack.isEmpty():
        binString += str(binStack.pop())
    return binString
def DecimalToBase(decNum, base):
    system = "0123456789ABCDEF"
    baseString = ""
    baseStack = Stack()
    while decNum > 0:
        baseNum = decNum % base
        baseStack.push(baseNum)
        decNum = decNum // base
    while not baseStack.isEmpty():
        baseString += system[baseStack.pop()]
    return baseString
Esempio n. 5
0
class SyntaxTree:
    """코드의 구문을 저장한 트리

    구문 분석 단계의 결과로 생성된다.

    in 키워드로 반복문을 사용하면 preorder로 순회한다.
    트리 예시)
                                 total
                     prog                       $
        word   (  )        block

    순서 예시)
        total - prog - word - ( - ) - block - $
    """
    def __init__(self):
        self._root: TokenNode = None
        self._parent_stack = Stack()
        self._current: TreeStackNode = None

    @property
    def root(self) -> TokenNode:
        return self._root

    @root.setter
    def root(self, token_node: TokenNode):
        self._root = token_node

    def __iter__(self):
        return self

    def __next__(self) -> TokenNode:
        if self._current is None:
            if self._root is not None:
                self._current = TreeStackNode(self._root)
                return self._current.token_node
            else:
                raise StopIteration

        while True:
            child = self._current.next_child()

            if self._current.token_node.get_child(child) is not None:
                self._parent_stack.push(self._current)
                self._current = TreeStackNode(
                    self._current.token_node.get_child(child))
                return self._current.token_node
            else:
                if not self._parent_stack.is_empty():
                    self._current = self._parent_stack.pop()
                    continue
                else:
                    self._current = None
                    raise StopIteration
def parChecker(parString):
    s = Stack()
    for par in parString:
        if par == "(":
            s.push(par)
        else:
            if s.isEmpty():
                return False
            else:
                s.pop()
    return s.isEmpty()
def postfixEva(postfixString):
    operandStack = Stack()
    postfixList = postfixString.split(" ")
    print postfixList
    for postfixEle in postfixList:
        if postfixEle in "0123456789":
            print "push %s in the operand stack." % postfixEle
            operandStack.push(postfixEle)
        else:
            operand2 = operandStack.pop()
            operand1 = operandStack.pop()
            mathResult = mathCal(postfixEle, int(operand1), int(operand2))
            print "calculate %s %s %s and push the result %s in the operand stack" %(operand1, postfixEle, operand2, mathResult)
            operandStack.push(mathResult)
    return operandStack.pop()
def symChecker(symString):
    s = Stack()
    for sym in symString:
        if sym in "({[":
            s.push(sym)
        else:
            if s.isEmpty():
                return False
            else:
                matSym = s.pop()
                if not matchChecker(matSym,sym):
                    return False
    return s.isEmpty()
def parseTreeBuilder(inputExpr):
    exprList = inputExpr.split(" ")
    parseTree = BinaryTree("")
    parentRoot = Stack()
    parentRoot.push(parseTree)
    currentRoot = parseTree
    for token in exprList:
        if token == "(":
            currentRoot.insertLeft("")
            parentRoot.push(currentRoot)
            currentRoot = currentRoot.getLeftChild()
        elif token not in ['+','-','*','/',')']:
            currentRoot.setRootVal(int(token))
            currentRoot = parentRoot.pop()
        elif token in ['+','-','*','/']:
            currentRoot.setRootVal(token)
            currentRoot.insertRight("")
            parentRoot.push(currentRoot)
            currentRoot = currentRoot.getRightChild()
        elif token == ")":
            currentRoot = parentRoot.pop()
        else:
            raise ValueError
    return parseTree
def infixToPostfix(infixString):
    order = {"*": 3, "/": 3, "+": 2, "-": 2, "(": 1}
    operatorStack = Stack()
    postfixString = []
    infixList = infixString.split()
    print infixList
    for infixEle in infixList:
        if infixEle in "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789":
            print "append %s to the output string" % infixEle
            postfixString.append(infixEle)
        elif infixEle == "(":
            print "push ( to the stack"
            operatorStack.push(infixEle)
        elif infixEle == ")":
            print "pop operator until see ("
            topOper = operatorStack.pop()
            while topOper != "(":
                print "pop %s until see (" % topOper                
                postfixString.append(topOper)
                topOper = operatorStack.pop()
        else:
            while (not operatorStack.isEmpty()) and (order[operatorStack.peek()] >= order[infixEle]):
                print "pop out %s before push %s in" % (operatorStack.peek(), infixEle)
                postfixString.append(operatorStack.pop())        
            print "push %s in the stack" % infixEle
            operatorStack.push(infixEle)
    while not operatorStack.isEmpty():
        postfixString.append(operatorStack.pop())   
    return postfixString
from datastructure import Stack

#-----------------------------------------------------------------
# Tower of Hanoi
def moveTower(height, fromPole, toPole, withPole):
    if height >= 1:
        moveTower(height-1, fromPole, withPole, toPole)
        popOut = fromPole.pop()
        toPole.push(popOut)
        print "Moving Disk",popOut,"from", fromPole.name, "to", toPole.name
        moveTower(height-1, withPole, toPole, fromPole)

fStack = Stack()
fStack.name = "A"
tStack = Stack()
tStack.name = "B"
wStack = Stack()
wStack.name = "C"
for i in range(5, 0, -1):
    fStack.push(i)
    
moveTower(5, fStack, tStack, wStack)            

#-----------------------------------------------------------------
# Define a class with recursive function to solve "Die hard" problem
class dieHard:
    
    def __init__(self, big, small, goal):
        self.big = big
        self.small = small
        self.init = [0,0]
Esempio n. 12
0
    def parse(self) -> list:
        """Scanner로부터 받아온 Token들을 parse하는 메서드

        최초 기호와 마지막 기호가 담긴 stack과 Token들이 담긴 queue를 이용하여
        PARSING_TABLE에 따라 parse한다.
        LL parser의 원리를 사용한다.

        Returns: SyntaxTree, SymbolTable로 구성된 list를 반환한다.

        Raises:
            NoSemiColonError: 세미 콜론이 있어야할 위치에 없을 때 발생한다.
            NotDefinedCompileError: 에러를 파악할 수 없을 때 발생한다.
            RedundantVariableDeclarationError: 심볼 테이블에 이미 같은 식별자, 블록 넘버의 심볼이 있을 때 발생한다.
            RuntimeError: 심볼 테이블에 int, char 이외의 변수가 입력되는 경우 발생한다.
        """
        # Symbol Table
        symbol_table = SymbolTable(self._source_code)

        # 변수의 타입 기록
        vtype = None

        # 현재 word가 변수 선언할 때의 식별자인지 기록
        is_decl_var = False

        # Syntax Tree
        syntax_tree = SyntaxTree()

        # syntax tree에서 현재 접근 중인 노드의 스택 노드
        current_stack_node: TreeStackNode = None

        # syntax tree에서 현재 접근 중인 노드의 부모 스택
        parent_stack = Stack()

        # error handling을 위해 token이 담긴 queue에서 꺼낸 token들을 저장하는 stack
        used_token_stack = Stack()

        # symbol을 관리할 stack
        stack = Stack()

        stack.push(Parser.END_SYMBOL)
        stack.push(Parser.START_SYMBOL)

        root_node = TreeStackNode(
            TokenNode(Token(Parser.TOTAL_SYMBOL, None, None, 0)))
        root_node.token_node.add_child(
            Token(Parser.START_SYMBOL, None, None, 0))
        root_node.token_node.add_child(Token(Parser.END_SYMBOL, None, None, 0))
        syntax_tree.root = root_node.token_node
        parent_stack.push(root_node)
        current_stack_node = TreeStackNode(
            root_node.token_node.get_child(root_node.next_child()))

        self._token_queue.enqueue(Token(Parser.END_SYMBOL, "", 0, 0))

        log(f"queue : {self._token_queue}")
        log(f"stack : {stack}")
        log(f"work  : start\n")

        try:
            while not stack.is_empty():
                for tree_stack_node in parent_stack:
                    log(f"stack node : {tree_stack_node.token_node.token}")
                for token_node in syntax_tree:
                    log(f"node : {token_node.token} '{token_node.token.token_string}'"
                        )

                log(f"current node : {current_stack_node.token_node.token}")

                if self._token_queue.get().token == stack.get():
                    # 기호가 같을 때 pop
                    token = self._token_queue.dequeue()
                    used_token_stack.push(token)
                    stack.pop()

                    # 토큰이 데이터 타입인 경우, 기록한다
                    if token.token == 'int' or token.token == 'char':
                        vtype = token.token
                    # 토큰이 세미 콜론인 경우, 심볼 테이블에 추가하는 것을 그만둔다.
                    elif token.token == ';':
                        is_decl_var = False
                    # 토큰이 word인 경우,
                    elif is_decl_var and token.token == 'word':
                        symbol_table.add_symbol(token, vtype)

                    # syntax tree의 현재 접근 중인 노드를 queue에서 빠진 token로 교체한다.
                    current_stack_node.token_node.token = token

                    # 부모로 올라가 다음 child로 이동한다.
                    if not token.token == Parser.END_SYMBOL:
                        while True:
                            current_stack_node = parent_stack.pop()
                            next_child = current_stack_node.token_node.get_child(
                                current_stack_node.next_child())

                            if next_child is not None:
                                parent_stack.push(current_stack_node)
                                current_stack_node = TreeStackNode(next_child)
                                break

                    log(f"queue : {self._token_queue}")
                    log(f"stack : {stack}")
                    log(f"work  : pop\n")
                else:
                    # 기호가 다를 땐 확장
                    symbol = stack.pop()
                    next_symbols = Parser.PARSING_TABLE[symbol][
                        self._token_queue.get().token]

                    # 기호가 decl인 경우, 변수 선언으로 간주하고 앞으로 나오는 word들을 심볼 테이블에 추가한다.
                    if symbol == 'decl':
                        is_decl_var = True

                    if next_symbols[0] != 'e':
                        # e는 엡실론으로 추가하지 않는다.
                        # 역순으로 stack에 추가한다.
                        for i in range(-1, -(len(next_symbols) + 1), -1):
                            stack.push(next_symbols[i])

                        # 원래 순서로 syntax tree의 현재 접근 중인 노드의 child로 추가한다.
                        for i in range(0, len(next_symbols)):
                            current_stack_node.token_node.add_child(
                                Token(next_symbols[i], None, None, 0))

                        # 부모 스택에 현재 스택 노드를 추가한 후 첫번째 child로 이동
                        parent_stack.push(current_stack_node)
                        current_stack_node = TreeStackNode(
                            current_stack_node.token_node.get_child(
                                current_stack_node.next_child()))
                    else:
                        # 부모로 올라가 다음 child로 이동한다.
                        while True:
                            current_stack_node = parent_stack.pop()
                            next_child = current_stack_node.token_node.get_child(
                                current_stack_node.next_child())

                            if next_child is not None:
                                parent_stack.push(current_stack_node)
                                current_stack_node = TreeStackNode(next_child)
                                break

                    log(f"queue : {self._token_queue}")
                    log(f"stack : {stack}")
                    log(f"work  : {symbol} -> {next_symbols}\n")
        except KeyError:
            for token in self._token_queue:
                pass

            # stack에 남은 다음 token이 세미 콜론이면 세미 콜론이 있어야할 곳에 없는 것으로 판정한다.
            if stack.get() == ';':
                raise NoSemiColonError(self._source_code,
                                       used_token_stack.get())

            raise NotDefinedCompileError()

        return [syntax_tree, symbol_table]
Esempio n. 13
0
def Generate_code(Code):
    In = Instruction()
    result_Code = []
    operater = ["*", "+", "==", ">", "="]
    # While block의 중첩을 구분하기 위함.
    whileStack = Stack()
    # block # 구분하기 위함.
    blockStack = Stack()

    #연산자와 피연산자를 저장하기 위함
    num = []
    op = []

    #현재 어느 Tree속에 들어와있는지 구분(WHILE, IF, THEN, ELSE, RETURN, block)
    current_state = ""
    #WHILE LABEL에 숫자를 붙이기 위함
    While_num = 0
    #IF LABEL에 숫자를 붙이기 위함
    if_num = 0
    #LABEL <block_num : while/if_num>
    block_num = 0
    register_num = 0

    for token in Code:

        num1 = 0
        num2 = 0

        if token.token.token == "WHILE":
            While_num += 1
            current_state = "WHILE"
            whileStack.push(token.token.token)
            result_Code.append(f"WHILE <{block_num+ 1 } : {While_num}> : ")
        elif token.token.token == "IF":
            current_state = "IF"
            if_num += 1
            result_Code.append(f"IF <{block_num} : {if_num}> : ")
        elif token.token.token == "RETURN":
            current_state = "RETURN"

        if token.token.token == "block":
            block_num += 1
            blockStack.push(block_num)
        elif token.token.token == "}":

            block_num = blockStack.pop()
            if current_state == 'block' and not whileStack.is_empty():
                result_Code.append(f"END_WHILE <{block_num } : {While_num}> :")
                While_num -= 1
                whileStack.pop()

#WHILE로 시작할 경우
        if current_state == "WHILE":
            #연산자, 피연산자 저장
            if token.token.token == "num" or token.token.token == "word":
                result_Code.append(
                    In.LD("R" + str(register_num), token.token.token_string))
                num.append("R" + str(register_num))
                register_num += 1
            if token.token.token in operater:
                op.append(token.token.token)
            # 조건 부분이 끝나면 연산 시작
            if token.token.token == "block":
                current_state = "block"
                op.reverse()
                num.reverse()
                # 피연산자와 연산자 LIST의 길이를 보고 연산을 반복한다.
                while len(num) - 1 != 0 and len(op) != 0:
                    num1 = num[0]
                    num2 = num[1]
                    if op[0] == "==":
                        result_Code.extend(In.Operater(num1, num2, op[0]))
                    else:
                        result_Code.append(In.Operater(num1, num2, op[0]))
                    del num[0]
                    num[0] = num2
                    del op[0]
                result_Code.append(
                    In.JUMPF(num[0], f"END_WHILE <{block_num} : {While_num}>"))
                # 한 block, cond에 관해 연산이 끝나면 num list와 op list는 모두 비운 뒤 다른 연산에 들어간다.
                del num[0]

        if current_state == "block":
            if token.token.token == "num" or token.token.token == "word":
                result_Code.append(
                    In.LD("R" + str(register_num), token.token.token_string))
                num.append("R" + str(register_num))
                register_num += 1
            if token.token.token in operater:
                op.append(token.token.token)
            if token.token.token == ";":
                op.reverse()
                num.reverse()
                while len(num) - 1 != 0 and len(op) != 0:
                    num1 = num[0]
                    num2 = num[1]
                    if op[0] == "==":
                        result_Code.extend(In.Operater(num1, num2, op[0]))
                    else:
                        result_Code.append(In.Operater(num1, num2, op[0]))
                    del num[0]
                    num[0] = num2
                    del op[0]
                del num[0]
                result_Code.append(
                    In.JUMP(f"WHILE <{block_num} : {While_num}>"))

#if로 시작할 경우"
        if current_state == "IF":
            if token.token.token == "num" or token.token.token == "word":
                result_Code.append(
                    In.LD("R" + str(register_num), token.token.token_string))
                num.append("R" + str(register_num))
                register_num += 1
            if token.token.token in operater:
                op.append(token.token.token)
            if token.token.token == "THEN":
                current_state = "THEN"
                op.reverse()
                num.reverse()
                while len(num) - 1 != 0 and len(op) != 0:
                    num1 = num[0]
                    num2 = num[1]
                    if op[0] == "==":
                        result_Code.extend(In.Operater(num1, num2, op[0]))
                    else:
                        result_Code.append(In.Operater(num1, num2, op[0]))
                    del num[0]
                    num[0] = num2
                    del op[0]
                result_Code.append(
                    In.JUMPF(num[0], f"ELSE <{block_num} : {if_num}> : "))
                del num[0]

        if current_state == "THEN":
            if token.token.token == "num" or token.token.token == "word":
                result_Code.append(
                    In.LD("R" + str(register_num), token.token.token_string))
                num.append("R" + str(register_num))
                register_num += 1
            if token.token.token in operater:
                op.append(token.token.token)
            if token.token.token == "ELSE":
                current_state = "ELSE"
                op.reverse()
                num.reverse()
                while len(num) - 1 != 0 and len(op) != 0:
                    num1 = num[0]
                    num2 = num[1]
                    if op[0] == "==":
                        result_Code.extend(In.Operater(num1, num2, op[0]))
                    else:
                        result_Code.append(In.Operater(num1, num2, op[0]))
                    del num[0]
                    num[0] = num2
                    del op[0]
                result_Code.append(f"ELSE <{block_num} : {if_num}> : ")
                del num[0]

        if current_state == "ELSE":
            if token.token.token == "num" or token.token.token == "word":
                result_Code.append(
                    In.LD("R" + str(register_num), token.token.token_string))
                num.append("R" + str(register_num))
                register_num += 1
            if token.token.token in operater:
                op.append(token.token.token)
            if token.token.token == "}":
                op.reverse()
                num.reverse()
                while len(num) - 1 != 0 and len(op) != 0:
                    num1 = num[0]
                    num2 = num[1]
                    if op[0] == "==":
                        result_Code.extend(In.Operater(num1, num2, op[0]))
                    else:
                        result_Code.append(In.Operater(num1, num2, op[0]))
                    del num[0]
                    num[0] = num2
                    del op[0]
                del num[0]
                result_Code.append(f"ENDIF <{block_num} : {if_num}> : ")


#RETURN으로 시작할 경우
        if current_state == "RETURN":
            if token.token.token == "num" or token.token.token == "word":
                result_Code.append(
                    In.LD("R" + str(register_num), token.token.token_string))
                num.append("R" + str(register_num))
                register_num += 1
            if token.token.token in operater:
                op.append(token.token.token)
            if token.token.token == ";":
                current_state = "block"
                op.reverse()
                num.reverse()
                while len(num) - 1 != 0 and len(op) != 0:
                    num1 = num[0]
                    num2 = num[1]
                    if op[0] == "==":
                        result_Code.extend(In.Operater(num1, num2, op[0]))
                    else:
                        result_Code.append(In.Operater(num1, num2, op[0]))
                    del num[0]
                    num[0] = num2
                    del op[0]
                result_Code.append(In.ADD("RV", "ZERO", num[0]))
                del num[0]

    file_writer = FileWriter(file_path.split("/")[0] + "/targetCode.code")
    for i in result_Code:
        file_writer.write(i)
        file_writer.write("\n")
        print(i)
Esempio n. 14
0
def Syntax_tree_Optimization(syntax_tree):
    Code = []

    TreeStack = Stack()
    block_num = 0

    for token in syntax_tree:
        if token.token.token == "total":
            TreeStack.push(token.token.token)

        if token.token.token == "block" and TreeStack.get() == "total":
            block_num += 1
            TreeStack.push(token.token.token)
            Code.append(token)

        if token.token.token == "}":
            Code.append(token)
            block_num -= 1
            while TreeStack.get() != "block":
                if TreeStack.get() == "total":
                    break
                TreeStack.pop()
            TreeStack.pop()

            if not TreeStack.is_empty() and TreeStack.get() == "WHILE":
                TreeStack.pop()
            if not TreeStack.is_empty() and TreeStack.get() == "ELSE":
                TreeStack.pop()
                TreeStack.pop()
                TreeStack.pop()

        if TreeStack.is_empty():
            continue
        elif TreeStack.get() == "stat":
            if token.token.token == "WHILE" or token.token.token == "IF" or token.token.token == "RETURN":
                Code.append(token)
                TreeStack.push(token.token.token)
            if token.token.token == "word":
                Code.append(token)
                TreeStack.push(token.token.token)

        elif TreeStack.get() == "WHILE":
            if token.token.token == "cond":
                Code.append(token)
                TreeStack.push(token.token.token)

        elif TreeStack.get() == "cond":
            if token.token.token != "block" and token.token.token != "THEN":
                if token.token.token_string is not None:
                    Code.append(token)
            if token.token.token == "block":
                TreeStack.pop()
                block_num += 1
                Code.append(token)
                TreeStack.push(token.token.token)
            if token.token.token == "THEN":
                TreeStack.pop()
                Code.append(token)
                TreeStack.push(token.token.token)

        elif TreeStack.get() == "block":
            if token.token.token == "stat":
                TreeStack.push(token.token.token)

        elif TreeStack.get() == "IF":
            if token.token.token == "cond":
                Code.append(token)
                TreeStack.push(token.token.token)

        elif TreeStack.get() == "IF":
            if token.token.token == "cond":
                Code.append(token)
                TreeStack.push(token.token.token)

        elif TreeStack.get() == "THEN":
            if token.token.token == "block":
                block_num += 1
                Code.append(token)
                TreeStack.push(token.token.token)
            if token.token.token == "ELSE":
                Code.append(token)
                TreeStack.push(token.token.token)

        elif TreeStack.get() == "ELSE":
            if token.token.token == "block":
                block_num += 1
                Code.append(token)
                TreeStack.push(token.token.token)

        elif TreeStack.get() == 'word':
            if token.token.token == ";":
                Code.append(token)
                TreeStack.pop()
                continue
            if token.token.token_string is not None:
                Code.append(token)

        elif TreeStack.get() == "RETURN":
            if token.token.token == ";":
                Code.append(token)
                TreeStack.pop()
                if TreeStack.get() == "stat":
                    TreeStack.pop()
                continue
            if token.token.token_string is not None:
                Code.append(token)
    Generate_code(Code)
Esempio n. 15
0
 def __init__(self):
     self._root: TokenNode = None
     self._parent_stack = Stack()
     self._current: TreeStackNode = None