Question
I need the necessary corrections made to the Lexer & Parser code so that when running the Lisp program, after inputting (if (> 2 3)
I need the necessary corrections made to the Lexer & Parser code so that when running the Lisp program, after inputting
(if (> 2 3) 40 50) (or (> 2 3) (> 3 2)) (and (> 2 3) (> 3 2))
I get the following output:
LISP: (if (> 2 3) 40 50); 50.0 LISP: (or (> 2 3) (> 3 2)); True LISP: (and (> 2 3) (> 3 2)); False
# Lexer
import ply.lex as lex
t_SC = r';' t_LP = r'\(' t_RP = r'\)'
reserved = {'cdr' : 'CDR', 'car':'CAR', 'cons':'CONS', 'allow':'ALLOW'}
t_P = r'\+' t_M = r'-' t_T = r'\*' t_D = r'/'
tokens = ['NUM', 'ID', 'LP', 'RP', 'P', 'M', 'T', 'D', 'SC'] + list(reserved.values())
def t_NUM(t): r'[-+]?[0-9]+(\.([0-9]+)?)?' t.type = 'NUM' t.value = float(t.value) return t
def t_ID(t): r'[a-zA-Z][_a-zA-Z0-9]*' t_val = t.value.lower() if (t_val in reserved.keys()): t.type = reserved[t_val] else: t.type = 'ID' return t
t_ignore = " \t"
def t_error(t): print(f"Illegal character {t.value[0]}") raise Exception('LEXER ERROR')
lexer = lex.lex()
data = ''' [25/(3*40) + {300-20} -16.5] {(300-250)<(400-500)} 20 & 30 | 50 # This is a comment ''' lexer.input(data)
if __name__ == '__main__':
s = '(+ (car (2 3 4)) (car (cdr (cdr (9 8 7 6)))))' s1 = '(* (car (2 4 (+ 2 4) 8)) (/ 27 9));' lexer.input(s1)
while True: tok = lexer.token() if not tok: break print(tok)
# Parser
import ply.yacc as yacc from LispLexer import tokens
def p_LISP_Start(p): 'lispStart : lisplist SC' p[0] = p[1]
def p_LISPLIST_1(p): 'lisplist : lisp' p[0] = p[1]
def p_LISPLIST_2(p): 'lisplist : list' p[0] = p[1]
def p_LISP_1(p): 'lisp : NUM' p[0] = ['num',p[1]]
def p_LISP_2(p): 'lisp : ID' p[0] = ['id',p[1]]
def p_LISP_3(p): 'lisp : LP P lisp lisp RP' p[0] = ['+', p[3], p[4]]
def p_LISP_4(p): 'lisp : LP M lisp lisp RP' p[0] = ['-', p[3], p[4]]
def p_LISP_5(p): 'lisp : LP T lisp lisp RP' p[0] = ['*', p[3], p[4]]
def p_LISP_6(p): 'lisp : LP D lisp lisp RP' p[0] = ['/', p[3], p[4]]
def p_LISP_7(p): 'lisp : LP CAR list RP' p[0] = ['car', p[3]]
def p_LISP_8(p): 'lisp : LP ALLOW LP assigns RP lisp RP' p[0] = ['allow', p[4], p[6]] def p_ASSIGNS_1(p): 'assigns : assign' p[0] = [p[1]]
def p_ASSIGNS_2(p): 'assigns : assigns assign' p[0] = p[1] + [p[2]]
def p_ASSIGN(p): 'assign : LP ID lisp RP' p[0] = [p[2], p[3]]
def p_LIST_1(p): 'list : LP RP' p[0] = [[]]
def p_LIST_2(p): 'list : LP elements RP' p[0] = p[2]
def p_ELEMENTS_1(p): 'elements : lisp' p[0] = [p[1],[]]
def p_ELEMENTS_2(p): 'elements : lisp elements' p[0] = [p[1], p[2]]
def p_LIST_3(p): 'list : LP CDR list RP' p[0] = ['cdr', p[3]]
def p_LIST_4(p): 'list : LP CONS lisp list RP' p[0] = [p[3], p[4]]
def p_error(p): print("Syntax error in input!")
parser = yacc.yacc()
if __name__ == "__main__": l = ['34;', '(+ 20 30);', '(* (+ 1 2) (/ 8 4));', '(* (car (2 4 (+ 2 4) 8)) (/ 27 9));', '(+ (car (2 3 4)) (car (cdr (cdr (9 8 7 6)))));', '(+ x 4);', '(car (2 3 x y));', '(allow ((x 10) (y (+ 25 (car (20 30)))) (z (+ 10 23))) (+ x (car (y 20 z))) );', '(allow ((x 2)(y 4)) (+ x y));', '(allow ((x 10) (y (+ 25 (car (20 30)))) (z (+ 10 23))) (+ x (car (y 20 z))) );', '(car (cons 2 (cdr (10 20 30))));', '(cdr (1 2 3 4));']
l1 = ['(10 20 30)', '()', '(cdr (1 2 3 4))', '(cdr (cdr (cons 10 (20 30 (allow ((x 2)(y 4)) (+ x y))))))', '(cons 24 (30 (+ 20 20) 50))', '(cons (+ 3 4) ((+ 1 2) (* 1 2) (/20 2)))', '(cons 2 (cdr (10 20 30)))']
for data in l: print(parser.parse(data))
for data in l1: print(parser.parse(f'{data};'))
#Lisp
from LispParser import parser
def eval_expression(tree): if tree[0] == 'num': return (tree[1], 'OK')
if tree[0] == 'id': return (0, f'ERROR: Cannot evaluate ID {tree[1]}')
if tree[0] in ['+', '-', '*', '/']: v1, code1 = eval_expression(tree[1]) if (code1 != 'OK'): return (0, code1)
v2, code2 = eval_expression(tree[2]) if (code2 != 'OK'): return (0, code2)
if tree[0] == '+': result = v1+v2 elif tree[0] == '-': result = v1-v2 elif tree[0] == '*': result = v1*v2 else: if v2 == 0: return (0, "ERROR: Divided by 0!") result = v1/v2
return (result, 'OK')
if tree[0] == 'allow': sub = tree[2] for id_val in tree[1]: id = id_val[0] val, code = eval_expression(id_val[1]) if (code != 'OK'): return (0, code) sub = substitute(sub, id, val)
return eval_expression(sub)
return eval_list(tree)
def substitute(tree, id, val): tree1 = [] if (len(tree)>0 and tree[0] =='allow'): repls = tree[1] for repl in repls: if repl[0] == id: return tree
for node in tree: if (node == ['id', id]): tree1.append(['num', val]) else: if type(node) == list: tree1.append(substitute(node, id, val)) else: tree1.append(node) return tree1
def eval_list(tree): if (len(tree)>0) and tree[0] in ['car', 'cdr']: list1, code1 = eval_list(tree[1]) if (code1 != 'OK'): return (0, code1) if (list1 == []): return (0, f'{tree[0].upper()} of empty list Error!')
if (tree[0] == 'car'): return (list1[0], "OK") else: return (list1[1], "OK")
if tree != []: head, code = eval_expression(tree[0]) if (code == "OK"): tail, code1 = eval_list(tree[1]) if (code1 == "OK"): return ([head, tail], "OK") else: return (0, code1) else: return (0, code) else: return ([], "OK")
def grab_list(l): if (len(l)>1): return [l[0]] + grab_list(l[1]) else: return []
while(True): data = input("LISP: ") if (data[-1]!=';'): data+=';'
if (data == "exit;"): break
try: expr = parser.parse(data) val, code = eval_expression(expr) if (code == "OK"): if type(val) == list: val = grab_list(val) val = str(val).replace('[','(').replace(']',')').replace(',','')
print(f'The value is {val}') else: print(code) except Exception as e: print(e)
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started