Added DefaultParser

This commit is contained in:
2019-10-29 18:39:51 +01:00
parent 101319b8b6
commit 8107e149b9
18 changed files with 1581 additions and 376 deletions
+73 -10
View File
@@ -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
View File
@@ -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