Skip to content
This repository has been archived by the owner on Jan 24, 2024. It is now read-only.

Commit

Permalink
Merge pull request #3 from SoFolichon/wip-fix
Browse files Browse the repository at this point in the history
Wip fix
  • Loading branch information
GabDug authored Jan 11, 2018
2 parents 2370a2f + 47799d6 commit ba9257f
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 112 deletions.
194 changes: 107 additions & 87 deletions src/eval_global.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,17 @@ def _single_element(element: tuple, variable_dic):
elif element[0] == "clear":
logger.info("Clear screen")
_clear()
return ""
return "", "none"
elif element[0] in variable_dic:
return variable_dic[element[0]]
else:
raise Exception(f"unknown variable ('{element[0]}')")
elif element[1] == "integer":
return element[0]
return element
elif element[1] == "string":
return element[0]
return element
elif element[1] == "boolean":
return element[0]


def _get_single_element_type(element):
"""Returns the type of an element (bool, str, int...)"""
if element == "false" or element == "true":
return "boolean"
elif isinstance(element, int):
return "integer"
else:
return "string"
return element


def _eval_global(expression: list, var_dic: dict):
Expand All @@ -58,7 +48,7 @@ def _eval_global(expression: list, var_dic: dict):

# If expression is single-operand (exit condition of recursivity)
if length == 1:
logger.debug(" Return:" + str(expression[0][0]))
logger.debug(" Return:" + str(expression))
return _single_element(expression[0], var_dic)

# Expression Shape: left-expression main-operator right-expression
Expand All @@ -83,94 +73,121 @@ def _eval_global(expression: list, var_dic: dict):
if expression[operator_index][0] == "not":
logger.debug(" Processing not")
if left_expression is None or left_expression == []:
if _eval_global(right_expression, var_dic) == "true":
return "false"
if _eval_global(right_expression, var_dic)[0] == "true":
return ("false", "boolean")
else:
return "true"
return ("true", "boolean")
else:
if _eval_global(right_expression, var_dic) == "true":
if _eval_global(right_expression, var_dic)[0] == "true":
left_expression.append(("false", "boolean"))
else:
left_expression.append(("true", "boolean"))
return _eval_global(left_expression, var_dic)

# Binary infix operators
else:
if main_operator[0] == '+':
left = _eval_global(left_expression, var_dic)
left_type = _get_single_element_type(left)
right = _eval_global(right_expression, var_dic)
right_type = _get_single_element_type(right)
if left_type != right_type:
if left_type == "string" and right_type == "integer":
return left + str(right)
elif left_type == "integer" and right_type == "string":
return str(left) + right
else:
raise Exception(f"type mismatch ({left_type} {main_operator[0]} {right_type})")
else:
return left + right
elif main_operator[0] == '-':
try:
return _eval_global(left_expression, var_dic) - _eval_global(right_expression, var_dic)
except TypeError:
raise Exception(f"type mismatch ({left_type} {main_operator[0]} {right_type})")
elif main_operator[0] == '*':
return _eval_global(left_expression, var_dic) * _eval_global(right_expression, var_dic)
elif main_operator[0] == "/":
return _eval_global(left_expression, var_dic) // _eval_global(right_expression, var_dic)
elif main_operator[0] == '==':
if _eval_global(left_expression, var_dic) == _eval_global(right_expression, var_dic):
return "true"
else:
return "false"
elif main_operator[0] == '!=':
if _eval_global(left_expression, var_dic) != _eval_global(right_expression, var_dic):
return "true"
else:
return "false"
elif main_operator[0] == '<':
if _eval_global(left_expression, var_dic) < _eval_global(right_expression, var_dic):
return "true"
else:
return "false"
elif main_operator[0] == '>':
if _eval_global(left_expression, var_dic) > _eval_global(right_expression, var_dic):
return "true"
else:
return "false"
elif main_operator[0] == '<=':
if _eval_global(left_expression, var_dic) <= _eval_global(right_expression, var_dic):
return "true"
else:
return "false"
elif main_operator[0] == '>=':
if _eval_global(left_expression, var_dic) >= _eval_global(right_expression, var_dic):
return "true"
else:
return "false"
elif main_operator[0] == 'and':
if _eval_global(left_expression, var_dic) == _eval_global(right_expression, var_dic) == 'true':
return "true"
else:
return "false"
elif main_operator[0] == 'or':
if _eval_global(left_expression, var_dic) == "true" or _eval_global(right_expression, var_dic) == 'true':
return "true"
else:
return "false"
elif main_operator[0] == '=' and len(left_expression) != 1:
right = _eval_global(right_expression, var_dic)
# First, the assignment because we don't evaluate the variable name (left)
if main_operator[0] == '=' and len(left_expression) != 1:
raise Exception("variable assignment should be 'variable = exp'")
elif main_operator[0] == '=' and left_expression[0][1] == "variable":
if left_expression[0][0] in unauthorized_var:
raise Exception("variable name can't be a reserved keyword")
else:
var_dic[left_expression[0][0]] = _eval_global(right_expression, var_dic)
return ""
var_dic[left_expression[0][0]] = right
return "", "none"
# If we have "=" but the left side is not a variable
elif main_operator[0] == '=' and left_expression[0][1] != "variable":
raise Exception("variable name must start with a letter")

# Then, all the operators that are binary (we evaluate
left = _eval_global(left_expression, var_dic)

# For left and right:
# [0] is the value
# [1] is the type
# [2] is the priority (exists if type operator)

# Integer only operators
if main_operator[0] in "/-*":
if left[1] == right[1] == "integer":
if main_operator[0] == '*':
return left[0] * right[0], "integer"
elif main_operator[0] == "/":
return left[0] // right[0], "integer"
elif main_operator[0] == '-':
return left[0] - right[0], "integer"
else:
raise Exception(f"type mismatch ({left[1]} {main_operator[0]} {right[1]})")

# Boolean only
elif main_operator[0] in ["and", "or"]:
if left[1] == right[1] == "boolean":
if main_operator[0] == "and":
if left[0] == right[0] == 'true':
return "true", "boolean"
else:
return "false", "boolean"
elif main_operator[0] == 'or':
print("left0 " + str(left[0]))
print("rught0 " + str(right[0]))

if left[0] == "true" or right[0] == 'true':
return "true", "boolean"
else:
return "false", "boolean"
else:
raise Exception(f"type mismatch ({left[1]} {main_operator[0]} {right[1]})")

# String and int only
elif main_operator[0] in ["+", "<", ">", "<=", ">="]:
if (left[1] == right[1]) and (left[1] == "integer" or left[1] == "string"):
if main_operator[0] == '+':
if left[1] != right[1]:
if left[1] == "string" and right[1] == "integer":
return left[0] + str(right[0]), "string"
elif left[1] == "integer" and right[1] == "string":
return str(left) + right, "string"
else:
raise Exception(f"type mismatch ({left[1]} {main_operator[0]} {right[1]})")
else:
return left[0] + right[0], "integer"
elif main_operator[0] == '<':
if left[0] < right[0]:
return "true", "boolean"
else:
return "false", "boolean"
elif main_operator[0] == '>':
if left[0] > right[0]:
return "true", "boolean"
else:
return "false", "boolean"
elif main_operator[0] == '<=':
if left[0] <= right[0]:
return "true", "boolean"
else:
return "false", "boolean"
elif main_operator[0] == '>=':
if left[0] >= right[0]:
return "true", "boolean"
else:
return "false", "boolean"
else:
raise Exception(f"type mismatch ({left[1]} {main_operator[0]} {right[1]})")

# Working with all types
elif main_operator[0] in ["==", "!="]:
if main_operator[0] == '==':
if left[0] == right[0]:
return "true", "boolean"
else:
return "false", "boolean"
elif main_operator[0] == '!=':
if left[0] != right[0]:
return "true", "boolean"
else:
return "false", "boolean"


def _first_eval(expression: list, variable_dic):
"""Evaluates an expression (boolean, integer or string), where the input is a parsed list of tokens."""
Expand All @@ -185,7 +202,7 @@ def _first_eval(expression: list, variable_dic):

def ext_eval_global(expression_str: str, variable_dic=None):
"""Evaluates an expression (boolean, integer or string), where the input is a string."""
return _first_eval(parse(expression_str), variable_dic)
return _first_eval(parse(expression_str), variable_dic)[0]


def find_operator(expression):
Expand All @@ -205,6 +222,7 @@ def find_operator(expression):
return i


# FOR DEBUGGING PURPOSE ONLY
if __name__ == "__main__":
import logging
from sys import stdout
Expand All @@ -219,4 +237,6 @@ def find_operator(expression):
logger.addHandler(ch)
logger.info("Starting logger from module.")

print(ext_eval_global("'Test' + 'string'"))
dict_var = {}
print(ext_eval_global("a = 10", dict_var))
print(ext_eval_global("a + 1", dict_var))
26 changes: 2 additions & 24 deletions src/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ def remove_parenthesis(expression):
raise Exception("missing operand near " + str(expression))


# FOR DEBUGGING PURPOSE ONLY
if __name__ == "__main__":
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
Expand All @@ -142,29 +143,6 @@ def remove_parenthesis(expression):
logger.addHandler(ch)
logger.info("Starting logger from module.")

# logger.info(parse("'Salut'"))
logger.info(parse("1 === 1"))
# logger.info(parse("'Salut'+'toi'"))
# logger.info(parse("'Salut+'toi'"))
logger.info((parse("3+(4*(4-8))")))
logger.info(parse("3+4*2"))
logger.info(parse("248+345"))
logger.info(parse("(3 + 2) * 4"))
logger.info(parse("3 - 4"))
logger.info(parse("-4 + 3"))
logger.info(parse("(-1) + -1 + (-1 - -1)"))
logger.info(parse("(3+254)* 44 "))
logger.info(parse("'Yo'"))
logger.info(parse("'Hey''You'"))
logger.info(parse("'Test' + 'os'"))
# logger.info(parse("'test"))
logger.info(parse("((1))"))
logger.info(parse("(1)*(2)"))
logger.info(parse("(1+(2*3))"))
logger.info(parse("(1+(2*3))(4*5)"))
logger.info(parse("((1+(2*3))(4*5))"))
logger.info(parse("(4+6)-5*9"))
logger.info(parse("true"))
logger.info(parse("true and false"))
logger.info(parse("1 < 5 and 5 < 10"))
logger.info(parse("1+ 2 +3 == 2 * 3"))
logger.info(parse("test = 2 * 3"))
3 changes: 2 additions & 1 deletion src/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@


class TestEval(unittest.TestCase):
"""We run some tests, with an expression and the expected output."""

def test_integers(self):
test = [("1", "1"),
("(1)", "1"),
Expand Down Expand Up @@ -48,7 +50,6 @@ def test_bool(self):
("(true or false) and false", "false"),
("not false and not false", "true"),
("1<0", "false"),

]

for e in range(len(test)):
Expand Down

0 comments on commit ba9257f

Please sign in to comment.