Added ExactConceptParser
This commit is contained in:
+42
-20
@@ -1,9 +1,9 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from core.concept import Concept, ErrorConcept, Property, TooManySuccessConcept, ReturnValueConcept
|
||||
from parsers.PythonParser import PythonParser, PythonGetNamesVisitor, PythonNode
|
||||
from parsers.PythonParser import PythonGetNamesVisitor, PythonNode
|
||||
from sdp.sheerkaDataProvider import SheerkaDataProvider, Event, SheerkaDataProviderDuplicateKeyError
|
||||
from parsers.DefaultParser import DefaultParser, DefConceptNode
|
||||
from parsers.DefaultParser import DefConceptNode, DefaultParser
|
||||
import core.utils
|
||||
|
||||
import logging
|
||||
@@ -50,6 +50,7 @@ class Sheerka(Concept):
|
||||
NAME = "Sheerka"
|
||||
UNKNOWN_CONCEPT_NAME = "Unknown Concept"
|
||||
SUCCESS_CONCEPT_NAME = "Success"
|
||||
CONCEPT_TOO_LONG_CONCEPT_NAME = "Concept too long"
|
||||
|
||||
CONCEPTS_ENTRY = "All_Concepts"
|
||||
BUILTIN_CONCEPTS_KEYS = "Builtins_Concepts"
|
||||
@@ -60,6 +61,8 @@ class Sheerka(Concept):
|
||||
super().__init__(Sheerka.NAME)
|
||||
|
||||
# cache of the most used concepts
|
||||
# Note that these are only templates
|
||||
# They are used as a footprint for instantiation
|
||||
self.concepts_cache = {}
|
||||
|
||||
# a concept can be instantiated
|
||||
@@ -91,8 +94,9 @@ class Sheerka(Concept):
|
||||
try:
|
||||
self.init_logging()
|
||||
self.sdp = SheerkaDataProvider(root_folder)
|
||||
self.parsers.append(lambda text: DefaultParser(text, PythonParser))
|
||||
self.parsers.append(lambda text: PythonParser(text))
|
||||
self.parsers.append(core.utils.get_class("parsers.DefaultParser.DefaultParser"))
|
||||
self.parsers.append(core.utils.get_class("parsers.PythonParser.PythonParser"))
|
||||
#self.parsers.append(core.utils.get_class("parsers.ExactConceptParser.ExactConceptParser"))
|
||||
|
||||
self.evaluators.append(core.utils.get_object("evaluators.DefaultEvaluator.DefaultEvaluator"))
|
||||
self.evaluators.append(core.utils.get_object("evaluators.AddConceptEvaluator.AddConceptEvaluator"))
|
||||
@@ -103,7 +107,7 @@ class Sheerka(Concept):
|
||||
|
||||
self.create_builtin_concepts()
|
||||
except IOError as e:
|
||||
return ReturnValue(self, False, self.get(Sheerka.ERROR_CONCEPT_NAME), e)
|
||||
return ReturnValue(self, False, self.get(ErrorConcept.NAME), e)
|
||||
|
||||
return ReturnValue(self, True, self.get(Sheerka.SUCCESS_CONCEPT_NAME))
|
||||
|
||||
@@ -129,12 +133,15 @@ class Sheerka(Concept):
|
||||
self,
|
||||
Concept(Sheerka.UNKNOWN_CONCEPT_NAME, key=Sheerka.UNKNOWN_CONCEPT_NAME),
|
||||
Concept(Sheerka.SUCCESS_CONCEPT_NAME, key=Sheerka.SUCCESS_CONCEPT_NAME),
|
||||
Concept(Sheerka.CONCEPT_TOO_LONG_CONCEPT_NAME, key=Sheerka.CONCEPT_TOO_LONG_CONCEPT_NAME),
|
||||
ErrorConcept(),
|
||||
TooManySuccessConcept(),
|
||||
ReturnValueConcept(),
|
||||
]
|
||||
|
||||
for concept in builtins:
|
||||
self.add_in_cache(concept)
|
||||
|
||||
from_db = self.sdp.get_safe(self.CONCEPTS_ENTRY, concept.key)
|
||||
if from_db is None:
|
||||
log.debug(f"'{concept.name}' concept is not found. Adding.")
|
||||
@@ -143,7 +150,6 @@ class Sheerka(Concept):
|
||||
else:
|
||||
log.debug(f"Found concept '{from_db}'. Updating.")
|
||||
concept.update_from(from_db)
|
||||
self.concepts_cache[concept.key] = concept
|
||||
|
||||
def init_logging(self):
|
||||
if self.debug:
|
||||
@@ -158,7 +164,7 @@ class Sheerka(Concept):
|
||||
def eval(self, text):
|
||||
evt_digest = self.sdp.save_event(Event(text))
|
||||
exec_context = ExecutionContext(self, evt_digest)
|
||||
return_values = self.try_parse(text)
|
||||
return_values = self.try_parse(exec_context, text)
|
||||
return_values = self.try_eval(exec_context, return_values)
|
||||
|
||||
# return_values = []
|
||||
@@ -172,17 +178,17 @@ class Sheerka(Concept):
|
||||
|
||||
return return_values
|
||||
|
||||
def try_parse(self, text):
|
||||
def try_parse(self, context, text):
|
||||
result = []
|
||||
log.debug(f"Parsing '{text}'")
|
||||
for parser in self.parsers:
|
||||
p = parser(text)
|
||||
p = parser()
|
||||
# try:
|
||||
# tree = p.parse()
|
||||
# result.append((p.name, tree))
|
||||
# except Exception as e:
|
||||
# result.append((p.name, e))
|
||||
tree = p.parse()
|
||||
tree = p.parse(context, text)
|
||||
result.append(ReturnValue(p.name, not p.has_error, p.error_sink if p.has_error else tree))
|
||||
return result
|
||||
|
||||
@@ -235,11 +241,12 @@ class Sheerka(Concept):
|
||||
setattr(concept, prop, source)
|
||||
|
||||
# try to find variables (eg props)
|
||||
# Note that with this method, the variables will be created in the order of appearance
|
||||
for token in def_concept_node.tokens["name"]:
|
||||
if token.value in get_names_visitor.names:
|
||||
concept.props.append(Property(token.value, None))
|
||||
concept.set_prop(token.value, None)
|
||||
|
||||
concept.key = DefaultParser.get_concept_name(def_concept_node.tokens["name"], [p.name for p in concept.props])
|
||||
concept.init_key(def_concept_node.tokens["name"])
|
||||
concept.add_codes(def_concept_node.get_codes())
|
||||
self.set_id_if_needed(concept, False)
|
||||
|
||||
@@ -249,22 +256,34 @@ class Sheerka(Concept):
|
||||
return ReturnValue(self.add_concept.__name__, False, ErrorConcept(body=error), error.args[0])
|
||||
return ReturnValue(self.add_concept.__name__, True, concept)
|
||||
|
||||
def get(self, concept_name):
|
||||
def add_in_cache(self, concept):
|
||||
"""
|
||||
Adds a concept template in cache.
|
||||
The cache is used as a proxy before looking at sdp
|
||||
:param concept:
|
||||
:return:
|
||||
"""
|
||||
self.concepts_cache[concept.key] = concept
|
||||
|
||||
def get(self, concept_key):
|
||||
"""
|
||||
Tries to find a concept
|
||||
:param concept_name:
|
||||
TODO: how to manage single vs multiple instances
|
||||
:param concept_key:
|
||||
:return:
|
||||
"""
|
||||
|
||||
# first search in cache
|
||||
if concept_name in self.concepts_cache:
|
||||
return self.concepts_cache[concept_name]
|
||||
if concept_key in self.concepts_cache:
|
||||
return self.concepts_cache[concept_key]
|
||||
|
||||
return self.sdp.get(self.CONCEPTS_ENTRY, concept_name)
|
||||
return self.sdp.get_safe(self.CONCEPTS_ENTRY, concept_key) or \
|
||||
self.new(self.UNKNOWN_CONCEPT_NAME, body=concept_key)
|
||||
|
||||
def new(self, concept, **kwargs):
|
||||
"""
|
||||
Returns an instance of a new concept
|
||||
TODO: Checks if the concept is supposed to be unique (ex Sheerka, or the number 'one' for example)
|
||||
:param concept:
|
||||
:param kwargs:
|
||||
:return:
|
||||
@@ -287,11 +306,14 @@ class Sheerka(Concept):
|
||||
:return:
|
||||
"""
|
||||
|
||||
if not isinstance(a, Concept) or not isinstance(b, Concept):
|
||||
return False
|
||||
if not isinstance(a, Concept):
|
||||
raise SyntaxError("The first parameter of isinstance MUST be a concept")
|
||||
|
||||
b_key = b if isinstance(b, str) else b.key
|
||||
|
||||
# TODO : manage when a is the list of all possible b
|
||||
return a.key == b.key
|
||||
# for example, if a is a color, it will be found the entry 'All_Colors'
|
||||
return a.key == b_key
|
||||
|
||||
@staticmethod
|
||||
def test():
|
||||
|
||||
Reference in New Issue
Block a user