Implemented some enhancement request and fixed some bugs

Fixed #2 : Variables are not recognized when inside a rule token
Fixed #15 : Rule: rete attributes are lost when a new ontology is created
Fixed #14 : ReteNetwork: Format rules must not be added to Rete network
Fixed #16 : DefConcept: Variables are not recognized when they are keyword arguments
Fixed #4 : Comparison are not correctly set when comparison property is a concept
Fixed #14 : Parser: merge FunctionParser.NamesNode and ExpressionParser.NamesNode
Fixed #18 : Parser: Add SourceCodeNode test to UnrecognizedNodeParser
Fixed #20 : At startup Number concept is saved in db a numerous number of time
Fixed #21 : CacheManager: I can remove all elements from a ListIfNeededCache and fill it again
Fixed #22 : CacheManager: I can remove all elements from a SetCache and fill it again
Fixed #23 : HistoryManager: history() no longer works
Fixed #24 : HistoryManager: history() no longer works after creating an exec rule
Fixed #25 : SheerkaMemory: Use MemoryObject instead of sheerka.local
Fixed #26 : Debugger: add the list all available services..
Fixed #27 : CONCEPTS_GRAMMARS_ENTRY does not seems to be in use any more
Fixed #28 : Give order to services
This commit is contained in:
2021-02-12 15:15:31 +01:00
parent 3a12ea58df
commit cac2dad17f
62 changed files with 1182 additions and 480 deletions
+18 -54
View File
@@ -1,22 +1,20 @@
from dataclasses import dataclass
from typing import List
from core.builtin_concepts import BuiltinConcepts
from core.builtin_helpers import get_lexer_nodes_from_unrecognized, update_compiled
from core.concept import Concept
from core.sheerka.services.SheerkaExecute import ParserInput
from core.tokenizer import TokenKind, Token
from core.tokenizer import TokenKind
from core.utils import get_n_clones
from parsers.SequenceNodeParser import SequenceNodeParser
from parsers.BaseNodeParser import SourceCodeNode, SourceCodeWithConceptNode, UnrecognizedTokensNode
from parsers.BaseParser import BaseParser, UnexpectedTokenParsingError, UnexpectedEofParsingError, Node
from parsers.BnfNodeParser import BnfNodeParser
from parsers.PythonWithConceptsParser import PythonWithConceptsParser
from parsers.RuleParser import RuleParser
from parsers.SequenceNodeParser import SequenceNodeParser
from parsers.SyaNodeParser import SyaNodeParser
from parsers.expressions import NameExprNode
# No need to check for Python code as the source code node will resolve to python code anyway
# I only look for concepts, so
PARSERS = [RuleParser.NAME,
SequenceNodeParser.NAME,
BnfNodeParser.NAME,
@@ -28,49 +26,16 @@ class FunctionParserNode(Node):
pass
@dataclass()
class NamesNode(FunctionParserNode):
start: int # index of the first token
end: int # index of the last token
tokens: List[Token]
def __repr__(self):
return f"NameNode('{self.str_value()}')"
def str_value(self):
if self.tokens is None:
return None
return "".join([t.str_value for t in self.tokens])
def to_unrecognized(self):
"""
UnrecognizedTokensNode with all tokens
"""
return UnrecognizedTokensNode(self.start, self.end, self.tokens).fix_source()
def to_str_unrecognized(self):
"""
UnrecognizedTokensNode with one token, which is a string token of all the tokens
"""
token = Token(TokenKind.STRING,
"'" + self.str_value() + "'",
self.tokens[0].index,
self.tokens[0].line,
self.tokens[0].column)
return UnrecognizedTokensNode(self.start, self.end, [token]).fix_source()
@dataclass()
class FunctionParameter:
"""
class the represent result of the parameter parsing
"""
value: NamesNode # value parsed
separator: NamesNode = None # holds the value and the position of the separator
value: NameExprNode # value parsed
separator: NameExprNode = None # holds the value and the position of the separator
def add_sep(self, start, end, tokens):
self.separator = NamesNode(start, end, tokens)
self.separator = NameExprNode(start, end, tokens)
def value_to_unrecognized(self):
return UnrecognizedTokensNode(self.value.start, self.value.end, self.value.tokens).fix_source()
@@ -83,8 +48,8 @@ class FunctionParameter:
@dataclass
class FunctionNode(FunctionParserNode):
first: NamesNode # beginning of the function (it should represent the name of the function)
last: NamesNode # last part of the function (it should be the trailing parenthesis)
first: NameExprNode # beginning of the function (it should represent the name of the function)
last: NameExprNode # last part of the function (it should be the trailing parenthesis)
parameters: list
@@ -95,11 +60,11 @@ class FN(FunctionNode):
Thereby,
FN("first", "last", ["param1," ...]) can be compared to
FunctionNode(NamesNode("first"), NamesNode("second"), [FunctionParameter(NamesNodes("param1"), NamesNodes(", ")])
FunctionNode(NameExprNode("first"), NameExprNode("second"), [FunctionParameter(NamesNodes("param1"), NamesNodes(", ")])
Note that FunctionParameter can easily be defined with a single string
* "param" -> FunctionParameter(NamesNode("param"), None)
* "param, " -> FunctionParameter(NamesNode("param"), NamesNode(", "))
* "param" -> FunctionParameter(NameExprNode("param"), None)
* "param, " -> FunctionParameter(NameExprNode("param"), NameExprNode(", "))
For more complicated situations, you can use a tuple (value, sep) to define the value part and the separator part
"""
@@ -123,14 +88,13 @@ class FN(FunctionNode):
return self.first == other.first and self.last == other.last and self.parameters == other.parameters
if isinstance(other, FunctionNode):
if self.first != other.first.str_value() or self.last != other.last.str_value():
if self.first != other.first.value or self.last != other.last.value:
return False
if len(self.parameters) != len(other.parameters):
return False
for self_parameter, other_parameter in zip(self.parameters, other.parameters):
value = other_parameter.value.str_value() if isinstance(self_parameter[0],
str) else other_parameter.value
sep = other_parameter.separator.str_value() if other_parameter.separator else None
value = other_parameter.value.value if isinstance(self_parameter[0], str) else other_parameter.value
sep = other_parameter.separator.value if other_parameter.separator else None
if self_parameter[0] != value or self_parameter[1] != sep:
return False
@@ -244,7 +208,7 @@ class FunctionParser(BaseParser):
[TokenKind.LPAR]))
return None
start_node = NamesNode(start, start + 1, self.parser_input.tokens[start:start + 2])
start_node = NameExprNode(start, start + 1, self.parser_input.tokens[start:start + 2])
if not self.parser_input.next_token():
self.add_error(UnexpectedEofParsingError(f"Unexpected EOF after left parenthesis"))
return FunctionNode(start_node, None, None)
@@ -261,7 +225,7 @@ class FunctionParser(BaseParser):
return FunctionNode(start_node, None, params)
return FunctionNode(start_node,
NamesNode(self.parser_input.pos, self.parser_input.pos, [token]),
NameExprNode(self.parser_input.pos, self.parser_input.pos, [token]),
params)
def parse_parameters(self):
@@ -319,7 +283,7 @@ class FunctionParser(BaseParser):
if not self.parser_input.next_token(skip_whitespace=False):
break
return NamesNode(start_pos, self.parser_input.pos - 1, tokens) if len(tokens) else None
return NameExprNode(start_pos, self.parser_input.pos - 1, tokens) if len(tokens) else None
def to_source_code_node(self, function_node: FunctionNode):
python_parser = PythonWithConceptsParser()
@@ -350,7 +314,7 @@ class FunctionParser(BaseParser):
# try to recognize every parameter, one by one
for param in function_node.parameters:
if isinstance(param.value, NamesNode):
if isinstance(param.value, NameExprNode):
# try to recognize concepts
unrecognized = param.value.to_unrecognized()
nodes_sequences = get_lexer_nodes_from_unrecognized(self.context,