1# -----------------------------------------------------------------------------
2# calc.py
3#
4# This example shows how to run the parser in a debugging mode
5# with output routed to a logging object.
6# -----------------------------------------------------------------------------
7
8import sys
9sys.path.insert(0,"../..")
10
11if sys.version_info[0] >= 3:
12    raw_input = input
13
14tokens = (
15    'NAME','NUMBER',
16    )
17
18literals = ['=','+','-','*','/', '(',')']
19
20# Tokens
21
22t_NAME    = r'[a-zA-Z_][a-zA-Z0-9_]*'
23
24def t_NUMBER(t):
25    r'\d+'
26    t.value = int(t.value)
27    return t
28
29t_ignore = " \t"
30
31def t_newline(t):
32    r'\n+'
33    t.lexer.lineno += t.value.count("\n")
34
35def t_error(t):
36    print("Illegal character '%s'" % t.value[0])
37    t.lexer.skip(1)
38
39# Build the lexer
40import ply.lex as lex
41lex.lex()
42
43# Parsing rules
44
45precedence = (
46    ('left','+','-'),
47    ('left','*','/'),
48    ('right','UMINUS'),
49    )
50
51# dictionary of names
52names = { }
53
54def p_statement_assign(p):
55    'statement : NAME "=" expression'
56    names[p[1]] = p[3]
57
58def p_statement_expr(p):
59    'statement : expression'
60    print(p[1])
61
62def p_expression_binop(p):
63    '''expression : expression '+' expression
64                  | expression '-' expression
65                  | expression '*' expression
66                  | expression '/' expression'''
67    if p[2] == '+'  : p[0] = p[1] + p[3]
68    elif p[2] == '-': p[0] = p[1] - p[3]
69    elif p[2] == '*': p[0] = p[1] * p[3]
70    elif p[2] == '/': p[0] = p[1] / p[3]
71
72def p_expression_uminus(p):
73    "expression : '-' expression %prec UMINUS"
74    p[0] = -p[2]
75
76def p_expression_group(p):
77    "expression : '(' expression ')'"
78    p[0] = p[2]
79
80def p_expression_number(p):
81    "expression : NUMBER"
82    p[0] = p[1]
83
84def p_expression_name(p):
85    "expression : NAME"
86    try:
87        p[0] = names[p[1]]
88    except LookupError:
89        print("Undefined name '%s'" % p[1])
90        p[0] = 0
91
92def p_error(p):
93    if p:
94        print("Syntax error at '%s'" % p.value)
95    else:
96        print("Syntax error at EOF")
97
98import ply.yacc as yacc
99yacc.yacc()
100
101import logging
102logging.basicConfig(
103    level=logging.INFO,
104    filename="parselog.txt"
105)
106
107while 1:
108    try:
109        s = raw_input('calc > ')
110    except EOFError:
111        break
112    if not s: continue
113    yacc.parse(s,debug=logging.getLogger())
114