Enhanced complex concepts handling
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from parsers.BaseParser import BaseParser
|
||||
from parsers.ConceptLexerParser import UnrecognizedTokensNode, ConceptNode
|
||||
from parsers.PythonParser import PythonParser
|
||||
|
||||
|
||||
class PythonWithConceptsParser(BaseParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__("PythonWithConcepts", 20)
|
||||
self.identifiers = None
|
||||
self.identifiers_key = None
|
||||
|
||||
@staticmethod
|
||||
def sanitize(identifier):
|
||||
res = ""
|
||||
for c in identifier:
|
||||
res += c if c.isalnum() else "0"
|
||||
return res
|
||||
|
||||
def parse(self, context, text):
|
||||
sheerka = context.sheerka
|
||||
if not sheerka.isinstance(text, BuiltinConcepts.PARSER_RESULT):
|
||||
return None
|
||||
|
||||
nodes = text.body
|
||||
if not isinstance(nodes, list):
|
||||
return None
|
||||
|
||||
if len(nodes) == 0:
|
||||
return None
|
||||
|
||||
if not isinstance(nodes[0], (ConceptNode, UnrecognizedTokensNode)):
|
||||
return None
|
||||
|
||||
source = ""
|
||||
to_parse = ""
|
||||
identifiers = {}
|
||||
identifiers_key = {}
|
||||
python_ids_mappings = {}
|
||||
|
||||
def _get_identifier(c):
|
||||
"""
|
||||
Internal function because I don't want identifiers, identifiers_key and python_ids_mappings
|
||||
to be instance variables
|
||||
I would like to keep this parser as stateless as possible
|
||||
:param c:
|
||||
:return:
|
||||
"""
|
||||
if id(c) in identifiers:
|
||||
return identifiers[id(c)]
|
||||
|
||||
identifier = "__C__" + self.sanitize(c.key or c.name)
|
||||
if c.id:
|
||||
identifier += "__" + c.id
|
||||
|
||||
if identifier in identifiers_key:
|
||||
identifiers_key[identifier] += 1
|
||||
identifier += f"_{identifiers_key[identifier]}"
|
||||
else:
|
||||
identifiers_key[identifier] = 0
|
||||
|
||||
identifier += "__C__"
|
||||
|
||||
identifiers[id(c)] = identifier
|
||||
return identifier
|
||||
|
||||
for node in nodes:
|
||||
if isinstance(node, ConceptNode):
|
||||
source += node.source
|
||||
if to_parse:
|
||||
to_parse += " "
|
||||
concept = node.concept
|
||||
python_id = _get_identifier(concept)
|
||||
to_parse += python_id
|
||||
python_ids_mappings[python_id] = concept
|
||||
else:
|
||||
source += node.source
|
||||
to_parse += node.source
|
||||
|
||||
with context.push(self, "Trying Python for '" + to_parse + "'") as sub_context:
|
||||
python_parser = PythonParser()
|
||||
result = python_parser.parse(sub_context, to_parse)
|
||||
|
||||
if result.status:
|
||||
python_node = result.body.body
|
||||
python_node.source = source
|
||||
python_node.concepts = python_ids_mappings
|
||||
|
||||
return sheerka.ret(
|
||||
self.name,
|
||||
True,
|
||||
sheerka.new(
|
||||
BuiltinConcepts.PARSER_RESULT,
|
||||
parser=self,
|
||||
source=source,
|
||||
body=result.body.body,
|
||||
try_parsed=None))
|
||||
|
||||
else:
|
||||
|
||||
return sheerka.ret(
|
||||
self.name,
|
||||
False,
|
||||
result.body)
|
||||
|
||||
def concept_identifier(self, concept):
|
||||
if id(concept) in self.identifiers:
|
||||
return self.identifiers[id(concept)]
|
||||
|
||||
|
||||
identifier = "__C__" + (concept.key or concept.name)
|
||||
if concept.id:
|
||||
identifier += "__" + concept.id
|
||||
identifier += "__C__"
|
||||
|
||||
return identifier
|
||||
Reference in New Issue
Block a user