Fixed BnfNodeParser to allow expressions like 'number hundred' when number is a group
This commit is contained in:
@@ -525,7 +525,7 @@ class CNC(CN):
|
||||
to_compare = {k: v for k, v in other.concept.compiled.items() if k != ConceptParts.BODY}
|
||||
else:
|
||||
to_compare = other.concept.compiled
|
||||
if self.compiled == to_compare:
|
||||
if self.compiled == to_compare: # expanded form to ease the debug
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@@ -673,7 +673,8 @@ class BaseNodeParser(BaseParser):
|
||||
|
||||
concept = to_map(self, concept) if to_map else concept
|
||||
result.append(concept)
|
||||
return result + custom_concepts
|
||||
return core.utils.make_unique(result + custom_concepts,
|
||||
lambda c: c.concept.id if hasattr(c, "concept") else c.id)
|
||||
|
||||
return custom_concepts if custom else None
|
||||
|
||||
@@ -707,16 +708,20 @@ class BaseNodeParser(BaseParser):
|
||||
@staticmethod
|
||||
def resolve_concepts_by_first_keyword(context, concepts_by_first_keyword):
|
||||
sheerka = context.sheerka
|
||||
res = {}
|
||||
|
||||
def resolve_concepts(concept_str):
|
||||
c_key, c_id = core.utils.unstr_concept(concept_str)
|
||||
if c_id in already_seen:
|
||||
return ChickenAndEggError(already_seen)
|
||||
|
||||
already_seen.add(c_id)
|
||||
|
||||
resolved = set()
|
||||
to_resolve = set()
|
||||
concept = sheerka.get_by_id(core.utils.unstr_concept(concept_str)[1])
|
||||
chicken_and_egg = set()
|
||||
|
||||
if concept.id in already_seen:
|
||||
raise ChickenAndEggError(already_seen)
|
||||
else:
|
||||
already_seen.add(concept.id)
|
||||
concept = sheerka.get_by_id(c_id)
|
||||
|
||||
if sheerka.isaset(context, concept):
|
||||
concepts = sheerka.get_set_elements(context, concept)
|
||||
@@ -730,11 +735,18 @@ class BaseNodeParser(BaseParser):
|
||||
(to_resolve if keyword.startswith("c:|") else resolved).add(keyword)
|
||||
|
||||
for concept_to_resolve_str in to_resolve:
|
||||
resolved |= resolve_concepts(concept_to_resolve_str)
|
||||
res = resolve_concepts(concept_to_resolve_str)
|
||||
if isinstance(res, ChickenAndEggError):
|
||||
chicken_and_egg |= res.concepts
|
||||
else:
|
||||
resolved |= res
|
||||
to_resolve.clear()
|
||||
|
||||
return resolved
|
||||
if len(resolved) == 0 and len(chicken_and_egg) > 0:
|
||||
raise ChickenAndEggError(chicken_and_egg)
|
||||
else:
|
||||
return resolved
|
||||
|
||||
res = {}
|
||||
for k, v in concepts_by_first_keyword.items():
|
||||
if k.startswith("c:|"):
|
||||
try:
|
||||
@@ -744,8 +756,16 @@ class BaseNodeParser(BaseParser):
|
||||
res.setdefault(resolved, []).extend(v)
|
||||
except ChickenAndEggError as ex:
|
||||
context.log(f"Chicken and egg detected for {k}, concepts={ex.concepts}")
|
||||
# res[k] = sheerka.new(BuiltinConcepts.CHICKEN_AND_EGG,
|
||||
# body=[sheerka.get_by_id(c) for c in ex.concepts])
|
||||
concepts_in_recursion = ex.concepts
|
||||
# make sure to have all the parents
|
||||
for parent in v:
|
||||
concepts_in_recursion.add(parent)
|
||||
|
||||
for concept_id in concepts_in_recursion:
|
||||
# make sure we keep the longest chain
|
||||
old = sheerka.chicken_and_eggs.get(concept_id)
|
||||
if old is None or len(old) < len(ex.concepts):
|
||||
sheerka.chicken_and_eggs.put(concept_id, concepts_in_recursion)
|
||||
else:
|
||||
res.setdefault(k, []).extend(v)
|
||||
|
||||
@@ -755,6 +775,53 @@ class BaseNodeParser(BaseParser):
|
||||
|
||||
return sheerka.ret("BaseNodeParser", True, res)
|
||||
|
||||
@staticmethod
|
||||
def get_referenced_concepts(context, concept_id, already_seen):
|
||||
"""
|
||||
Gets all the tokens that may allow to recognize concept concept_id
|
||||
Basically, it returns all the starting tokens for concept concept_id
|
||||
CHICKEN_AND_EGG is returned when a circular references are found
|
||||
:param context:
|
||||
:param concept_id:
|
||||
:param already_seen:
|
||||
:return:
|
||||
"""
|
||||
if concept_id in already_seen:
|
||||
return ChickenAndEggError(already_seen)
|
||||
|
||||
already_seen.add(concept_id)
|
||||
|
||||
resolved = set()
|
||||
to_resolve = set()
|
||||
chicken_and_egg = set()
|
||||
sheerka = context.sheerka
|
||||
concept = sheerka.get_by_id(concept_id)
|
||||
|
||||
if sheerka.isaset(context, concept):
|
||||
concepts = sheerka.get_set_elements(context, concept)
|
||||
else:
|
||||
concepts = [concept]
|
||||
|
||||
for concept in concepts:
|
||||
BaseNodeParser.ensure_bnf(context, concept) # need to make sure that it cannot fail
|
||||
keywords = BaseNodeParser.get_first_tokens(sheerka, concept)
|
||||
for keyword in keywords:
|
||||
(to_resolve if keyword.startswith("c:|") else resolved).add(keyword)
|
||||
|
||||
for concept_to_resolve_str in to_resolve:
|
||||
c_key, c_id = core.utils.unstr_concept(concept_to_resolve_str)
|
||||
res = BaseNodeParser.get_referenced_concepts(context, c_id, already_seen)
|
||||
if isinstance(res, ChickenAndEggError):
|
||||
chicken_and_egg |= res.concepts
|
||||
else:
|
||||
resolved |= res
|
||||
to_resolve.clear()
|
||||
|
||||
if len(resolved) == 0 and len(chicken_and_egg) > 0:
|
||||
raise ChickenAndEggError(chicken_and_egg)
|
||||
else:
|
||||
return resolved
|
||||
|
||||
@staticmethod
|
||||
def resolve_sya_associativity_and_precedence(context, sya):
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user