1# ----------------------------------------------------------------------------- 2# calc.py 3# 4# A simple calculator with variables. Asks the user for more input and 5# demonstrates the use of the t_eof() rule. 6# ----------------------------------------------------------------------------- 7 8import sys 9sys.path.insert(0, "../..") 10 11if sys.version_info[0] >= 3: 12 raw_input = input 13 14tokens = ( 15 'NAME', 'NUMBER', 16) 17 18literals = ['=', '+', '-', '*', '/', '(', ')'] 19 20# Tokens 21 22t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' 23 24 25def t_NUMBER(t): 26 r'\d+' 27 t.value = int(t.value) 28 return t 29 30t_ignore = " \t" 31 32 33def t_newline(t): 34 r'\n+' 35 t.lexer.lineno += t.value.count("\n") 36 37 38def t_eof(t): 39 more = raw_input('... ') 40 if more: 41 t.lexer.input(more + '\n') 42 return t.lexer.token() 43 else: 44 return None 45 46 47def t_error(t): 48 print("Illegal character '%s'" % t.value[0]) 49 t.lexer.skip(1) 50 51# Build the lexer 52import ply.lex as lex 53lex.lex() 54 55# Parsing rules 56 57precedence = ( 58 ('left', '+', '-'), 59 ('left', '*', '/'), 60 ('right', 'UMINUS'), 61) 62 63# dictionary of names 64names = {} 65 66 67def p_statement_assign(p): 68 'statement : NAME "=" expression' 69 names[p[1]] = p[3] 70 71 72def p_statement_expr(p): 73 'statement : expression' 74 print(p[1]) 75 76 77def p_expression_binop(p): 78 '''expression : expression '+' expression 79 | expression '-' expression 80 | expression '*' expression 81 | expression '/' expression''' 82 if p[2] == '+': 83 p[0] = p[1] + p[3] 84 elif p[2] == '-': 85 p[0] = p[1] - p[3] 86 elif p[2] == '*': 87 p[0] = p[1] * p[3] 88 elif p[2] == '/': 89 p[0] = p[1] / p[3] 90 91 92def p_expression_uminus(p): 93 "expression : '-' expression %prec UMINUS" 94 p[0] = -p[2] 95 96 97def p_expression_group(p): 98 "expression : '(' expression ')'" 99 p[0] = p[2] 100 101 102def p_expression_number(p): 103 "expression : NUMBER" 104 p[0] = p[1] 105 106 107def p_expression_name(p): 108 "expression : NAME" 109 try: 110 p[0] = names[p[1]] 111 except LookupError: 112 print("Undefined name '%s'" % p[1]) 113 p[0] = 0 114 115 116def p_error(p): 117 if p: 118 print("Syntax error at '%s'" % p.value) 119 else: 120 print("Syntax error at EOF") 121 122import ply.yacc as yacc 123yacc.yacc() 124 125while 1: 126 try: 127 s = raw_input('calc > ') 128 except EOFError: 129 break 130 if not s: 131 continue 132 yacc.parse(s + '\n') 133