calc.py revision 2632:1bb2f91485ea
1# ----------------------------------------------------------------------------- 2# calc.py 3# 4# A simple calculator with variables. This is from O'Reilly's 5# "Lex and Yacc", p. 63. 6# ----------------------------------------------------------------------------- 7 8tokens = ( 9 'NAME','NUMBER', 10 'PLUS','MINUS','TIMES','DIVIDE','EQUALS', 11 'LPAREN','RPAREN', 12 ) 13 14# Tokens 15 16t_PLUS = r'\+' 17t_MINUS = r'-' 18t_TIMES = r'\*' 19t_DIVIDE = r'/' 20t_EQUALS = r'=' 21t_LPAREN = r'\(' 22t_RPAREN = r'\)' 23t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' 24 25def t_NUMBER(t): 26 r'\d+' 27 try: 28 t.value = int(t.value) 29 except ValueError: 30 print "Integer value too large", t.value 31 t.value = 0 32 return t 33 34t_ignore = " \t" 35 36def t_newline(t): 37 r'\n+' 38 t.lineno += t.value.count("\n") 39 40def t_error(t): 41 print "Illegal character '%s'" % t.value[0] 42 t.skip(1) 43 44# Build the lexer 45import lex 46lex.lex(optimize=1) 47 48# Parsing rules 49 50precedence = ( 51 ('left','PLUS','MINUS'), 52 ('left','TIMES','DIVIDE'), 53 ('right','UMINUS'), 54 ) 55 56# dictionary of names 57names = { } 58 59def p_statement_assign(t): 60 'statement : NAME EQUALS expression' 61 names[t[1]] = t[3] 62 63def p_statement_expr(t): 64 'statement : expression' 65 print t[1] 66 67def p_expression_binop(t): 68 '''expression : expression PLUS expression 69 | expression MINUS expression 70 | expression TIMES expression 71 | expression DIVIDE expression''' 72 if t[2] == '+' : t[0] = t[1] + t[3] 73 elif t[2] == '-': t[0] = t[1] - t[3] 74 elif t[2] == '*': t[0] = t[1] * t[3] 75 elif t[2] == '/': t[0] = t[1] / t[3] 76 elif t[2] == '<': t[0] = t[1] < t[3] 77 78def p_expression_uminus(t): 79 'expression : MINUS expression %prec UMINUS' 80 t[0] = -t[2] 81 82def p_expression_group(t): 83 'expression : LPAREN expression RPAREN' 84 t[0] = t[2] 85 86def p_expression_number(t): 87 'expression : NUMBER' 88 t[0] = t[1] 89 90def p_expression_name(t): 91 'expression : NAME' 92 try: 93 t[0] = names[t[1]] 94 except LookupError: 95 print "Undefined name '%s'" % t[1] 96 t[0] = 0 97 98def p_error(t): 99 print "Syntax error at '%s'" % t.value 100 101import yacc 102yacc.yacc(optimize=1) 103 104while 1: 105 try: 106 s = raw_input('calc > ') 107 except EOFError: 108 break 109 yacc.parse(s) 110 111