Added SyaNodeParser (finally, after one month)
This commit is contained in:
+94
-10
@@ -17,12 +17,7 @@ from core.sheerka_logger import console_handler
|
||||
|
||||
import logging
|
||||
|
||||
# CONCEPT_EVALUATION_STEPS = [
|
||||
# BuiltinConcepts.BEFORE_EVALUATION,
|
||||
# BuiltinConcepts.EVALUATION,
|
||||
# BuiltinConcepts.AFTER_EVALUATION]
|
||||
|
||||
CONCEPT_LEXER_PARSER_CLASS = "parsers.ConceptLexerParser.ConceptLexerParser"
|
||||
CONCEPT_LEXER_PARSER_CLASS = "parsers.BnfNodeParser.BnfNodeParser"
|
||||
BNF_PARSER_CLASS = "parsers.BnfParser.BnfParser"
|
||||
CONCEPTS_FILE = "_concepts.txt"
|
||||
|
||||
@@ -37,6 +32,9 @@ class Sheerka(Concept):
|
||||
CONCEPTS_BY_NAME_ENTRY = "Concepts_By_Name"
|
||||
CONCEPTS_BY_HASH_ENTRY = "Concepts_By_Hash" # store hash of concepts definitions (not values)
|
||||
CONCEPTS_DEFINITIONS_ENTRY = "Concepts_Definitions" # to store definitions (bnf) of concepts
|
||||
CONCEPTS_BY_FIRST_KEYWORD_ENTRY = "Concepts_By_First_Keyword"
|
||||
CONCEPTS_SYA_DEFINITION_ENTRY = "Concepts_Sya_Definitions"
|
||||
|
||||
BUILTIN_CONCEPTS_KEYS = "Builtins_Concepts" # sequential key for builtin concepts
|
||||
USER_CONCEPTS_KEYS = "User_Concepts" # sequential key for user defined concepts
|
||||
|
||||
@@ -65,6 +63,10 @@ class Sheerka(Concept):
|
||||
# a grammar is a resolved BNF
|
||||
self.concepts_grammars = {}
|
||||
|
||||
# cache for SYA concepts
|
||||
self.concepts_by_first_keyword = {}
|
||||
self.sya_definitions = {}
|
||||
|
||||
# a concept can be instantiated
|
||||
# ex: File is a concept, but File('foo.txt') is an instance
|
||||
# TODO: manage contexts
|
||||
@@ -119,7 +121,8 @@ class Sheerka(Concept):
|
||||
self.initialize_builtin_concepts()
|
||||
self.initialize_builtin_parsers()
|
||||
self.initialize_builtin_evaluators()
|
||||
self.initialize_concepts_definitions(exec_context)
|
||||
self.initialize_bnf_parsing(exec_context)
|
||||
self.initialize_sya_parsing()
|
||||
res = ReturnValueConcept(self, True, self)
|
||||
|
||||
exec_context.add_values(return_values=res)
|
||||
@@ -174,12 +177,25 @@ class Sheerka(Concept):
|
||||
"""
|
||||
core.utils.init_package_import("parsers")
|
||||
base_class = core.utils.get_class("parsers.BaseParser.BaseParser")
|
||||
modules_to_skip = ["parsers.BaseNodeParser"]
|
||||
|
||||
temp_result = {}
|
||||
for parser in core.utils.get_sub_classes("parsers", base_class):
|
||||
if parser.__module__ == base_class.__module__:
|
||||
continue
|
||||
|
||||
self.init_log.debug(f"Adding builtin parser '{parser.__name__}'")
|
||||
self.parsers[core.utils.get_full_qualified_name(parser)] = parser
|
||||
if parser.__module__ in modules_to_skip:
|
||||
continue
|
||||
|
||||
qualified_name = core.utils.get_full_qualified_name(parser)
|
||||
self.init_log.debug(f"Adding builtin parser '{qualified_name}'")
|
||||
temp_result[qualified_name] = parser
|
||||
|
||||
# Now we sort the parser by name.
|
||||
# It's not important for the logic of their usage as they have their priority anyway,
|
||||
# We do that for the unit tests. They are to complicated to write otherwise
|
||||
for name in sorted(temp_result.keys()):
|
||||
self.parsers[name] = temp_result[name]
|
||||
|
||||
def initialize_builtin_evaluators(self):
|
||||
"""
|
||||
@@ -195,7 +211,7 @@ class Sheerka(Concept):
|
||||
self.init_log.debug(f"Adding builtin evaluator '{evaluator.__name__}'")
|
||||
self.evaluators.append(evaluator)
|
||||
|
||||
def initialize_concepts_definitions(self, execution_context):
|
||||
def initialize_bnf_parsing(self, execution_context):
|
||||
self.init_log.debug("Initializing concepts grammars.")
|
||||
definitions = self.get_concepts_definitions(execution_context)
|
||||
|
||||
@@ -211,6 +227,25 @@ class Sheerka(Concept):
|
||||
|
||||
self.concepts_grammars = lexer_parser.concepts_grammars
|
||||
|
||||
def initialize_sya_parsing(self):
|
||||
self.init_log.debug("Initializing sya definitions.")
|
||||
|
||||
self.concepts_by_first_keyword = self.sdp.get_safe(
|
||||
self.CONCEPTS_BY_FIRST_KEYWORD_ENTRY,
|
||||
load_origin=False) or {}
|
||||
|
||||
self.sya_definitions = self.sdp.get_safe(
|
||||
self.CONCEPTS_SYA_DEFINITION_ENTRY,
|
||||
load_origin=False) or {}
|
||||
|
||||
def reset(self):
|
||||
self.reset_cache()
|
||||
self.concepts_by_first_keyword = {}
|
||||
self.concepts_grammars = {}
|
||||
self.sya_definitions = {}
|
||||
self.sdp.reset()
|
||||
self.sdp.set_key(self.USER_CONCEPTS_KEYS, 1000)
|
||||
|
||||
def reset_cache(self, filter_to_use=None):
|
||||
"""
|
||||
reset the different cache that exists
|
||||
@@ -220,6 +255,7 @@ class Sheerka(Concept):
|
||||
if filter_to_use is None:
|
||||
self.cache_by_key = {}
|
||||
self.cache_by_id = {}
|
||||
self.cache_by_name = {}
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
|
||||
@@ -324,6 +360,38 @@ class Sheerka(Concept):
|
||||
"""
|
||||
return self.sets_handler.set_isa(context, concept, concept_set)
|
||||
|
||||
def set_sya_def(self, context, list_of_def):
|
||||
"""
|
||||
Set the precedence and/or the associativity of a concept
|
||||
:param context:
|
||||
:param list_of_def list of tuple(concept_id, precedence (int), SyaAssociativity)
|
||||
:return:
|
||||
"""
|
||||
|
||||
# validate the entries
|
||||
for concept_id, precedence, associativity in list_of_def:
|
||||
if concept_id == BuiltinConcepts.UNKNOWN_CONCEPT:
|
||||
return self.ret(self.name,
|
||||
False,
|
||||
self.new(BuiltinConcepts.ERROR, body=f"Concept {concept_id} is not known"))
|
||||
|
||||
# update the definitions
|
||||
for concept_id, precedence, associativity in list_of_def:
|
||||
if precedence is None and associativity is None:
|
||||
try:
|
||||
del self.sya_definitions[concept_id]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
self.sya_definitions[concept_id] = (precedence, associativity.value)
|
||||
|
||||
# then save
|
||||
self.sdp.set(context.event.get_digest(),
|
||||
self.CONCEPTS_SYA_DEFINITION_ENTRY,
|
||||
self.sya_definitions)
|
||||
|
||||
return self.ret(self.name, True, self.new(BuiltinConcepts.SUCCESS))
|
||||
|
||||
def get_set_elements(self, context, concept):
|
||||
"""
|
||||
Concept is supposed to be a set
|
||||
@@ -571,6 +639,22 @@ class Sheerka(Concept):
|
||||
|
||||
return self.value(body_to_use)
|
||||
|
||||
def get_error(self, obj):
|
||||
if isinstance(obj, Concept) and obj.metadata.is_builtin and obj.key in BuiltinErrors:
|
||||
return obj
|
||||
|
||||
if isinstance(obj, list):
|
||||
return obj
|
||||
|
||||
if self.isinstance(obj, BuiltinConcepts.RETURN_VALUE):
|
||||
if obj.status:
|
||||
return None
|
||||
|
||||
if self.isinstance(obj.body, BuiltinConcepts.PARSER_RESULT):
|
||||
return self.get_error(obj.body.body)
|
||||
|
||||
return NotImplementedError()
|
||||
|
||||
def get_values(self, objs):
|
||||
if not (isinstance(objs, list) or
|
||||
self.isinstance(objs, BuiltinConcepts.LIST) or
|
||||
|
||||
Reference in New Issue
Block a user