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    '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
114