Working on #48 : Fixed first version of ExpressionParser.py
This commit is contained in:
@@ -13,6 +13,9 @@ class ErrorSink:
|
||||
def __init__(self):
|
||||
self.sink = []
|
||||
|
||||
def __repr__(self):
|
||||
return f"Errors({self.sink})"
|
||||
|
||||
def add_error(self, error):
|
||||
self.sink.append(error)
|
||||
|
||||
@@ -258,4 +261,3 @@ class BaseParserInputParser(BaseParser):
|
||||
by_ids.add(c.id)
|
||||
|
||||
return list_a
|
||||
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
from core.builtin_concepts_ids import BuiltinConcepts
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput
|
||||
from core.tokenizer import TokenKind
|
||||
from core.utils import get_text_from_tokens
|
||||
from parsers.BaseParser import ErrorSink
|
||||
from parsers.BaseExpressionParser import NameExprNode, VariableNode, BaseExpressionParser
|
||||
from parsers.FunctionParser import FunctionParser
|
||||
from parsers.LogicalOperatorParser import LogicalOperatorParser
|
||||
from parsers.RelationalOperatorParser import RelationalOperatorParser
|
||||
from parsers.BaseExpressionParser import ParenthesisNode, NameExprNode, VariableNode, BaseExpressionParser
|
||||
|
||||
|
||||
class ExpressionParser(BaseExpressionParser):
|
||||
@@ -19,59 +16,15 @@ class ExpressionParser(BaseExpressionParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(ExpressionParser.NAME, 60, False, yield_eof=False)
|
||||
self.variable_parser = VariableOrNamesParser()
|
||||
self.function_parser = FunctionParser()
|
||||
self.relational_parser = RelationalOperatorParser(expr_parser=self.variable_parser)
|
||||
self.function_parser = FunctionParser(expr_parser=self, tokens_parser=self.variable_parser)
|
||||
self.relational_parser = RelationalOperatorParser(expr_parser=self.function_parser)
|
||||
self.logical_parser = LogicalOperatorParser(expr_parser=self.relational_parser)
|
||||
|
||||
def parse(self, context, parser_input: ParserInput):
|
||||
"""
|
||||
:param context:
|
||||
:param parser_input:
|
||||
:return:
|
||||
"""
|
||||
|
||||
if not isinstance(parser_input, ParserInput):
|
||||
return None
|
||||
|
||||
context.log(f"Parsing '{parser_input}' with {self.NAME}Parser", self.name)
|
||||
sheerka = context.sheerka
|
||||
|
||||
if parser_input.is_empty():
|
||||
return context.sheerka.ret(self.name,
|
||||
False,
|
||||
sheerka.new(BuiltinConcepts.IS_EMPTY))
|
||||
|
||||
error_sink = ErrorSink()
|
||||
if not self.reset_parser_input(parser_input, error_sink):
|
||||
return context.sheerka.ret(
|
||||
self.name,
|
||||
False,
|
||||
context.sheerka.new(BuiltinConcepts.ERROR, body=error_sink.sink))
|
||||
|
||||
node = self.parse_input(context, parser_input, error_sink)
|
||||
if isinstance(node, ParenthesisNode):
|
||||
node = node.node
|
||||
|
||||
value = self.get_return_value_body(context.sheerka, parser_input.as_text(), node, node, error_sink.sink)
|
||||
|
||||
ret = context.sheerka.ret(
|
||||
self.name,
|
||||
not error_sink.has_error,
|
||||
value)
|
||||
|
||||
return ret
|
||||
|
||||
def parse_input(self, context, parser_input, error_sink):
|
||||
pos = parser_input.pos
|
||||
for parser in [self.logical_parser,
|
||||
self.relational_parser,
|
||||
self.variable_parser]: # [self.logical_parser, self.relational_parser, self.function_parser]:
|
||||
parser_input.seek(pos) # reset position
|
||||
res = parser.parse_input(context, parser_input, error_sink)
|
||||
if res and not error_sink.has_error:
|
||||
return res
|
||||
return self.logical_parser.parse_input(context, parser_input, error_sink)
|
||||
|
||||
return None
|
||||
def parse_tokens_stop_condition(self, token, parser_input):
|
||||
pass
|
||||
|
||||
|
||||
class VariableOrNamesParser(BaseExpressionParser):
|
||||
@@ -80,44 +33,6 @@ class VariableOrNamesParser(BaseExpressionParser):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(VariableOrNamesParser.NAME, 60, False, yield_eof=False)
|
||||
|
||||
def parse(self, context, parser_input: ParserInput):
|
||||
"""
|
||||
:param context:
|
||||
:param parser_input:
|
||||
:return:
|
||||
"""
|
||||
|
||||
if not isinstance(parser_input, ParserInput):
|
||||
return None
|
||||
|
||||
context.log(f"Parsing '{parser_input}' with {self.NAME}Parser", self.name)
|
||||
sheerka = context.sheerka
|
||||
|
||||
if parser_input.is_empty():
|
||||
return context.sheerka.ret(self.name,
|
||||
False,
|
||||
sheerka.new(BuiltinConcepts.IS_EMPTY))
|
||||
|
||||
error_sink = ErrorSink()
|
||||
if not self.reset_parser_input(parser_input, error_sink):
|
||||
return context.sheerka.ret(
|
||||
self.name,
|
||||
False,
|
||||
context.sheerka.new(BuiltinConcepts.ERROR, body=error_sink.sink))
|
||||
|
||||
node = self.parse_input(context, parser_input, error_sink)
|
||||
if isinstance(node, ParenthesisNode):
|
||||
node = node.node
|
||||
|
||||
value = self.get_return_value_body(context.sheerka, parser_input.as_text(), node, node, error_sink.sink)
|
||||
|
||||
ret = context.sheerka.ret(
|
||||
self.name,
|
||||
not error_sink.has_error,
|
||||
value)
|
||||
|
||||
return ret
|
||||
|
||||
def parse_input(self, context, parser_input, error_sink):
|
||||
# try to recognize a VariableNode
|
||||
dots_found = []
|
||||
@@ -148,3 +63,6 @@ class VariableOrNamesParser(BaseExpressionParser):
|
||||
parser_input.as_tokens(),
|
||||
parts[0],
|
||||
*parts[1:])
|
||||
|
||||
def parse_tokens_stop_condition(self, token, parser_input):
|
||||
pass
|
||||
|
||||
@@ -40,6 +40,7 @@ class FunctionParser(BaseExpressionParser):
|
||||
self.sep = sep
|
||||
self.longest_concepts_only = longest_concepts_only
|
||||
self.expr_parser = kwargs.get("expr_parser", None)
|
||||
self.tokens_parser = kwargs.get("tokens_parser", None)
|
||||
|
||||
def function_parser_get_return_value_body(self, context, source, source_code_node):
|
||||
if source_code_node.error_when_parsing:
|
||||
@@ -71,7 +72,16 @@ class FunctionParser(BaseExpressionParser):
|
||||
return res[0] if len(res) == 1 else res
|
||||
|
||||
def parse_input(self, context, parser_input, error_sink):
|
||||
return self.parse_function(context, parser_input, error_sink)
|
||||
# when FunctionParser is used by LexerNode or SheerkaExecute, it must fail if no function is found
|
||||
# when it is used by ExpressionParser, it must default to VariableOrNamesParser
|
||||
pos = parser_input.pos
|
||||
res = self.parse_function(context, parser_input, error_sink)
|
||||
if (not res or error_sink.has_error) and self.tokens_parser:
|
||||
parser_input.seek(pos)
|
||||
error_sink.clear()
|
||||
return self.tokens_parser.parse_input(context, parser_input, error_sink)
|
||||
|
||||
return res
|
||||
|
||||
def parse_function(self, context, parser_input, error_sink):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user