12632Sstever@eecs.umich.edu# ----------------------------------------------------------------------------- 22632Sstever@eecs.umich.edu# calc.py 32632Sstever@eecs.umich.edu# 42632Sstever@eecs.umich.edu# A simple calculator with variables. This is from O'Reilly's 52632Sstever@eecs.umich.edu# "Lex and Yacc", p. 63. 62632Sstever@eecs.umich.edu# ----------------------------------------------------------------------------- 72632Sstever@eecs.umich.edu 84479Sbinkertn@umich.eduimport sys 94479Sbinkertn@umich.edusys.path.insert(0,"../..") 104479Sbinkertn@umich.edu 116498Snate@binkert.orgif sys.version_info[0] >= 3: 126498Snate@binkert.org raw_input = input 136498Snate@binkert.org 142632Sstever@eecs.umich.edutokens = ( 152632Sstever@eecs.umich.edu 'NAME','NUMBER', 162632Sstever@eecs.umich.edu ) 172632Sstever@eecs.umich.edu 184479Sbinkertn@umich.eduliterals = ['=','+','-','*','/', '(',')'] 194479Sbinkertn@umich.edu 202632Sstever@eecs.umich.edu# Tokens 212632Sstever@eecs.umich.edu 222632Sstever@eecs.umich.edut_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' 232632Sstever@eecs.umich.edu 242632Sstever@eecs.umich.edudef t_NUMBER(t): 252632Sstever@eecs.umich.edu r'\d+' 266498Snate@binkert.org t.value = int(t.value) 272632Sstever@eecs.umich.edu return t 282632Sstever@eecs.umich.edu 292632Sstever@eecs.umich.edut_ignore = " \t" 302632Sstever@eecs.umich.edu 312632Sstever@eecs.umich.edudef t_newline(t): 322632Sstever@eecs.umich.edu r'\n+' 334479Sbinkertn@umich.edu t.lexer.lineno += t.value.count("\n") 346498Snate@binkert.org 352632Sstever@eecs.umich.edudef t_error(t): 366498Snate@binkert.org print("Illegal character '%s'" % t.value[0]) 374479Sbinkertn@umich.edu t.lexer.skip(1) 386498Snate@binkert.org 392632Sstever@eecs.umich.edu# Build the lexer 404479Sbinkertn@umich.eduimport ply.lex as lex 412632Sstever@eecs.umich.edulex.lex() 422632Sstever@eecs.umich.edu 432632Sstever@eecs.umich.edu# Parsing rules 442632Sstever@eecs.umich.edu 452632Sstever@eecs.umich.eduprecedence = ( 464479Sbinkertn@umich.edu ('left','+','-'), 474479Sbinkertn@umich.edu ('left','*','/'), 482632Sstever@eecs.umich.edu ('right','UMINUS'), 492632Sstever@eecs.umich.edu ) 502632Sstever@eecs.umich.edu 512632Sstever@eecs.umich.edu# dictionary of names 522632Sstever@eecs.umich.edunames = { } 532632Sstever@eecs.umich.edu 544479Sbinkertn@umich.edudef p_statement_assign(p): 554479Sbinkertn@umich.edu 'statement : NAME "=" expression' 564479Sbinkertn@umich.edu names[p[1]] = p[3] 572632Sstever@eecs.umich.edu 584479Sbinkertn@umich.edudef p_statement_expr(p): 592632Sstever@eecs.umich.edu 'statement : expression' 606498Snate@binkert.org print(p[1]) 612632Sstever@eecs.umich.edu 624479Sbinkertn@umich.edudef p_expression_binop(p): 634479Sbinkertn@umich.edu '''expression : expression '+' expression 644479Sbinkertn@umich.edu | expression '-' expression 654479Sbinkertn@umich.edu | expression '*' expression 664479Sbinkertn@umich.edu | expression '/' expression''' 674479Sbinkertn@umich.edu if p[2] == '+' : p[0] = p[1] + p[3] 684479Sbinkertn@umich.edu elif p[2] == '-': p[0] = p[1] - p[3] 694479Sbinkertn@umich.edu elif p[2] == '*': p[0] = p[1] * p[3] 704479Sbinkertn@umich.edu elif p[2] == '/': p[0] = p[1] / p[3] 712632Sstever@eecs.umich.edu 724479Sbinkertn@umich.edudef p_expression_uminus(p): 734479Sbinkertn@umich.edu "expression : '-' expression %prec UMINUS" 744479Sbinkertn@umich.edu p[0] = -p[2] 752632Sstever@eecs.umich.edu 764479Sbinkertn@umich.edudef p_expression_group(p): 774479Sbinkertn@umich.edu "expression : '(' expression ')'" 784479Sbinkertn@umich.edu p[0] = p[2] 792632Sstever@eecs.umich.edu 804479Sbinkertn@umich.edudef p_expression_number(p): 814479Sbinkertn@umich.edu "expression : NUMBER" 824479Sbinkertn@umich.edu p[0] = p[1] 832632Sstever@eecs.umich.edu 844479Sbinkertn@umich.edudef p_expression_name(p): 854479Sbinkertn@umich.edu "expression : NAME" 862632Sstever@eecs.umich.edu try: 874479Sbinkertn@umich.edu p[0] = names[p[1]] 882632Sstever@eecs.umich.edu except LookupError: 896498Snate@binkert.org print("Undefined name '%s'" % p[1]) 904479Sbinkertn@umich.edu p[0] = 0 912632Sstever@eecs.umich.edu 924479Sbinkertn@umich.edudef p_error(p): 936498Snate@binkert.org if p: 946498Snate@binkert.org print("Syntax error at '%s'" % p.value) 956498Snate@binkert.org else: 966498Snate@binkert.org print("Syntax error at EOF") 972632Sstever@eecs.umich.edu 984479Sbinkertn@umich.eduimport ply.yacc as yacc 992632Sstever@eecs.umich.eduyacc.yacc() 1002632Sstever@eecs.umich.edu 1012632Sstever@eecs.umich.eduwhile 1: 1022632Sstever@eecs.umich.edu try: 1032632Sstever@eecs.umich.edu s = raw_input('calc > ') 1042632Sstever@eecs.umich.edu except EOFError: 1052632Sstever@eecs.umich.edu break 1064479Sbinkertn@umich.edu if not s: continue 1072632Sstever@eecs.umich.edu yacc.parse(s) 108