Added DefaultParser
This commit is contained in:
+73
-10
@@ -1,29 +1,92 @@
|
||||
import hashlib
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class ConceptParts(Enum):
|
||||
WHERE = "where"
|
||||
PRE = "pre"
|
||||
POST = "post"
|
||||
BODY = "body"
|
||||
|
||||
|
||||
class Concept:
|
||||
"""
|
||||
Default concept object
|
||||
A concept is a the base object of our universe
|
||||
Everything is a concept
|
||||
"""
|
||||
props_to_serialize = ("id", "name", "where", "pre", "post", "body", "desc")
|
||||
|
||||
concepts_id = 0
|
||||
key_name = "concepts"
|
||||
|
||||
def __init__(self, name, is_builtin=False):
|
||||
def __init__(self, name=None, is_builtin=False, where=None, pre=None, post=None, body=None, desc=None):
|
||||
self.name = name
|
||||
self.is_builtin = is_builtin
|
||||
self.pre = None # list of pre conditions before calling the main function
|
||||
self.post = None # list of post conditions after calling the main function
|
||||
self.main = None # main method, can also be the value of the concept
|
||||
self.id = Concept.concepts_id
|
||||
Concept.concepts_id = Concept.concepts_id + 1
|
||||
self.where = where # condition to recognize variables in name
|
||||
self.pre = pre # list of pre conditions before calling the main function
|
||||
self.post = post # list of post conditions after calling the main function
|
||||
self.body = body # main method, can also be the value of the concept
|
||||
self.desc = desc
|
||||
self.key = None
|
||||
self.parent = None
|
||||
|
||||
self.props = [] # list of Property for this concept
|
||||
self.functions = {} # list of helper functions
|
||||
|
||||
def __str__(self):
|
||||
return f"({self.id}){self.name}"
|
||||
self.codes = {}
|
||||
|
||||
def __repr__(self):
|
||||
return f"({self.id}){self.name}"
|
||||
return f"({self.key}){self.name}"
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, Concept):
|
||||
return False
|
||||
return self.name == other.name and \
|
||||
self.where == other.where and \
|
||||
self.pre == other.pre and \
|
||||
self.post == other.post and \
|
||||
self.body == other.body
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.name)
|
||||
|
||||
def add_codes(self, codes):
|
||||
"""
|
||||
From a dict of <ConceptParts, AST>
|
||||
fill the codes
|
||||
:param codes:
|
||||
:return:
|
||||
"""
|
||||
possibles_codes = set(item.value for item in ConceptParts)
|
||||
if codes is None:
|
||||
return
|
||||
for key in codes:
|
||||
if key in possibles_codes:
|
||||
self.codes[ConceptParts(key)] = codes[key]
|
||||
|
||||
def get_digest(self):
|
||||
"""
|
||||
Returns the digest of the event
|
||||
:return: hexa form of the sha256
|
||||
"""
|
||||
return hashlib.sha256(f"Concept:{self.name}{self.pre}{self.post}{self.body}".encode("utf-8")).hexdigest()
|
||||
|
||||
def to_dict(self):
|
||||
props_as_dict = dict((prop, getattr(self, prop)) for prop in self.props_to_serialize)
|
||||
return props_as_dict
|
||||
|
||||
def from_dict(self, as_dict):
|
||||
for prop in self.props_to_serialize:
|
||||
setattr(self, prop, as_dict[prop])
|
||||
return self
|
||||
|
||||
|
||||
class ErrorConcept(Concept):
|
||||
def __init__(self, where=None, pre=None, post=None, body=None, desc=None):
|
||||
Concept.__init__(self, "error", is_builtin=True, where=where, pre=pre, post=post, body=body, desc=desc)
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.name} : {self.body}"
|
||||
|
||||
|
||||
class Property:
|
||||
|
||||
+49
-9
@@ -1,8 +1,9 @@
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
|
||||
from core.concept import Concept
|
||||
from sdp.sheerkaDataProvider import SheerkaDataProvider
|
||||
from core.concept import Concept, ErrorConcept
|
||||
from parsers.PythonParser import PythonParser
|
||||
from sdp.sheerkaDataProvider import SheerkaDataProvider, Event
|
||||
from parsers.DefaultParser import DefaultParser, DefConceptNode
|
||||
|
||||
|
||||
class Singleton(type):
|
||||
@@ -54,6 +55,7 @@ class Sheerka(Concept, metaclass=Singleton):
|
||||
self.create_builtin_concepts()
|
||||
|
||||
self.sdp = None
|
||||
self.parsers = []
|
||||
|
||||
def create_builtin_concepts(self):
|
||||
"""
|
||||
@@ -76,11 +78,38 @@ class Sheerka(Concept, metaclass=Singleton):
|
||||
|
||||
try:
|
||||
self.sdp = SheerkaDataProvider(root_folder)
|
||||
self.parsers.append(lambda text: DefaultParser(text, PythonParser))
|
||||
except IOError as e:
|
||||
return ReturnValue(False, self.get_concept(Sheerka.ERROR_CONCEPT_NAME, True), e)
|
||||
|
||||
return ReturnValue(True, self.get_concept(Sheerka.SUCCESS_CONCEPT_NAME, True))
|
||||
|
||||
def eval(self, text):
|
||||
#evt_digest = self.sdp.save_event(Event(text))
|
||||
result = self.try_parse(text)
|
||||
|
||||
return_values = []
|
||||
for parser_name, status, node in result:
|
||||
if not status:
|
||||
return_values.append(ReturnValue(False, ErrorConcept(body=node)))
|
||||
elif status and isinstance(node, DefConceptNode):
|
||||
return_values.append(self.add_concept(node))
|
||||
|
||||
return return_values
|
||||
|
||||
def try_parse(self, text):
|
||||
result = []
|
||||
for parser in self.parsers:
|
||||
p = parser(text)
|
||||
# try:
|
||||
# tree = p.parse()
|
||||
# result.append((p.name, tree))
|
||||
# except Exception as e:
|
||||
# result.append((p.name, e))
|
||||
tree = p.parse()
|
||||
result.append((p.name, not p.has_error, p.error_sink if p.has_error else tree))
|
||||
return result
|
||||
|
||||
def get_concept(self, name, is_builtin=False):
|
||||
"""
|
||||
Given a concept name, tries to find it
|
||||
@@ -93,6 +122,22 @@ class Sheerka(Concept, metaclass=Singleton):
|
||||
return concept
|
||||
return self.concepts[1]
|
||||
|
||||
def add_concept(self, def_concept_node: DefConceptNode):
|
||||
"""
|
||||
Adds a new concept to the system
|
||||
:param def_concept_node: DefConceptNode
|
||||
:return: digest of the new concept
|
||||
"""
|
||||
|
||||
concept = Concept(def_concept_node.name)
|
||||
for prop in ("where", "pre", "post", "body"):
|
||||
concept_part_node = getattr(def_concept_node, prop)
|
||||
value = concept_part_node.source if hasattr(concept_part_node, "source") else ""
|
||||
setattr(concept, prop, value)
|
||||
|
||||
concept.add_codes(def_concept_node.get_codes())
|
||||
return ReturnValue(True, concept)
|
||||
|
||||
@staticmethod
|
||||
def concept_equals(concept1, concept2):
|
||||
"""True if the two concepts refer to the same concept"""
|
||||
@@ -102,9 +147,4 @@ class Sheerka(Concept, metaclass=Singleton):
|
||||
if concept1 is None or concept2 is None:
|
||||
return False
|
||||
|
||||
return concept1.id == concept2.id
|
||||
|
||||
def record_event(self, event):
|
||||
self.sdp.save_event(event)
|
||||
|
||||
|
||||
return concept1.key == concept2.key
|
||||
|
||||
Reference in New Issue
Block a user