Files
Sheerka-Old/src/sheerkapython/ExprToPython.py
T
kodjo 87cab44fb8 Fixed #125: SheerkaErrorManager
Fixed #135: Change services service priorities
Fixed #136: ErrorManager: Implement recognize_error
Fixed #137: BNFNodeParser : Error when parsing regex with sub parsers
Fixed #138: get_last_errors(): real errors sources are lost
Fixed #139: OneError return value removes the origin of the error
Fixed #140: Concept variables are not correctly handled when parsing sub expression
Fixed #143: Implement has_unknown_concepts()
2021-10-28 14:04:41 +02:00

131 lines
5.1 KiB
Python

from itertools import product
from core.builtin_concepts_ids import BuiltinConcepts
from core.sheerka.services.sheerka_service import FailedToCompileError
from core.tokenizer import TokenKind
from parsers.BaseExpressionParser import AndNode, ListComprehensionNode, NameExprNode, VariableNode, \
end_parenthesis_mapping, open_parenthesis_mapping
from sheerkapython.BaseExprTransform import BaseExprTransform, ExprTransformHints, do_not_eval_source_hint, \
is_a_question_hint, not_a_question_hint, wrap_concept_call_hint
class PythonExprVisitor(BaseExprTransform):
def __init__(self, context, obj_counter=0):
super().__init__(context, obj_counter)
def compile(self, expr_node, hint=None):
eval_question = self.context.in_context(BuiltinConcepts.EVAL_QUESTION_REQUESTED)
hint = hint or ExprTransformHints(eval_source=True, eval_question=eval_question)
try:
visitor_objects = self.visit(expr_node, hint)
except FailedToCompileError:
return None
results = []
for obj in visitor_objects:
ret = self.context.sheerka.parse_python(self.context, obj.source)
if ret.status:
ret.body.source = obj.text
ret.body.body.original_source = obj.text
ret.body.body.objects = obj.objects
results.append(ret)
else:
self.errors[obj.text] = self.context.sheerka.get_error_cause(ret.body)
return results
def visit_ListComprehensionNode(self, expr_node: ListComprehensionNode, hint: ExprTransformHints):
"""
:param expr_node:
:param hint:
:return:
"""
def _get_variables_names_from_target(target):
return [token.strip() for token in target.get_source().split(",")]
visitor_objects = []
source = expr_node.get_source()
product_inputs = []
# add parenthesis around the element if needed
# test case test_ExprToPython.test_i_can_compile_when_element_is_missing_its_parenthesis()
if expr_node.element.first is None and len(expr_node.element.items) > 1:
expr_node.element.first = NameExprNode(-1, -1, [open_parenthesis_mapping[TokenKind.LPAR]])
expr_node.element.last = NameExprNode(-1, -1, [end_parenthesis_mapping[TokenKind.LPAR]])
element_variables = set()
for comp in expr_node.generators:
comprehension_variables = _get_variables_names_from_target(comp.target)
element_variables.update(comprehension_variables)
# target
target_objs = self.visit(comp.target, do_not_eval_source_hint)
# iter
iter_hint = not_a_question_hint.copy()
iter_hint.variables = comprehension_variables
iter_objs = self.visit(comp.iterable, not_a_question_hint)
# if
if comp.if_expr:
# parse it using PythonConditionExprVisitor
res = self.context.sheerka.parse_expression(self.context, comp.if_expr.get_source())
if not res.status:
self.errors[comp.if_expr.get_source()] = res.body
return None
if_expr_hint = is_a_question_hint.copy()
if_expr_hint.variables = comprehension_variables
if_expr_objs = self.visit(res.body.body, if_expr_hint)
else:
if_expr_objs = [None]
product_inputs.extend([target_objs, iter_objs, if_expr_objs])
hint = wrap_concept_call_hint.copy()
hint.variables = element_variables
element_objs = self.visit(expr_node.element, hint)
product_inputs.insert(0, element_objs)
for items in product(*product_inputs):
obj = self.create_list_comprehension(source, *items)
obj.variables -= element_variables
visitor_objects.append(obj)
return visitor_objects
def visit_VariableNode(self, expr_node: VariableNode, hint: ExprTransformHints):
source = expr_node.get_source()
return self.parse_source_code(source,
hint.eval_question,
hint.wrap_concept_call,
hint.variables) if hint.eval_source else \
self.do_not_parse_source_code(source)
def visit_NameExprNode(self, expr_node: NameExprNode, hint: ExprTransformHints):
"""
create visitor objects from NameExprNode
:param expr_node:
:param hint:
:return:
"""
source = expr_node.get_source()
return self.parse_source_code(source,
hint.eval_question,
hint.wrap_concept_call,
hint.variables) if hint.eval_source else \
self.do_not_parse_source_code(source)
def visit_OrNode(self, expr_node: AndNode, hint: ExprTransformHints):
"""
:param expr_node:
:param hint:
:return:
"""
return self.visit_or_or_and_node("or", expr_node, hint)