@@ -59,10 +59,20 @@ def __init__(self, expression, func=None):
5959 :param expression: mathematical expression as string
6060 """
6161 # Validate on expression and raise exception if not true
62- expression = expression .replace (" " , "" )
62+
63+ # if " " in expression:
64+ # raise ExpressionFormatException("Expression should not de with spaces")
65+
66+ # expression = expression.replace(" ", "")
67+
6368 if not expression :
6469 raise NoExpressionException ("The expression was not passed" )
6570
71+ # if expression.startswith("--") or expression.startswith("=") or expression.startswith("+"):
72+ # raise ExpressionFormatException("The expression bad format")
73+ # if expression.endswith("-"):
74+ # raise ExpressionFormatException("The expression bad format")
75+
6676 # TODO: comment
6777 self ._mathematical_functions = {
6878 name : val for name , val in getmembers (math ) if type (val ).__name__ == "builtin_function_or_method"
@@ -76,16 +86,16 @@ def __init__(self, expression, func=None):
7686
7787 self ._func = None
7888 if func :
89+ func = func .strip ()
7990 if func not in self ._mathematical_functions :
80- raise UnsupportedMathematicalFunctionException ("We do not support '{}' function" .format (self . _func ))
91+ raise UnsupportedMathematicalFunctionException ("We do not support '{}' function" .format (func ))
8192 self ._func = self ._mathematical_functions .get (func )
8293
8394 self ._expression = []
8495
8596 bracket_level = 0
8697 item = []
8798 last_mathematical_action = None
88- bracket_closed = False
8999 bracket_content = []
90100 self ._comparison_operation = False
91101 self ._multivalue = False
@@ -116,19 +126,32 @@ def __init__(self, expression, func=None):
116126 else :
117127 raise ExpressionFormatException ("After comparison operation expression or number are expected" )
118128
119- # Look for multivalue expression
120- if "(" not in expression and ")" not in expression and "," in expression :
121- if not self ._func :
122- raise ExpressionFormatException ("Commas allowed only in function calls." )
123- parts = expression .split ("," )
124- self ._expression = [Element (i ) for i in parts ]
125- self ._multivalue = True
129+ # Look for commas in expression
130+ start_index = 0
131+ multivalue_items = []
132+ for i , c in enumerate (expression ):
133+ # increase bracket level
134+ if c == "(" :
135+ bracket_level += 1
136+ # decrease bracket level
137+ elif c == ")" :
138+ bracket_level -= 1
139+ elif c == "," and bracket_level == 0 :
140+ self ._multivalue = True
141+ multivalue_items .append (Element (expression [start_index :i ]))
142+ start_index = i + 1
143+ if self ._multivalue :
144+ self ._expression = multivalue_items
145+ self ._expression .append (Element (expression [start_index :]))
126146 return
127147
128148 # Validate format expression and raise exception if it is not valid
129149 item = []
150+ bracket_closed = False
130151 for i in expression :
131- if bracket_closed :
152+ if bracket_closed and bracket_level == 0 :
153+ if i == " " :
154+ continue
132155 if i not in self .MATH_ACTIONS and i != ")" :
133156 raise ExpressionFormatException ("After bracket closed 'math sign' or "
134157 "another bracket close are expected" )
@@ -163,10 +186,11 @@ def __init__(self, expression, func=None):
163186 else :
164187 if i in self .MATH_ACTIONS :
165188 if item :
166- item = "" .join (item )
167- if item in self ._mathematical_constants :
168- item = self ._mathematical_constants [item ]
169- self ._expression .append (float (item ))
189+ item = "" .join (item ).strip ()
190+ if item :
191+ if item in self ._mathematical_constants :
192+ item = self ._mathematical_constants [item ]
193+ self ._expression .append (float (item ))
170194 item = []
171195
172196 # Handle double mathematical operation
@@ -209,6 +233,8 @@ def _calculate_boolean_expression(self):
209233 boolean_value = True
210234 for i , v in enumerate (self ._expression ):
211235 if isinstance (v , str ):
236+ if i <= 0 :
237+ raise ExpressionFormatException ("Comparison could be at the first position" )
212238 if v == ">=" :
213239 if not self ._expression [i - 1 ] >= self ._expression [i + 1 ]:
214240 boolean_value = False
@@ -243,17 +269,16 @@ def _calculate_mathematical_expression(self):
243269 first_negative = True
244270 del self ._expression [0 ]
245271
246- # Calculate power mathematical operation
247- self ._expression .reverse ()
248- while True :
249- try :
250- index = self ._expression .index ("^" )
251- self ._expression .pop (index )
252- power = self ._expression .pop (index - 1 )
253- self ._expression [index - 1 ] **= power
254- except ValueError :
255- break
256- self ._expression .reverse ()
272+ i = len (self ._expression ) - 1
273+ while i >= 0 :
274+ el = self ._expression [i ]
275+ if el == "^" :
276+ self ._expression .pop (i )
277+ power = self ._expression .pop (i )
278+ if power == "-" :
279+ power = - self ._expression .pop (i )
280+ self ._expression [i - 1 ] **= power
281+ i -= 1
257282
258283 # Calculate high priority mathematical operations
259284 new_expression = []
@@ -288,8 +313,8 @@ def _calculate_mathematical_expression(self):
288313 if isinstance (i , str ):
289314 if i in ("+" , "-" ,):
290315 operation = i
291- else :
292- raise UnsupportedMathematicalOperationException ("We do not support '{}' operation" .format (i ))
316+ # else:
317+ # raise UnsupportedMathematicalOperationException("We do not support '{}' operation".format(i))
293318 elif operation :
294319 if operation == "+" :
295320 value += i
@@ -312,35 +337,94 @@ def value(self):
312337 """
313338
314339 # Validate mathematical operations and calculate nested expressions
315- last_operation = None
340+ # i = len(self._expression) - 1
341+ # last_operation = None
342+ # print(">>", self._expression)
343+ # while i >= 0:
344+ # el = self._expression[i]
345+ # if isinstance(el, Element):
346+ # self._expression[i] = el.value()
347+ # last_operation = None
348+ # elif isinstance(el, str):
349+
316350 for i , v in enumerate (self ._expression ):
317351 if isinstance (v , Element ):
318352 self ._expression [i ] = v .value ()
319353 if isinstance (v , str ):
320- if v not in ( "<=" , ">=" , "==" , "!=" , "<>" , "**" , "// " ):
354+ if v . startswith ( "- " ):
321355 if len (v ) > 1 :
322356 if len (v ) % 2 == 0 :
323357 self ._expression [i ] = "+"
324358 else :
325359 self ._expression [i ] = "-"
360+ if v .startswith ("+" ):
361+ self ._expression [i ] = "+"
326362
327- if last_operation and v in ("+" , "-" ,):
328- if last_operation == "+" and v == "-" :
329- self ._expression [i ] = "-"
330- del self ._expression [i - 1 ]
331- elif last_operation == "-" and v == "+" :
332- self ._expression [i ] = "-"
333- del self ._expression [i ]
334- elif last_operation and v in self .MATH_ACTIONS :
335- raise DoubleOperationException ("'{so}' operation follows '{fo}'" .format (
336- so = last_operation ,
337- fo = v
338- ))
339-
340- if v in self .MATH_ACTIONS :
341- last_operation = v
342- else :
363+ expression = []
364+ last_operation = None
365+ sign = None
366+ for i , v in enumerate (self ._expression ):
367+ if isinstance (v , str ):
368+ if last_operation :
369+ if last_operation in ("+" , "-" ,):
370+ if v in ("+" , "-" ):
371+ if last_operation == v :
372+ last_operation = "+"
373+ else :
374+ last_operation = "-"
375+ else :
376+ raise DoubleOperationException ("'{so}' operation follows '{fo}'" .format (
377+ so = last_operation ,
378+ fo = v
379+ ))
380+ else :
381+ if v not in ("+" , "-" ):
382+ raise DoubleOperationException ("'{so}' operation follows '{fo}'" .format (
383+ so = last_operation ,
384+ fo = v
385+ ))
386+ if sign :
387+ if sign == v :
388+ sign = "+"
389+ else :
390+ sign = "-"
391+ else :
392+ sign = v
393+ else :
394+ last_operation = v
395+ continue
396+
397+ if last_operation :
398+ expression .append (last_operation )
343399 last_operation = None
400+ if sign == "-" :
401+ v = - v
402+ sign = None
403+ expression .append (v )
404+
405+ if last_operation or sign :
406+ raise ExpressionFormatException ("Expression finishes with mathematical operation." )
407+
408+ self ._expression = expression
409+
410+ # for i, v in enumerate(self._expression):
411+ # if isinstance(v, str):
412+ # if last_operation and v in ("+", "-",):
413+ # if last_operation == "+" and v == "-":
414+ # self._expression[i] = "-"
415+ # elif last_operation == "-" and v == "+":
416+ # self._expression[i] = "-"
417+ # del self._expression[i - 1]
418+ # elif last_operation and v in self.MATH_ACTIONS:
419+ # raise DoubleOperationException("'{so}' operation follows '{fo}'".format(
420+ # so=last_operation,
421+ # fo=v
422+ # ))
423+
424+ # if v in self.MATH_ACTIONS:
425+ # last_operation = v
426+ # else:
427+ # last_operation = None
344428
345429 # Evaluate comparison expression
346430 if self ._comparison_operation :
@@ -351,9 +435,7 @@ def value(self):
351435 try :
352436 return self ._func (* self ._expression )
353437 except TypeError :
354- raise ExpressionFormatException ("Expected 2 arguments, got 3 : '{}'" .format (self ._func ))
438+ raise ExpressionFormatException ("Expected 2 arguments: '{}'" .format (self ._func ))
355439
356- try :
357- return self ._calculate_mathematical_expression ()
358- except TypeError :
359- raise UnsupportedMathematicalOperationException ("We do not support '{}' operation" .format (i ))
440+ # print(self._expression)
441+ return self ._calculate_mathematical_expression ()
0 commit comments