3 # -----------------------------------------------------------------------------
6 # A simple calculator with variables. This is from O'Reilly's
7 # "Lex and Yacc", p. 63.
9 # Class-based example contributed to PLY by David McNab.
11 # Modified to use new-style classes. Test case.
12 # -----------------------------------------------------------------------------
15 sys
.path
.insert(0,"../..")
19 import ply
.yacc
as yacc
24 Base class for a lexer/parser that has the rules defined as methods
30 def __init__(self
, **kw
):
31 self
.debug
= kw
.get('debug', 0)
34 modname
= os
.path
.split(os
.path
.splitext(__file__
)[0])[1] + "_" + self
.__class
__.__name
__
36 modname
= "parser"+"_"+self
.__class
__.__name
__
37 self
.debugfile
= modname
+ ".dbg"
38 self
.tabmodule
= modname
+ "_" + "parsetab"
39 #print self.debugfile, self.tabmodule
41 # Build the lexer and parser
42 lex
.lex(module
=self
, debug
=self
.debug
)
43 yacc
.yacc(module
=self
,
45 debugfile
=self
.debugfile
,
46 tabmodule
=self
.tabmodule
)
51 s
= raw_input('calc > ')
62 'PLUS','MINUS','EXP', 'TIMES','DIVIDE','EQUALS',
76 t_NAME
= r
'[a-zA-Z_][a-zA-Z0-9_]*'
78 def t_NUMBER(self
, t
):
81 t
.value
= int(t
.value
)
83 print "Integer value too large", t
.value
85 #print "parsed number %s" % repr(t.value)
90 def t_newline(self
, t
):
92 t
.lexer
.lineno
+= t
.value
.count("\n")
95 print "Illegal character '%s'" % t
.value
[0]
101 ('left','PLUS','MINUS'),
102 ('left','TIMES','DIVIDE'),
107 def p_statement_assign(self
, p
):
108 'statement : NAME EQUALS expression'
109 self
.names
[p
[1]] = p
[3]
111 def p_statement_expr(self
, p
):
112 'statement : expression'
115 def p_expression_binop(self
, p
):
117 expression : expression PLUS expression
118 | expression MINUS expression
119 | expression TIMES expression
120 | expression DIVIDE expression
121 | expression EXP expression
123 #print [repr(p[i]) for i in range(0,4)]
124 if p
[2] == '+' : p
[0] = p
[1] + p
[3]
125 elif p
[2] == '-': p
[0] = p
[1] - p
[3]
126 elif p
[2] == '*': p
[0] = p
[1] * p
[3]
127 elif p
[2] == '/': p
[0] = p
[1] / p
[3]
128 elif p
[2] == '**': p
[0] = p
[1] ** p
[3]
130 def p_expression_uminus(self
, p
):
131 'expression : MINUS expression %prec UMINUS'
134 def p_expression_group(self
, p
):
135 'expression : LPAREN expression RPAREN'
138 def p_expression_number(self
, p
):
139 'expression : NUMBER'
142 def p_expression_name(self
, p
):
145 p
[0] = self
.names
[p
[1]]
147 print "Undefined name '%s'" % p
[1]
150 def p_error(self
, p
):
151 print "Syntax error at '%s'" % p
.value
153 if __name__
== '__main__':