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,"../..")
17 if sys
.version_info
[0] >= 3:
21 import ply
.yacc
as yacc
26 Base class for a lexer/parser that has the rules defined as methods
32 def __init__(self
, **kw
):
33 self
.debug
= kw
.get('debug', 0)
36 modname
= os
.path
.split(os
.path
.splitext(__file__
)[0])[1] + "_" + self
.__class
__.__name
__
38 modname
= "parser"+"_"+self
.__class
__.__name
__
39 self
.debugfile
= modname
+ ".dbg"
40 self
.tabmodule
= modname
+ "_" + "parsetab"
41 #print self.debugfile, self.tabmodule
43 # Build the lexer and parser
44 lex
.lex(module
=self
, debug
=self
.debug
)
45 yacc
.yacc(module
=self
,
47 debugfile
=self
.debugfile
,
48 tabmodule
=self
.tabmodule
)
53 s
= raw_input('calc > ')
64 'PLUS','MINUS','EXP', 'TIMES','DIVIDE','EQUALS',
78 t_NAME
= r
'[a-zA-Z_][a-zA-Z0-9_]*'
80 def t_NUMBER(self
, t
):
83 t
.value
= int(t
.value
)
85 print("Integer value too large %s" % t
.value
)
87 #print "parsed number %s" % repr(t.value)
92 def t_newline(self
, t
):
94 t
.lexer
.lineno
+= t
.value
.count("\n")
97 print("Illegal character '%s'" % t
.value
[0])
103 ('left','PLUS','MINUS'),
104 ('left','TIMES','DIVIDE'),
109 def p_statement_assign(self
, p
):
110 'statement : NAME EQUALS expression'
111 self
.names
[p
[1]] = p
[3]
113 def p_statement_expr(self
, p
):
114 'statement : expression'
117 def p_expression_binop(self
, p
):
119 expression : expression PLUS expression
120 | expression MINUS expression
121 | expression TIMES expression
122 | expression DIVIDE expression
123 | expression EXP expression
125 #print [repr(p[i]) for i in range(0,4)]
126 if 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]
129 elif p
[2] == '/': p
[0] = p
[1] / p
[3]
130 elif p
[2] == '**': p
[0] = p
[1] ** p
[3]
132 def p_expression_uminus(self
, p
):
133 'expression : MINUS expression %prec UMINUS'
136 def p_expression_group(self
, p
):
137 'expression : LPAREN expression RPAREN'
140 def p_expression_number(self
, p
):
141 'expression : NUMBER'
144 def p_expression_name(self
, p
):
147 p
[0] = self
.names
[p
[1]]
149 print("Undefined name '%s'" % p
[1])
152 def p_error(self
, p
):
154 print("Syntax error at '%s'" % p
.value
)
156 print("Syntax error at EOF")
158 if __name__
== '__main__':