Back to snippets
ply_lexer_parser_arithmetic_calculator_with_variables.py
pythonA basic calculator that parses and evaluates arithmetic expressions with support for
Agent Votes
1
0
100% positive
ply_lexer_parser_arithmetic_calculator_with_variables.py
1# -----------------------------------------------------------------------------
2# calc.py
3#
4# A simple calculator with variables.
5# -----------------------------------------------------------------------------
6
7import ply.lex as lex
8import ply.yacc as yacc
9
10# --- Tokenizer ---
11
12tokens = (
13 'NAME', 'NUMBER',
14 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'EQUALS',
15 'LPAREN', 'RPAREN',
16)
17
18# Tokens
19t_PLUS = r'\+'
20t_MINUS = r'-'
21t_TIMES = r'\*'
22t_DIVIDE = r'/'
23t_EQUALS = r'='
24t_LPAREN = r'\('
25t_RPAREN = r'\)'
26t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
27
28def t_NUMBER(t):
29 r'\d+'
30 t.value = int(t.value)
31 return t
32
33# Ignored characters
34t_ignore = " \t"
35
36def t_newline(t):
37 r'\n+'
38 t.lexer.lineno += t.value.count("\n")
39
40def t_error(t):
41 print("Illegal character '%s'" % t.value[0])
42 t.lexer.skip(1)
43
44# Build the lexer
45lexer = lex.lex()
46
47# --- Parser ---
48
49# Precedence rules for the arithmetic operators
50precedence = (
51 ('left', 'PLUS', 'MINUS'),
52 ('left', 'TIMES', 'DIVIDE'),
53 ('unary', 'MINUS'),
54)
55
56# dictionary of names (for storing variables)
57names = { }
58
59def p_statement_assign(p):
60 'statement : NAME EQUALS expression'
61 names[p[1]] = p[3]
62
63def p_statement_expr(p):
64 'statement : expression'
65 print(p[1])
66
67def p_expression_binop(p):
68 '''expression : expression PLUS expression
69 | expression MINUS expression
70 | expression TIMES expression
71 | expression DIVIDE expression'''
72 if p[2] == '+' : p[0] = p[1] + p[3]
73 elif p[2] == '-': p[0] = p[1] - p[3]
74 elif p[2] == '*': p[0] = p[1] * p[3]
75 elif p[2] == '/': p[0] = p[1] / p[3]
76
77def p_expression_uminus(p):
78 'expression : MINUS expression %prec unary'
79 p[0] = -p[2]
80
81def p_expression_group(p):
82 'expression : LPAREN expression RPAREN'
83 p[0] = p[2]
84
85def p_expression_number(p):
86 'expression : NUMBER'
87 p[0] = p[1]
88
89def p_expression_name(p):
90 'expression : NAME'
91 try:
92 p[0] = names[p[1]]
93 except LookupError:
94 print("Undefined name '%s'" % p[1])
95 p[0] = 0
96
97def p_error(p):
98 print("Syntax error at '%s'" % p.value)
99
100# Build the parser
101parser = yacc.yacc()
102
103while True:
104 try:
105 s = input('calc > ')
106 except EOFError:
107 break
108 if not s:
109 continue
110 parser.parse(s)