PL λαβ
Lab 1.2c[최준혁]: 구문 분석기 본문
오늘 제공된 강의자료의 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