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