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
10 # -----------------------------------------------------------------------------
13 sys
.path
.insert(0,"../..")
17 import ply
.yacc
as yacc
22 Base class for a lexer/parser that has the rules defined as methods
27 def __init__(self
, **kw
):
28 self
.debug
= kw
.get('debug', 0)
31 modname
= os
.path
.split(os
.path
.splitext(__file__
)[0])[1] + "_" + self
.__class
__.__name
__
33 modname
= "parser"+"_"+self
.__class
__.__name
__
34 self
.debugfile
= modname
+ ".dbg"
35 self
.tabmodule
= modname
+ "_" + "parsetab"
36 #print self.debugfile, self.tabmodule
38 # Build the lexer and parser
39 lex
.lex(module
=self
, debug
=self
.debug
)
40 yacc
.yacc(module
=self
,
42 debugfile
=self
.debugfile
,
43 tabmodule
=self
.tabmodule
)
48 s
= raw_input('calc > ')
59 'PLUS','MINUS','EXP', 'TIMES','DIVIDE','EQUALS',
73 t_NAME
= r
'[a-zA-Z_][a-zA-Z0-9_]*'
75 def t_NUMBER(self
, t
):
78 t
.value
= int(t
.value
)
80 print "Integer value too large", t
.value
82 #print "parsed number %s" % repr(t.value)
87 def t_newline(self
, t
):
89 t
.lexer
.lineno
+= t
.value
.count("\n")
92 print "Illegal character '%s'" % t
.value
[0]
98 ('left','PLUS','MINUS'),
99 ('left','TIMES','DIVIDE'),
104 def p_statement_assign(self
, p
):
105 'statement : NAME EQUALS expression'
106 self
.names
[p
[1]] = p
[3]
108 def p_statement_expr(self
, p
):
109 'statement : expression'
112 def p_expression_binop(self
, p
):
114 expression : expression PLUS expression
115 | expression MINUS expression
116 | expression TIMES expression
117 | expression DIVIDE expression
118 | expression EXP expression
120 #print [repr(p[i]) for i in range(0,4)]
121 if p
[2] == '+' : p
[0] = p
[1] + p
[3]
122 elif p
[2] == '-': p
[0] = p
[1] - p
[3]
123 elif p
[2] == '*': p
[0] = p
[1] * p
[3]
124 elif p
[2] == '/': p
[0] = p
[1] / p
[3]
125 elif p
[2] == '**': p
[0] = p
[1] ** p
[3]
127 def p_expression_uminus(self
, p
):
128 'expression : MINUS expression %prec UMINUS'
131 def p_expression_group(self
, p
):
132 'expression : LPAREN expression RPAREN'
135 def p_expression_number(self
, p
):
136 'expression : NUMBER'
139 def p_expression_name(self
, p
):
142 p
[0] = self
.names
[p
[1]]
144 print "Undefined name '%s'" % p
[1]
147 def p_error(self
, p
):
148 print "Syntax error at '%s'" % p
.value
150 if __name__
== '__main__':