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:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user