6598f5844f8296f215e48f6124c3e5807b0f5435
[platform/framework/web/lwnode.git] /
1 # -----------------------------------------------------------------------------
2 # calc.py
3 #
4 # A calculator parser that makes use of closures. The function make_calculator()
5 # returns a function that accepts an input string and returns a result.  All 
6 # lexing rules, parsing rules, and internal state are held inside the function.
7 # -----------------------------------------------------------------------------
8
9 import sys
10 sys.path.insert(0,"../..")
11
12 if sys.version_info[0] >= 3:
13     raw_input = input
14
15 # Make a calculator function
16
17 def make_calculator():
18     import ply.lex as lex
19     import ply.yacc as yacc
20
21     # ------- Internal calculator state
22
23     variables = { }       # Dictionary of stored variables
24
25     # ------- Calculator tokenizing rules
26
27     tokens = (
28         'NAME','NUMBER',
29     )
30
31     literals = ['=','+','-','*','/', '(',')']
32
33     t_ignore = " \t"
34
35     t_NAME    = r'[a-zA-Z_][a-zA-Z0-9_]*'
36
37     def t_NUMBER(t):
38         r'\d+'
39         t.value = int(t.value)
40         return t
41
42     def t_newline(t):
43         r'\n+'
44         t.lexer.lineno += t.value.count("\n")
45     
46     def t_error(t):
47         print("Illegal character '%s'" % t.value[0])
48         t.lexer.skip(1)
49     
50     # Build the lexer
51     lexer = lex.lex()
52
53     # ------- Calculator parsing rules
54
55     precedence = (
56         ('left','+','-'),
57         ('left','*','/'),
58         ('right','UMINUS'),
59     )
60
61     def p_statement_assign(p):
62         'statement : NAME "=" expression'
63         variables[p[1]] = p[3]
64         p[0] = None
65
66     def p_statement_expr(p):
67         'statement : expression'
68         p[0] = p[1]
69
70     def p_expression_binop(p):
71         '''expression : expression '+' expression
72                       | expression '-' expression
73                       | expression '*' expression
74                       | expression '/' expression'''
75         if p[2] == '+'  : p[0] = p[1] + p[3]
76         elif p[2] == '-': p[0] = p[1] - p[3]
77         elif p[2] == '*': p[0] = p[1] * p[3]
78         elif p[2] == '/': p[0] = p[1] / p[3]
79
80     def p_expression_uminus(p):
81         "expression : '-' expression %prec UMINUS"
82         p[0] = -p[2]
83
84     def p_expression_group(p):
85         "expression : '(' expression ')'"
86         p[0] = p[2]
87
88     def p_expression_number(p):
89         "expression : NUMBER"
90         p[0] = p[1]
91
92     def p_expression_name(p):
93         "expression : NAME"
94         try:
95             p[0] = variables[p[1]]
96         except LookupError:
97             print("Undefined name '%s'" % p[1])
98             p[0] = 0
99
100     def p_error(p):
101         if p:
102             print("Syntax error at '%s'" % p.value)
103         else:
104             print("Syntax error at EOF")
105
106
107     # Build the parser
108     parser = yacc.yacc()
109
110     # ------- Input function 
111     
112     def input(text):
113         result = parser.parse(text,lexer=lexer)
114         return result
115
116     return input
117
118 # Make a calculator object and use it
119 calc = make_calculator()
120
121 while True:
122     try:
123         s = raw_input("calc > ")
124     except EOFError:
125         break
126     r = calc(s)
127     if r:
128         print(r)
129
130