106 lines
3.3 KiB
Python
106 lines
3.3 KiB
Python
from core.builtin_concepts import BuiltinConcepts
|
|
from parsers.BaseParser import BaseParser
|
|
from parsers.ConceptLexerParser import ConceptNode
|
|
from parsers.MultipleConceptsParser import MultipleConceptsParser
|
|
from parsers.PythonParser import PythonParser
|
|
|
|
multiple_concepts_parser = MultipleConceptsParser()
|
|
|
|
|
|
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
|
|
|
|
if not text.parser == multiple_concepts_parser:
|
|
return None
|
|
|
|
nodes = text.body
|
|
source = ""
|
|
to_parse = ""
|
|
identifiers = {}
|
|
identifiers_key = {}
|
|
python_ids_mappings = {}
|
|
|
|
def _get_identifier(c):
|
|
"""
|
|
Get an identifier for a concept.
|
|
Make sure to return the same identifier if the same concept
|
|
Make sure to return a different identifier if same name but different concept
|
|
|
|
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)
|