Added empty string parser
This commit is contained in:
@@ -25,6 +25,7 @@ class BuiltinConcepts(Enum):
|
|||||||
PARSING = 16 # activated during the parsing. It contains the text to parse
|
PARSING = 16 # activated during the parsing. It contains the text to parse
|
||||||
AFTER_PARSING = 17 # activated when the parsing process seems to be finished
|
AFTER_PARSING = 17 # activated when the parsing process seems to be finished
|
||||||
CONCEPT_ALREADY_DEFINED = 18 # when you try to add the same concept twice
|
CONCEPT_ALREADY_DEFINED = 18 # when you try to add the same concept twice
|
||||||
|
NOP = 19 # no operation concept. Does nothing
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|||||||
+7
-2
@@ -208,7 +208,8 @@ class Sheerka(Concept):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def process(self, context, return_values, contextual_concepts=None):
|
def process(self, context, return_values, contextual_concepts=None):
|
||||||
log.debug("Evaluating parsing result.")
|
contextual_concepts_values = [c.value for c in contextual_concepts] if contextual_concepts else []
|
||||||
|
log.debug(f"Processing parsing result. context concept={contextual_concepts_values}")
|
||||||
|
|
||||||
# return_values must be a list
|
# return_values must be a list
|
||||||
if not isinstance(return_values, list):
|
if not isinstance(return_values, list):
|
||||||
@@ -317,8 +318,12 @@ class Sheerka(Concept):
|
|||||||
"""
|
"""
|
||||||
for part_key in ConceptParts:
|
for part_key in ConceptParts:
|
||||||
source = getattr(concept, part_key.value)
|
source = getattr(concept, part_key.value)
|
||||||
if source is None or source == "":
|
if source is None or not isinstance(source, str) or source == "":
|
||||||
|
|
||||||
|
# the only sources that I am sure to parse are strings
|
||||||
|
# I refuse empty strings for performance, I don't want to handle useless NOPConcepts
|
||||||
continue
|
continue
|
||||||
|
|
||||||
ret_val = self.expect_one(context, self.parse(context, source))
|
ret_val = self.expect_one(context, self.parse(context, source))
|
||||||
concept.codes[part_key] = ret_val
|
concept.codes[part_key] = ret_val
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
from core.builtin_concepts import ParserResultConcept
|
||||||
from core.concept import Concept, ConceptParts
|
from core.concept import Concept, ConceptParts
|
||||||
from evaluators.BaseEvaluator import OneReturnValueEvaluator
|
from evaluators.BaseEvaluator import OneReturnValueEvaluator
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from parsers.BaseParser import BaseParser
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -11,8 +14,9 @@ class ConceptEvaluator(OneReturnValueEvaluator):
|
|||||||
|
|
||||||
def matches(self, context, return_value):
|
def matches(self, context, return_value):
|
||||||
return return_value.status and \
|
return return_value.status and \
|
||||||
return_value.who == "Parsers:ConceptParser" and \
|
return_value.who.startswith(BaseParser.PREFIX) and \
|
||||||
isinstance(return_value.value, Concept)
|
isinstance(return_value.value, Concept) and \
|
||||||
|
not isinstance(return_value.value, ParserResultConcept) # because there are specific evaluators
|
||||||
|
|
||||||
def eval(self, context, return_value):
|
def eval(self, context, return_value):
|
||||||
sheerka = context.sheerka
|
sheerka = context.sheerka
|
||||||
@@ -27,9 +31,12 @@ class ConceptEvaluator(OneReturnValueEvaluator):
|
|||||||
# TODO; check pre
|
# TODO; check pre
|
||||||
# if pre is not true, return Concept with a false value
|
# if pre is not true, return Concept with a false value
|
||||||
|
|
||||||
|
if ConceptParts.BODY in concept.codes:
|
||||||
body = concept.codes[ConceptParts.BODY]
|
body = concept.codes[ConceptParts.BODY]
|
||||||
if body is None:
|
if body is None:
|
||||||
return None # nothing to do
|
return None # nothing to do
|
||||||
|
|
||||||
return sheerka.ret(self.name, True, body.value, parents=[return_value])
|
return sheerka.ret(self.name, True, body.value, parents=[return_value])
|
||||||
|
|
||||||
|
else:
|
||||||
|
return sheerka.ret(self.name, True, concept, parents=[return_value])
|
||||||
|
|||||||
@@ -29,4 +29,4 @@ class PythonEvaluator(OneReturnValueEvaluator):
|
|||||||
error = sheerka.new(BuiltinConcepts.ERROR, body=error)
|
error = sheerka.new(BuiltinConcepts.ERROR, body=error)
|
||||||
return sheerka.ret(self.name, False, error, parents=[return_value])
|
return sheerka.ret(self.name, False, error, parents=[return_value])
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError()
|
return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.ERROR), parents=[return_value])
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
from core.builtin_concepts import BuiltinConcepts
|
||||||
|
from parsers.BaseParser import BaseParser
|
||||||
|
import logging
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class EmptyStringParser(BaseParser):
|
||||||
|
"""
|
||||||
|
To parse empty or blank strings
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
BaseParser.__init__(self, "NullParser")
|
||||||
|
|
||||||
|
def parse(self, context, text):
|
||||||
|
sheerka = context.sheerka
|
||||||
|
|
||||||
|
if isinstance(text, str) and text.strip() == "" or \
|
||||||
|
isinstance(text, list) and text == [] or \
|
||||||
|
text is None:
|
||||||
|
log.debug(f"Recognized '{text}' as BuiltinConcepts.NOP.")
|
||||||
|
return sheerka.ret(self.name, True, sheerka.new(BuiltinConcepts.NOP))
|
||||||
|
|
||||||
|
log.debug(f"Failed to recognize '{text}'")
|
||||||
|
return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.NOT_FOR_ME))
|
||||||
@@ -28,7 +28,7 @@ class ExactConceptParser(BaseParser):
|
|||||||
sheerka = context.sheerka
|
sheerka = context.sheerka
|
||||||
words = self.get_words(text)
|
words = self.get_words(text)
|
||||||
if len(words) > self.MAX_WORDS_SIZE:
|
if len(words) > self.MAX_WORDS_SIZE:
|
||||||
return ReturnValueConcept(self.name, False, sheerka.new(BuiltinConcepts.CONCEPT_TOO_LONG, obj=text))
|
return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.CONCEPT_TOO_LONG, obj=text))
|
||||||
|
|
||||||
recognized = False
|
recognized = False
|
||||||
for combination in self.combinations(words):
|
for combination in self.combinations(words):
|
||||||
@@ -53,7 +53,7 @@ class ExactConceptParser(BaseParser):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
log.debug(f"Failed to recognize {words}")
|
log.debug(f"Failed to recognize {words}")
|
||||||
return ReturnValueConcept(self.name, False, sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, obj=text))
|
return sheerka.ret(self.name, False, sheerka.new(BuiltinConcepts.UNKNOWN_CONCEPT, obj=text))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_words(text):
|
def get_words(text):
|
||||||
|
|||||||
@@ -446,6 +446,21 @@ as:
|
|||||||
assert sheerka.isinstance(res[0].value, BuiltinConcepts.CONCEPT_ALREADY_DEFINED)
|
assert sheerka.isinstance(res[0].value, BuiltinConcepts.CONCEPT_ALREADY_DEFINED)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("text", [
|
||||||
|
"",
|
||||||
|
" ",
|
||||||
|
"\n",
|
||||||
|
])
|
||||||
|
def test_i_can_eval_a_empty_input(text):
|
||||||
|
sheerka = get_sheerka()
|
||||||
|
|
||||||
|
res = sheerka.eval(text)
|
||||||
|
|
||||||
|
assert len(res) == 1
|
||||||
|
assert res[0].status
|
||||||
|
assert sheerka.isinstance(res[0].value, BuiltinConcepts.NOP)
|
||||||
|
|
||||||
|
|
||||||
def get_sheerka():
|
def get_sheerka():
|
||||||
sheerka = Sheerka()
|
sheerka = Sheerka()
|
||||||
sheerka.initialize(root_folder)
|
sheerka.initialize(root_folder)
|
||||||
|
|||||||
Reference in New Issue
Block a user