calc.py revision 4479
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 112632Sstever@eecs.umich.edutokens = ( 122632Sstever@eecs.umich.edu 'NAME','NUMBER', 132632Sstever@eecs.umich.edu ) 142632Sstever@eecs.umich.edu 154479Sbinkertn@umich.eduliterals = ['=','+','-','*','/', '(',')'] 164479Sbinkertn@umich.edu 172632Sstever@eecs.umich.edu# Tokens 182632Sstever@eecs.umich.edu 192632Sstever@eecs.umich.edut_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' 202632Sstever@eecs.umich.edu 212632Sstever@eecs.umich.edudef t_NUMBER(t): 222632Sstever@eecs.umich.edu r'\d+' 232632Sstever@eecs.umich.edu try: 242632Sstever@eecs.umich.edu t.value = int(t.value) 252632Sstever@eecs.umich.edu except ValueError: 262632Sstever@eecs.umich.edu print "Integer value too large", t.value 272632Sstever@eecs.umich.edu t.value = 0 282632Sstever@eecs.umich.edu return t 292632Sstever@eecs.umich.edu 302632Sstever@eecs.umich.edut_ignore = " \t" 312632Sstever@eecs.umich.edu 322632Sstever@eecs.umich.edudef t_newline(t): 332632Sstever@eecs.umich.edu r'\n+' 344479Sbinkertn@umich.edu t.lexer.lineno += t.value.count("\n") 352632Sstever@eecs.umich.edu 362632Sstever@eecs.umich.edudef t_error(t): 372632Sstever@eecs.umich.edu print "Illegal character '%s'" % t.value[0] 384479Sbinkertn@umich.edu t.lexer.skip(1) 392632Sstever@eecs.umich.edu 402632Sstever@eecs.umich.edu# Build the lexer 414479Sbinkertn@umich.eduimport ply.lex as lex 422632Sstever@eecs.umich.edulex.lex() 432632Sstever@eecs.umich.edu 442632Sstever@eecs.umich.edu# Parsing rules 452632Sstever@eecs.umich.edu 462632Sstever@eecs.umich.eduprecedence = ( 474479Sbinkertn@umich.edu ('left','+','-'), 484479Sbinkertn@umich.edu ('left','*','/'), 492632Sstever@eecs.umich.edu ('right','UMINUS'), 502632Sstever@eecs.umich.edu ) 512632Sstever@eecs.umich.edu 522632Sstever@eecs.umich.edu# dictionary of names 532632Sstever@eecs.umich.edunames = { } 542632Sstever@eecs.umich.edu 554479Sbinkertn@umich.edudef p_statement_assign(p): 564479Sbinkertn@umich.edu 'statement : NAME "=" expression' 574479Sbinkertn@umich.edu names[p[1]] = p[3] 582632Sstever@eecs.umich.edu 594479Sbinkertn@umich.edudef p_statement_expr(p): 602632Sstever@eecs.umich.edu 'statement : expression' 614479Sbinkertn@umich.edu print p[1] 622632Sstever@eecs.umich.edu 634479Sbinkertn@umich.edudef p_expression_binop(p): 644479Sbinkertn@umich.edu '''expression : expression '+' expression 654479Sbinkertn@umich.edu | expression '-' expression 664479Sbinkertn@umich.edu | expression '*' expression 674479Sbinkertn@umich.edu | expression '/' expression''' 684479Sbinkertn@umich.edu if 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] 714479Sbinkertn@umich.edu elif p[2] == '/': p[0] = p[1] / p[3] 722632Sstever@eecs.umich.edu 734479Sbinkertn@umich.edudef p_expression_uminus(p): 744479Sbinkertn@umich.edu "expression : '-' expression %prec UMINUS" 754479Sbinkertn@umich.edu p[0] = -p[2] 762632Sstever@eecs.umich.edu 774479Sbinkertn@umich.edudef p_expression_group(p): 784479Sbinkertn@umich.edu "expression : '(' expression ')'" 794479Sbinkertn@umich.edu p[0] = p[2] 802632Sstever@eecs.umich.edu 814479Sbinkertn@umich.edudef p_expression_number(p): 824479Sbinkertn@umich.edu "expression : NUMBER" 834479Sbinkertn@umich.edu p[0] = p[1] 842632Sstever@eecs.umich.edu 854479Sbinkertn@umich.edudef p_expression_name(p): 864479Sbinkertn@umich.edu "expression : NAME" 872632Sstever@eecs.umich.edu try: 884479Sbinkertn@umich.edu p[0] = names[p[1]] 892632Sstever@eecs.umich.edu except LookupError: 904479Sbinkertn@umich.edu print "Undefined name '%s'" % p[1] 914479Sbinkertn@umich.edu p[0] = 0 922632Sstever@eecs.umich.edu 934479Sbinkertn@umich.edudef p_error(p): 944479Sbinkertn@umich.edu print "Syntax error at '%s'" % p.value 952632Sstever@eecs.umich.edu 964479Sbinkertn@umich.eduimport ply.yacc as yacc 972632Sstever@eecs.umich.eduyacc.yacc() 982632Sstever@eecs.umich.edu 992632Sstever@eecs.umich.eduwhile 1: 1002632Sstever@eecs.umich.edu try: 1012632Sstever@eecs.umich.edu s = raw_input('calc > ') 1022632Sstever@eecs.umich.edu except EOFError: 1032632Sstever@eecs.umich.edu break 1044479Sbinkertn@umich.edu if not s: continue 1052632Sstever@eecs.umich.edu yacc.parse(s) 106