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 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', 142632Sstever@eecs.umich.edu 'LPAREN','RPAREN', 152632Sstever@eecs.umich.edu ) 162632Sstever@eecs.umich.edu 172632Sstever@eecs.umich.edu# Tokens 182632Sstever@eecs.umich.edu 192632Sstever@eecs.umich.edut_PLUS = r'\+' 202632Sstever@eecs.umich.edut_MINUS = r'-' 212632Sstever@eecs.umich.edut_TIMES = r'\*' 222632Sstever@eecs.umich.edut_DIVIDE = r'/' 232632Sstever@eecs.umich.edut_EQUALS = r'=' 242632Sstever@eecs.umich.edut_LPAREN = r'\(' 252632Sstever@eecs.umich.edut_RPAREN = r'\)' 262632Sstever@eecs.umich.edut_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' 272632Sstever@eecs.umich.edu 282632Sstever@eecs.umich.edudef t_NUMBER(t): 292632Sstever@eecs.umich.edu r'\d+' 302632Sstever@eecs.umich.edu try: 312632Sstever@eecs.umich.edu t.value = int(t.value) 322632Sstever@eecs.umich.edu except ValueError: 332632Sstever@eecs.umich.edu print "Integer value too large", t.value 342632Sstever@eecs.umich.edu t.value = 0 352632Sstever@eecs.umich.edu return t 362632Sstever@eecs.umich.edu 372632Sstever@eecs.umich.edut_ignore = " \t" 382632Sstever@eecs.umich.edu 392632Sstever@eecs.umich.edudef t_newline(t): 402632Sstever@eecs.umich.edu r'\n+' 414479Sbinkertn@umich.edu t.lexer.lineno += t.value.count("\n") 422632Sstever@eecs.umich.edu 432632Sstever@eecs.umich.edudef t_error(t): 442632Sstever@eecs.umich.edu print "Illegal character '%s'" % t.value[0] 454479Sbinkertn@umich.edu t.lexer.skip(1) 462632Sstever@eecs.umich.edu 472632Sstever@eecs.umich.edu# Build the lexer 484479Sbinkertn@umich.eduimport ply.lex as lex 492632Sstever@eecs.umich.edulex.lex(optimize=1) 502632Sstever@eecs.umich.edu 512632Sstever@eecs.umich.edu# Parsing rules 522632Sstever@eecs.umich.edu 532632Sstever@eecs.umich.eduprecedence = ( 542632Sstever@eecs.umich.edu ('left','PLUS','MINUS'), 552632Sstever@eecs.umich.edu ('left','TIMES','DIVIDE'), 562632Sstever@eecs.umich.edu ('right','UMINUS'), 572632Sstever@eecs.umich.edu ) 582632Sstever@eecs.umich.edu 592632Sstever@eecs.umich.edu# dictionary of names 602632Sstever@eecs.umich.edunames = { } 612632Sstever@eecs.umich.edu 622632Sstever@eecs.umich.edudef p_statement_assign(t): 632632Sstever@eecs.umich.edu 'statement : NAME EQUALS expression' 642632Sstever@eecs.umich.edu names[t[1]] = t[3] 652632Sstever@eecs.umich.edu 662632Sstever@eecs.umich.edudef p_statement_expr(t): 672632Sstever@eecs.umich.edu 'statement : expression' 682632Sstever@eecs.umich.edu print t[1] 692632Sstever@eecs.umich.edu 702632Sstever@eecs.umich.edudef p_expression_binop(t): 712632Sstever@eecs.umich.edu '''expression : expression PLUS expression 722632Sstever@eecs.umich.edu | expression MINUS expression 732632Sstever@eecs.umich.edu | expression TIMES expression 742632Sstever@eecs.umich.edu | expression DIVIDE expression''' 752632Sstever@eecs.umich.edu if t[2] == '+' : t[0] = t[1] + t[3] 762632Sstever@eecs.umich.edu elif t[2] == '-': t[0] = t[1] - t[3] 772632Sstever@eecs.umich.edu elif t[2] == '*': t[0] = t[1] * t[3] 782632Sstever@eecs.umich.edu elif t[2] == '/': t[0] = t[1] / t[3] 792632Sstever@eecs.umich.edu elif t[2] == '<': t[0] = t[1] < t[3] 802632Sstever@eecs.umich.edu 812632Sstever@eecs.umich.edudef p_expression_uminus(t): 822632Sstever@eecs.umich.edu 'expression : MINUS expression %prec UMINUS' 832632Sstever@eecs.umich.edu t[0] = -t[2] 842632Sstever@eecs.umich.edu 852632Sstever@eecs.umich.edudef p_expression_group(t): 862632Sstever@eecs.umich.edu 'expression : LPAREN expression RPAREN' 872632Sstever@eecs.umich.edu t[0] = t[2] 882632Sstever@eecs.umich.edu 892632Sstever@eecs.umich.edudef p_expression_number(t): 902632Sstever@eecs.umich.edu 'expression : NUMBER' 912632Sstever@eecs.umich.edu t[0] = t[1] 922632Sstever@eecs.umich.edu 932632Sstever@eecs.umich.edudef p_expression_name(t): 942632Sstever@eecs.umich.edu 'expression : NAME' 952632Sstever@eecs.umich.edu try: 962632Sstever@eecs.umich.edu t[0] = names[t[1]] 972632Sstever@eecs.umich.edu except LookupError: 982632Sstever@eecs.umich.edu print "Undefined name '%s'" % t[1] 992632Sstever@eecs.umich.edu t[0] = 0 1002632Sstever@eecs.umich.edu 1012632Sstever@eecs.umich.edudef p_error(t): 1022632Sstever@eecs.umich.edu print "Syntax error at '%s'" % t.value 1032632Sstever@eecs.umich.edu 1044479Sbinkertn@umich.eduimport ply.yacc as yacc 1052632Sstever@eecs.umich.eduyacc.yacc(optimize=1) 1062632Sstever@eecs.umich.edu 1072632Sstever@eecs.umich.eduwhile 1: 1082632Sstever@eecs.umich.edu try: 1092632Sstever@eecs.umich.edu s = raw_input('calc > ') 1102632Sstever@eecs.umich.edu except EOFError: 1112632Sstever@eecs.umich.edu break 1122632Sstever@eecs.umich.edu yacc.parse(s) 1132632Sstever@eecs.umich.edu 114