PL λαβ
Lab 2.2a[김예령]: 기본 함수 본문
# 진행상황
Built-in 함수 c* 패밀리를 만드는 데 성공했지만 이전 Lab에서 만든 환경이 제대로 구축되지 않았지때문에 프로그램 초반에 환경을 설정하는 부분이 작동하지 않는다.
우선은 Built-in 함수가 잘 작동하는 지 보기위해 환경 설정 없이 바로 보내주도록 코드를 짰고(built-in이란 말이 무색하다...) 아래와 같이 동작한다.
foo와 bar를 이용해 cons함수가 잘 만들어지지만 출력하는 부분에서 foo, bar의 값이 아닌 foo, bar symbol name이 출력된다. 이 부분 또한 보완이 필요하다.
# Result
===== Init Symbol Table =====
['Nil', {'cons': <__main__.Data object at 0x000001A15AE601C0>, 'car': <__main__.Data object at 0x000001A15AE450A0>, 'cdr': <__main__.Data object at 0x000001A15AE43FD0>}]
======= Program Start =======
If you want Quit, type ':q'
>>> (define foo 1)
======= Symbol Table =======
['Nil', {'cons': <__main__.Data object at 0x000001A15AE601C0>, 'car': <__main__.Data object at 0x000001A15AE450A0>, 'cdr': <__main__.Data object at 0x000001A15AE43FD0>, 'foo': 1}]
=========== OUT ===========
foo
>>> (define bar 2)
======= Symbol Table =======
['Nil', {'cons': <__main__.Data object at 0x000001A15AE601C0>, 'car': <__main__.Data object at 0x000001A15AE450A0>, 'cdr': <__main__.Data object at 0x000001A15AE43FD0>, 'foo': 1, 'bar': 2}]
=========== OUT ===========
bar
>>> (cons foo bar)
======= Symbol Table =======
['Nil', {'cons': <__main__.Data object at 0x000001A15AE601C0>, 'car': <__main__.Data object at 0x000001A15AE450A0>, 'cdr': <__main__.Data object at 0x000001A15AE43FD0>, 'foo': 1, 'bar': 2}]
=========== OUT ===========
(foo . bar)
>>>
# Code
from enum import Enum
SymbolTable = []
class Type(Enum):
NIL = 0
INT = 1
PAIR = 2
SYMBOL = 3
Builtin = 4
class Data:
def __init__(self, type=Type.NIL, value=0):
self.type = type
self.value = value
def car(self):
return self.value[0]
def cdr(self):
return self.value[1]
def __str__(self):
if self.type == Type.NIL:
return "NIL"
elif self.type == Type.PAIR:
try:
if self.cdr() == int(self.cdr()):
return "(" + str(self.car()) + " . " + str(self.cdr()) + ")"
except:
retStr = "("
retStr += str(self.car())
atom = self.cdr()
while atom.type != Type.NIL:
if atom.type == Type.PAIR:
retStr += " . "
retStr += str(atom.car())
atom = atom.cdr()
else:
retStr += " . "
retStr += str(atom)
break
retStr += ")"
return str(retStr)
else:
return str(self.value)
# return "babo~ya"
def cons(d1, d2):
return Data(Type.PAIR, (d1, d2))
def mkint(n):
return Data(Type.INT, n)
def mksym(s):
return Data(Type.SYMBOL, s)
def nilp():
return Data(Type.NIL)
def make_builtin(fn):
return Data(Type.Builtin, fn)
class T_Type(Enum):
NIL = 0
OP = 1
CP = 2
SYM = 3
ID = 4
INT = 5
class Token:
def __init__(self, type=T_Type.NIL, value=None):
self.type = type
self.value = value
def __str__(self):
if self.type == T_Type.SYM or self.type == T_Type.ID or self.type == T_Type.INT:
return f"Token [{self.type}, Value: {self.value}]"
else:
return f"Token [{self.type}]"
def Lexer(lists):
TokenList = []
for i in range(len(lists)):
LA = lists[i]
if LA == "(":
TokenList.append(Token(T_Type.OP))
elif LA == ")":
TokenList.append(Token(T_Type.CP))
elif LA == "quote":
TokenList.append(Token(T_Type.SYM, "QUOTE"))
elif LA == "define":
TokenList.append(Token(T_Type.SYM, "DEF"))
elif LA == "lambda":
TokenList.append(Token(T_Type.SYM, "LAM"))
elif LA == "if":
TokenList.append(Token(T_Type.SYM, "IF"))
elif LA == "+":
TokenList.append(Token(T_Type.SYM, "PLUS"))
elif LA == "-":
TokenList.append(Token(T_Type.SYM, "MINUS"))
elif LA == ">":
TokenList.append(Token(T_Type.SYM, "GT"))
elif LA == "<":
TokenList.append(Token(T_Type.SYM, "LT"))
else:
try:
iL = int(LA)
isinstance(iL, int)
TokenList.append(Token(T_Type.INT, iL))
except:
TokenList.append(Token(T_Type.ID, LA))
return TokenList
def iCons(d_list):
if len(d_list) != 1:
return cons(d_list[0], iCons(d_list[1:]))
else:
return cons(d_list[0], nilp())
def Parser(tokenlist):
if len(tokenlist) == 0:
return "[ERROR] Empty List"
LA = tokenlist.pop(0)
if LA.type == T_Type.OP:
if tokenlist[0].type == T_Type.CP:
return nilp()
L = []
while tokenlist[0].type != T_Type.CP:
L.append(Parser(tokenlist))
tokenlist.pop(0)
LR = iCons(L)
return LR
elif LA.type == T_Type.CP:
return "[ERROR] Unexpected ')'"
else:
try:
if int(LA.value):
return Data(Type.INT, int(LA.value))
except:
return Data(Type.SYMBOL, LA.value)
def env_init(parent):
SymbolTable.append(parent)
SymbolTable.append({})
return "Error_OK"
def env_set(sym, val):
SymbolTable[1][sym.value] = val
return "ENV_SET"
def builtin_car(args):
if args.type == Type.NIL or args.cdr().type != Type.NIL:
return "Error_Args"
if args.car().type == Type.NIL:
return nilp()
elif args.car().type != Type.PAIR:
return "Error_Type"
else:
return args.car().car()
def builtin_cdr(args):
if args.type == Type.NIL or args.cdr().type != Type.NIL:
return "Error_Args"
if args.car().type == Type.NIL:
return nilp()
elif args.car().type != Type.PAIR:
return "Error_Type"
else:
return args.car().cdr()
def builtin_cons(args): # cons($1, $2)
if (
args.type == Type.NIL # arguments type != NIL
or args.cdr().type == Type.NIL # $2 != NIL
or args.cdr().cdr().type != Type.NIL # cons($1, cons($2, NIL))
):
return "Error_Args"
return cons(args.car(), args.cdr().car())
def SymbTable(lists):
LA = lists
if LA.type == Type.SYMBOL: # get symbol
if LA.value in SymbolTable[1]:
return SymbolTable[1].get(LA.value)
else:
return "Symbol not bound"
elif LA.type == Type.INT:
return str(LA.value)
elif LA.type == Type.NIL:
return str(LA)
else:
if LA.car().type == Type.SYMBOL: # set symbol
if LA.car().value == "QUOTE":
SymbolTable[1][LA.cdr().car().value] = None
return LA.cdr().car().value
elif LA.car().value == "DEF":
SymbolTable[1][LA.cdr().car().value] = LA.cdr().cdr().car().value
return LA.cdr().car().value
elif LA.car().value == "cons":
return builtin_cons(LA.cdr())
elif LA.car().value == "car":
return builtin_car(LA.cdr())
elif LA.car().value == "cdr":
return builtin_cdr(LA.cdr())
else:
return "IDK :/"
if __name__ == "__main__":
env = env_init("Nil")
env_set(mksym("cons"), make_builtin(builtin_cons))
env_set(mksym("car"), make_builtin(builtin_car))
env_set(mksym("cdr"), make_builtin(builtin_cdr))
print("===== Init Symbol Table =====")
print(SymbolTable)
print("======= Program Start =======")
line = input("If you want Quit, type ':q'\n>>> ")
while line != ":q":
if line:
# How can I handle one line code and multi line code at same time?
line = line.replace("(", " ( ").replace(")", " ) ").split()
r = Parser(Lexer(line))
sr = SymbTable(r)
print("======= Symbol Table =======")
print(SymbolTable)
print("=========== OUT ===========")
print(sr)
else:
break
line = input(">>> ")
'kos' 카테고리의 다른 글
Lab 2.1a[박인철]: 환경 (0) | 2021.04.27 |
---|---|
Lab 2.2[최준혁]: 기본 함수 (0) | 2021.04.24 |
Lab 2.2: 기본 함수 (0) | 2021.04.15 |
Lab 1.2c[TA]: 구문 분석기 (0) | 2021.04.15 |
Lab 2.1b[김예령]: 환경 (0) | 2021.04.15 |
Comments