Fixed #49 : ExpressionParser: Implement ExpressionParser

This commit is contained in:
2021-03-15 19:41:06 +01:00
parent 42bc6abf97
commit 27bc6c4ba1
7 changed files with 245 additions and 57 deletions
@@ -29,8 +29,6 @@ class SheerkaEvaluateRules(BaseService):
self.sheerka.register_debug_vars(self.NAME, "evaluate_rules", "results")
self.sheerka.register_debug_rules(self.NAME, "evaluate_rule", "*")
def reset_evaluators(self):
# instantiate evaluators, once for all, only keep when it's enabled
evaluators = [e_class() for e_class in self.sheerka.evaluators]
+49 -14
View File
@@ -14,10 +14,10 @@ from core.rule import Rule, ACTION_TYPE_PRINT
from core.sheerka.Sheerka import RECOGNIZED_BY_NAME, RECOGNIZED_BY_ID
from core.sheerka.services.sheerka_service import BaseService, FailedToCompileError
from core.tokenizer import Keywords, TokenKind, Token, IterParser
from core.utils import index_tokens, COLORS, get_text_from_tokens
from core.utils import index_tokens, COLORS, get_text_from_tokens, unstr_concept
from evaluators.ConceptEvaluator import ConceptEvaluator
from evaluators.PythonEvaluator import PythonEvaluator, Expando
from parsers.BaseExpressionParser import AndNode, ExpressionVisitor, VariableNode, ComparisonNode
from parsers.BaseExpressionParser import AndNode, ExpressionVisitor, VariableNode, ComparisonNode, FunctionNode
from parsers.BaseNodeParser import SourceCodeWithConceptNode, ConceptNode, SourceCodeNode
from parsers.LogicalOperatorParser import LogicalOperatorParser
from parsers.PythonParser import PythonNode
@@ -1127,7 +1127,6 @@ class ReteConditionExprVisitor(ExpressionVisitor):
self.context = context
self.var_counter = 0
self.variables = {}
self.res = []
def add_variable(self, target):
var_name = f"__x_{self.var_counter:02}__"
@@ -1135,35 +1134,71 @@ class ReteConditionExprVisitor(ExpressionVisitor):
self.variables[target] = var_name
return var_name
def init_variable_if_needed(self, node):
def init_or_get_variable_from_name(self, node, conditions):
if node.name not in self.variables:
var_name = self.add_variable(node.name)
self.res.append(Condition(V(var_name), "__name__", node.name))
conditions.append(Condition(V(var_name), "__name__", node.name))
return V(self.variables[node.name])
def init_or_get_variable_from_attr(self, node, conditions):
path = f"{node.name}.{node.attributes_str}"
if path in self.variables:
return self.variables[path]
root = self.init_or_get_variable_from_name(node, conditions)
var_name = self.add_variable(path)
variable = V(var_name)
conditions.append(Condition(root, node.attributes_str, variable))
return variable
def get_conditions(self, expr_node):
self.res.clear()
self.var_counter = 0
self.variables.clear()
self.visit(expr_node)
return AndConditions(self.res)
conditions = self.visit(expr_node)
return [AndConditions(conditions)]
def visit_VariableNode(self, expr_node):
var_name = self.init_variable_if_needed(expr_node)
conditions = []
var_name = self.init_or_get_variable_from_name(expr_node, conditions)
if expr_node.attributes_str is not None:
self.res.append(Condition(var_name, expr_node.attributes_str, True))
conditions.append(Condition(var_name, expr_node.attributes_str, True))
return conditions
def visit_AndNode(self, expr_node: AndNode):
conditions = []
for node in expr_node.parts:
self.visit(node)
conditions.extend(self.visit(node))
return conditions
def visit_ComparisonNode(self, expr_node: ComparisonNode):
if isinstance(expr_node.left, VariableNode):
left = self.init_variable_if_needed(expr_node.left)
conditions = []
left = self.init_or_get_variable_from_name(expr_node.left, conditions)
attr = expr_node.left.attributes_str or "__self__"
right = eval(get_text_from_tokens(expr_node.right.tokens))
self.res.append(Condition(left, attr, right))
conditions.append(Condition(left, attr, right))
return conditions
else:
raise FailedToCompileError(expr_node)
raise FailedToCompileError([expr_node])
def visit_FunctionNode(self, expr_node: FunctionNode):
if expr_node.first.value == "recognize(":
return self.function_recognize(expr_node.parameters[0].value, expr_node.parameters[1].value)
def function_recognize(self, source, target):
conditions = []
body_var = self.init_or_get_variable_from_attr(source, conditions)
conditions.append(Condition(body_var, "__is_concept__", True))
if isinstance(target, VariableNode):
conditions.append(Condition(body_var, "name", target.name))
else:
concept_key, concept_id = unstr_concept(target.value)
if concept_id:
conditions.append(Condition(body_var, "id", concept_id))
elif concept_key:
conditions.append(Condition(body_var, "name", concept_key))
return conditions