Skip to content

Commit 8c5d447

Browse files
committed
Added method check_expression
* Lot of tests has been added to the application checking this new function. It has to check if a individual is valid in a test in the GUI and before adding a new first individual
1 parent 8bbe0b6 commit 8c5d447

File tree

2 files changed

+209
-1
lines changed

2 files changed

+209
-1
lines changed

MLC/Common/LispTreeExpr/LispTreeExpr.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,44 @@
55
from MLC.Common.LispTreeExpr.OperationNodes import OpNodeFactory
66

77

8+
class ExprException(Exception):
9+
pass
10+
11+
12+
class OperationNotFoundException(Exception):
13+
14+
def __init__(self, operation, expression):
15+
Exception.__init__(self,
16+
"[EXPR_EXCEPTION] An invalid operation was found. "
17+
"Operation: {0} - Expression: {0}"
18+
.format(expression))
19+
20+
21+
class RootNotFoundExprException(Exception):
22+
23+
def __init__(self, expression):
24+
Exception.__init__(self,
25+
"[EXPR_EXCEPTION] Root node was not found. Expression: {0}"
26+
.format(expression))
27+
28+
29+
class NotBalancedParanthesisException(Exception):
30+
31+
def __init__(self, expression):
32+
Exception.__init__(self,
33+
"[EXPR_EXCEPTION] Parenthesis in expression are not okay. Expression: {0}"
34+
.format(expression))
35+
36+
37+
class OperationArgumentsAmountException(Exception):
38+
39+
def __init__(self, expression):
40+
Exception.__init__(self,
41+
"[EXPR_EXCEPTION] The amount of arguments processed by "
42+
"the operations is not correct . Expression: {0}"
43+
.format(expression))
44+
45+
846
class LispTreeExpr(object):
947

1048
def __init__(self, expr):
@@ -25,6 +63,88 @@ def __init__(self, expr):
2563
if Config.get_instance().getboolean('OPTIMIZATION', 'simplify'):
2664
self.simplify_tree()
2765

66+
@staticmethod
67+
def check_expression(expression):
68+
# Remove leading and trailing spaces
69+
expression = expression.strip()
70+
71+
# Remove two or more whitespaces with one
72+
expression = ' '.join(expression.split())
73+
74+
# If there are spaces before a ')', remove them
75+
expression = expression.replace(' )', ')')
76+
77+
# Check the expression to start with the substring (root
78+
if expression.find("(root") != 0:
79+
raise RootNotFoundExprException(expression)
80+
81+
# Check the amount of parenthesis to be balanced
82+
open_parenthesis = "("
83+
close_parenthesis = ")"
84+
string_to_find = open_parenthesis
85+
counter = 0
86+
for index in xrange(len(expression)):
87+
if expression[index] == open_parenthesis:
88+
counter += 1
89+
elif expression[index] == close_parenthesis:
90+
counter -= 1
91+
92+
if counter != 0:
93+
raise NotBalancedParanthesisException(expression)
94+
95+
# Now the expression is correct. Check the amount of arguments to be correct
96+
def check_operands(expr):
97+
print "Init - Expression: {0}".format(expr)
98+
op_string = expr[1:expr.find(' ')]
99+
expr_op = None
100+
try:
101+
expr_op = Operations.get_instance().get_operation_from_op_string(op_string)
102+
except KeyError:
103+
raise OperationNotFoundException(op_string, expr)
104+
105+
# Jump directly to the first argument
106+
pos = 1 + len(op_string) + 1
107+
arg_counter = 0
108+
argument_len = None
109+
while True:
110+
arg_counter += 1
111+
112+
if expr[pos] == '(':
113+
# The argument is another operator. Process it recursively
114+
argument_len = check_operands(expr[pos:])
115+
pos += argument_len
116+
if expr[pos] == ' ':
117+
pos += 1
118+
else:
119+
# The argument is a number or a sensor
120+
next_space = expr[pos:].find(' ')
121+
next_close = expr[pos:].find(')')
122+
if next_space < next_close:
123+
# There are more arguments. Jump to them
124+
argument_len = next_space
125+
pos += argument_len + 1
126+
else:
127+
argument_len = next_close
128+
pos += argument_len
129+
130+
# Check if this is the last argument
131+
if expr[pos] == ')':
132+
break
133+
134+
if arg_counter != expr_op["nbarg"]:
135+
print arg_counter
136+
raise OperationArgumentsAmountException(expr)
137+
138+
# The position always finished in the last bracket.
139+
# This is the same as the length of the operator
140+
return pos + 1
141+
142+
# Add an empty space at the end of the check_operands algorithm, to create a
143+
# single cut condition in the recursive algorithm
144+
expression = expression[6:-1]
145+
expression += " "
146+
check_operands(expression)
147+
28148
def simplify_tree(self):
29149
self._root = self._root.simplify()
30150
self._simplified_tree = '(root ' + self._root.to_string() + ')'

tests/mlc/common/lisp_tree_expr/test_expression_tree.py

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import unittest
22
import MLC.Log.log as lg
3+
from MLC import config as config_path
34
from MLC.Log.log import set_logger
45
from MLC.mlc_parameters.mlc_parameters import Config
6+
from MLC.Common.LispTreeExpr.LispTreeExpr import ExprException
57
from MLC.Common.LispTreeExpr.LispTreeExpr import LispTreeExpr
6-
from MLC import config as config_path
8+
from MLC.Common.LispTreeExpr.LispTreeExpr import NotBalancedParanthesisException
9+
from MLC.Common.LispTreeExpr.LispTreeExpr import OperationArgumentsAmountException
10+
from MLC.Common.LispTreeExpr.LispTreeExpr import OperationNotFoundException
11+
from MLC.Common.LispTreeExpr.LispTreeExpr import RootNotFoundExprException
712

813
import os
914

15+
1016
class ExpressionTreeTest(unittest.TestCase):
1117

1218
@classmethod
@@ -18,6 +24,74 @@ def setUpClass(cls):
1824
def setUp(self):
1925
pass
2026

27+
def test_check_expression_root_not_found(self):
28+
expression = '123'
29+
self.assert_check_expression_with_exception(expression, RootNotFoundExprException)
30+
31+
def test_check_expression_misplaced_parenthesis_1(self):
32+
expression = '(root )* 2 3))'
33+
self.assert_check_expression_with_exception(expression, NotBalancedParanthesisException)
34+
35+
def test_check_expression_misplaced_parenthesis_2(self):
36+
expression = '(root (* 2 3()'
37+
self.assert_check_expression_with_exception(expression, NotBalancedParanthesisException)
38+
39+
def test_check_expression_misplaced_parenthesis_3(self):
40+
expression = '(root (* 2 3)'
41+
self.assert_check_expression_with_exception(expression, NotBalancedParanthesisException)
42+
43+
def test_check_expression_misplaced_parenthesis_4(self):
44+
expression = '(root (* 2 3)))'
45+
self.assert_check_expression_with_exception(expression, NotBalancedParanthesisException)
46+
47+
def test_check_expression_operation_not_found(self):
48+
expression = '(root (y 2 3))'
49+
self.assert_check_expression_with_exception(expression, OperationNotFoundException)
50+
51+
def test_check_expression_incorrect_multiply_arguments_amount(self):
52+
expression = '(root (* 2 3 3))'
53+
self.assert_check_expression_with_exception(expression, OperationArgumentsAmountException)
54+
55+
def test_check_expression_incorrect_tanh_arguments_amount(self):
56+
expression = '(root (tanh 2 3))'
57+
self.assert_check_expression_with_exception(expression, OperationArgumentsAmountException)
58+
59+
def test_check_expression_complex_incorrect_tanh_arguments_amount(self):
60+
expression = '(root (tanh 2 (* 3 (/ 2 5))))'
61+
self.assert_check_expression_with_exception(expression, OperationArgumentsAmountException)
62+
63+
def test_check_expression_complex_incorrect_plus_arguments_amount(self):
64+
expression = '(root (+ (* 2 3 5) 8))'
65+
self.assert_check_expression_with_exception(expression, OperationArgumentsAmountException)
66+
67+
def test_check_expression_simple_correct_plus_arguments_amount(self):
68+
expression = '(root (+ 2 3))'
69+
self.assert_check_expression_without_exception(expression)
70+
71+
def test_check_expression_simple_correct_tanh_arguments_amount(self):
72+
expression = '(root (tanh 3))'
73+
self.assert_check_expression_without_exception(expression)
74+
75+
def test_check_expression_complex_correct_plus_arguments_amount_1(self):
76+
expression = '(root (+ 2 (* 3 (/ 2 5))))'
77+
self.assert_check_expression_without_exception(expression)
78+
79+
def test_check_expression_complex_correct_plus_arguments_amount_2(self):
80+
expression = '(root (+ 2 (* (/ 2 5) 3)))'
81+
self.assert_check_expression_without_exception(expression)
82+
83+
def test_check_expression_complex_correct_plus_arguments_amount_3(self):
84+
expression = '(root (+ (* 2 3) (/ 4 5)))'
85+
self.assert_check_expression_without_exception(expression)
86+
87+
def test_check_expression_complex_correct_plus_arguments_amount_4(self):
88+
expression = '(root (+ 8 (/ 4 5)))'
89+
self.assert_check_expression_without_exception(expression)
90+
91+
def test_check_expression_complex_correct_plus_arguments_amount_5(self):
92+
expression = '(root (+ (* 2 3) 8))'
93+
self.assert_check_expression_without_exception(expression)
94+
2195
def test_tree_depth_root(self):
2296
expression = '(root S0)'
2397
tree = LispTreeExpr(expression)
@@ -72,3 +146,17 @@ def assertNode(self, node, depth, childs, expr_index):
72146

73147
if not node.is_leaf():
74148
self.assertEquals(len(node._nodes), childs)
149+
150+
def assert_check_expression_with_exception(self, expression, exception_class):
151+
try:
152+
LispTreeExpr.check_expression(expression)
153+
self.assertTrue(True, False)
154+
except exception_class:
155+
self.assertTrue(True, True)
156+
157+
def assert_check_expression_without_exception(self, expression):
158+
try:
159+
LispTreeExpr.check_expression(expression)
160+
self.assertTrue(True, True)
161+
except ExprException:
162+
self.assertTrue(True, False)

0 commit comments

Comments
 (0)