-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
137 lines (113 loc) · 4.07 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
'''
The overall BNF and Parse Tree Description:
<expression> ::= <term> + <expression> | <term> - <expression> | <term>
<term> := <factor> * <term> | <factor> / <term> | <factor>
<factor> ::= ( <expression> ) | <operand>
<operand> ::= 0|1|2|3|4|5|6|7|8|9
* Each node was implemented into a class
operand node - class OperandNode
factor node - class FactorNode
term node - class TermNode
Expression node - class ExpressionNode
* The main expression is then parsed with the class Parser
'''
# Operand Node
class OperandNode():
def __init__(self, value):
self.value = value
def evaluate(self):
return self.value
# Factor Node
class FactorNode():
def __init__(self, child):
self.child = child
def evaluate(self):
return self.child.evaluate()
# Term Node
class TermNode():
def __init__(self, left, operator = None, right = None):
self.left = left
self.right = right
self.operator = operator
def evaluate(self):
if not self.operator:
return self.left.evaluate()
elif self.operator == '*':
return self.left.evaluate() * self.right.evaluate()
elif self.operator == '/':
return self.left.evaluate() / self.right.evaluate()
# Expression Node
class ExpressionNode():
def __init__(self, left, operator = None, right = None):
self.left = left
self.operator = operator
self.right = right
def evaluate(self):
if not self.operator:
return self.left.evaluate()
elif self.operator == '+':
return self.left.evaluate() + self.right.evaluate()
elif self.operator == '-':
return self.left.evaluate() - self.right.evaluate()
# Main parser for the expression
class Parser:
# Sets the initial position and gets rid of all whitespaces
def __init__(self, input_string):
# Getting rid of the spaces entirely
self.input = input_string.replace(' ', '')
# Set beginner starting position
self.position = 0
# Go through the expressions
def parse_expression(self):
left = self.parse_term()
while self.current_char() == '+' or self.current_char() == '-':
operator = self.current_char()
self.move()
right = self.parse_term()
left = ExpressionNode(left, operator, right)
return left
# Go through the terms
def parse_term(self):
left = self.parse_fator()
while self.current_char() == '*' or self.current_char() == '/':
operator = self.current_char()
self.move()
right = self.parse_fator()
left = TermNode(left, operator, right)
return left
# Go through the factors
def parse_fator(self):
if self.current_char() == '(':
self.move()
expr = self.parse_expression()
if self.current_char() == ')':
self.move()
return FactorNode(expr)
else:
return self.parse_operand()
# Go through the operands
def parse_operand(self):
start = self.position
while self.current_char() is not None and self.current_char().isdigit():
self.move()
value = int(self.input[start:self.position])
return OperandNode(value)
# Evaluates the current character to be processed
def current_char(self):
if self.position >= len(self.input):
return None
return self.input[self.position]
def move(self):
self.position += 1
# Builds the expression tree
def expression_evaluation(input_string):
parser = Parser(input_string)
tree = parser.parse_expression()
return tree.evaluate()
# Usage
input_string = input("Please enter expression: ")
if not input_string:
input_string = "5 + 3 * 8" # Ans: 29
result = expression_evaluation(input_string)
print(f'Input Expression: {input_string}')
print(f'Result: {result}')