PL λαβ

Lab 1.2c[최준혁]: 구문 분석기 본문

kos

Lab 1.2c[최준혁]: 구문 분석기

junhyeokk 2021. 4. 13. 19:50

오늘 제공된 강의자료의 read_list 부분 참고하여 구현하지 못했던 read_list 함수까지 완성하였습니다.

from data_mark2 import Type, Data, mksym, mkint, nil, nilp, cons
from enum import Enum

class Error(Enum):
    Error_OK = 0
    Error_Syntax = 1

class Token:
    def __init__(self, lexeme, location):
        self.lexeme = lexeme
        self.location = location

    def __getitem__(self, idx):
        return self.lexeme[idx]

    def match(self, another_token):
        return self.lexeme == another_token.lexeme

class Input():
    def __init__(self, input_str):  # lex 역할을 여기서 수행
        """string을 의미없는 공백들은 없애고 token(word, punctuation)들로 쪼갬 + syntax error 발생"""
        self.token_list = []
        for location, token_str in enumerate(input_str.split(' ')):
            self.token_list.append(Token(token_str.upper(), location))
        self.current_index = 0

    def nextToken(self):
        if len(self.token_list) <= self.current_index:
            return Error.Error_Syntax, None
        self.current_index += 1
        return Error.Error_OK, self.token_list[self.current_index - 1]

def read_expr(input_class):
    """single object를 읽어서 에러 상태와 나머지 input에 대한 포인터 반환"""
    err, token = input_class.nextToken()
    if err != Error.Error_OK:
        return err, None

    if token[0] == '(':
        err, result = read_list(input_class)
        return err, result
    # elif token[0] == ')':
    #     return Error.Error_Syntax, None
    else:
        err, result = parse_simple(input_class, token)
        return err, result

def parse_simple(input_class, token):  # parser
    """간단한 데이터(integers, symbols, NIL에 대해 처리"""
    if token.lexeme.isdecimal():
        return Error.Error_OK, mkint(int(token.lexeme))
    elif token.lexeme == "NIL":
        return Error.Error_OK, nil()
    else:
        return Error.Error_OK, mksym(token.lexeme)

def read_list(input_class):
    """improper lists와 pair에 대해 처리"""
    # la = [c for c in input_class.token_list[input_class.current_index]]
    # input에서 whitespace를 제거한 상태이므로 생략 : 추후 변경시 고쳐야 할수도 있음
    # err, token = input_class.nextToken()

    if input_class.token_list[input_class.current_index][0] == ')':
        # OOP스럽게 변경 가능할듯
        return Error.Error_OK, Data()

    err, ca = read_expr(input_class)
    if err != Error.Error_OK:
        return err, None

    err, cd = read_list(input_class)
    if err != Error.Error_OK:
        return err, None

    return Error.Error_OK, cons(ca, cd)

if __name__ == "__main__":
    input_line = input("> ")
    while input_line:
        input_class = Input(input_line)
        err, result_data = read_expr(input_class)

        if err == Error.Error_OK:
            print(result_data)
        elif err == Error.Error_Syntax:
            print("Syntax error")

        input_line = input("> ")

# > 42
# 42
# > (foo bar)
# (FOO BAR)
# > (s (t . u) v . (w . nil))
# (S (T . U) V W)
# > ()
# NIL

테스트 결과

이렇게 했을 때 pair까지 다 리스트로 처리되기는 하지만 중첩된 경우에 대해서도 동작하는 것을 확인했습니다. 토큰 사이마다 직접 공백을 넣어줘야 동작하는 부분은 다른 학생들의 코드 참고해서 수정하도록 하겠습니다.

'kos' 카테고리의 다른 글

Lab 2.1a[최준혁]: 환경  (0) 2021.04.13
Lab 2.1a[김예령]: 환경  (0) 2021.04.13
Lab 2.1: 환경  (0) 2021.04.13
Lab 1.2b[박인철]: 구문 분석기  (0) 2021.04.13
Lab 1.2b[최준혁]: 구문 분석기  (0) 2021.04.12
Comments