Refactored parsers to introduce priority

This commit is contained in:
2020-01-08 19:45:54 +01:00
parent b4346b5af0
commit a62c1f0f13
13 changed files with 531 additions and 42 deletions
+65 -25
View File
@@ -211,42 +211,82 @@ class Sheerka(Concept):
def _call_parsers(self, execution_context, return_values, logger=None):
result = []
# return_values must be a list
if not isinstance(return_values, list):
return_values = [return_values]
for return_value in return_values:
# make sure we only parse user input
if not return_value.status or not self.isinstance(return_value.body, BuiltinConcepts.USER_INPUT):
result.append(return_value)
continue
# first make the distinguish between what is for the parsers and what is not
result = []
to_process = []
for r in return_values:
if not r.status or not self.isinstance(r.body, BuiltinConcepts.USER_INPUT):
result.append(r)
else:
to_process.append(r)
to_parse = return_value.body.body # get the underlying text
if not to_process:
return result
if self.log.isEnabledFor(logging.DEBUG):
debug_text = "'" + to_parse + "'" if isinstance(to_parse, str) \
else "'" + BaseParser.get_text_from_tokens(to_parse) + "' as tokens"
execution_context.log(logger or self.log, f"Parsing {debug_text}")
# keep track of the originals user inputs, as they need to be removed at the end
user_inputs = to_process[:]
for parser in self.parsers.values():
p = parser(sheerka=self)
if logger:
p.log = logger
# group the parsers by priorities
instantiated_parsers = [parser(sheerka=self) for parser in self.parsers.values()]
grouped_parsers = {}
for parser in [p for p in instantiated_parsers if p.enabled]:
if logger:
parser.log = logger
grouped_parsers.setdefault(parser.priority, []).append(parser)
sorted_priorities = sorted(grouped_parsers.keys(), reverse=True)
with execution_context.push(desc=f"Parsing using {p.name}") as sub_context:
res = p.parse(sub_context, to_parse)
stop_processing = False
for priority in sorted_priorities:
inputs_for_this_group = to_process[:]
if hasattr(res, "__iter__"):
for r in res:
r.parents = [return_value]
result.append(r)
else:
res.parents = [return_value]
result.append(res)
for parser in grouped_parsers[priority]:
sub_context.add_values(return_values=res)
return_value_success_found = False
for return_value in inputs_for_this_group:
to_parse = return_value.body.body \
if self.isinstance(return_value.body, BuiltinConcepts.USER_INPUT) \
else return_value.body
# if self.log.isEnabledFor(logging.DEBUG):
# debug_text = "'" + to_parse + "'" if isinstance(to_parse, str) \
# else "'" + BaseParser.get_text_from_tokens(to_parse) + "' as tokens"
# execution_context.log(logger or self.log, f"Parsing {debug_text}")
with execution_context.push(desc=f"Parsing using {parser.name}") as sub_context:
res = parser.parse(sub_context, to_parse)
if res is not None:
if hasattr(res, "__iter__"):
for r in res:
if r is None:
continue
r.parents = [return_value]
result.append(r)
if self.isinstance(r.body, BuiltinConcepts.PARSER_RESULT):
to_process.append(r)
if r.status:
return_value_success_found = True
else:
res.parents = [return_value]
result.append(res)
if self.isinstance(res.body, BuiltinConcepts.PARSER_RESULT):
to_process.append(res)
if res.status:
return_value_success_found = True
if return_value_success_found:
stop_processing = True
break # Stop the other return_values (but not the other parsers with the same priority)
if stop_processing:
break # Do not try the other priorities if a match is found
result = core.utils.remove_list_from_list(result, user_inputs)
return result
def _call_evaluators(self, execution_context, return_values, process_step, evaluation_context=None, logger=None):