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