Working on #48 : Added BaseExprParser and BaseNodeParser.py
This commit is contained in:
@@ -7,7 +7,7 @@ from core.sheerka.services.sheerka_service import FailedToCompileError
|
||||
from core.tokenizer import TokenKind, Tokenizer, Keywords
|
||||
from core.utils import get_text_from_tokens
|
||||
from parsers.BaseNodeParser import UnrecognizedTokensNode
|
||||
from parsers.BaseParser import BaseParser, UnexpectedTokenParsingError, UnexpectedEofParsingError, BaseExprParser
|
||||
from parsers.BaseParser import UnexpectedTokenParsingError, UnexpectedEofParsingError, BaseExprParser, ErrorSink
|
||||
from parsers.PythonWithConceptsParser import PythonWithConceptsParser
|
||||
from parsers.expressions import ParenthesisNode, OrNode, AndNode, NotNode, LeftPartNotFoundError, \
|
||||
ParenthesisMismatchError, NameExprNode, ExprNode, VariableNode, ComparisonNode
|
||||
@@ -76,6 +76,7 @@ class LogicalOperatorParser(BaseExprParser):
|
||||
self.and_tokens = list(Tokenizer(" and ", yield_eof=False))
|
||||
self.and_not_tokens = list(Tokenizer(" and not ", yield_eof=False))
|
||||
self.not_tokens = list(Tokenizer("not ", yield_eof=False))
|
||||
self.expr_parser = kwargs.get("expr_parser", None)
|
||||
|
||||
@staticmethod
|
||||
def clean_parenthesis_nodes(nodes):
|
||||
@@ -101,144 +102,161 @@ class LogicalOperatorParser(BaseExprParser):
|
||||
False,
|
||||
sheerka.new(BuiltinConcepts.IS_EMPTY))
|
||||
|
||||
if not self.reset_parser(context, parser_input):
|
||||
return self.sheerka.ret(
|
||||
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=self.error_sink))
|
||||
context.sheerka.new(BuiltinConcepts.ERROR, body=error_sink.sink))
|
||||
|
||||
self.parser_input.next_token()
|
||||
tree = self.parse_input()
|
||||
token = self.parser_input.token
|
||||
tree = self.parse_input(context, parser_input, error_sink)
|
||||
|
||||
token = parser_input.token
|
||||
if token and token.type != TokenKind.EOF:
|
||||
self.add_error(UnexpectedTokenParsingError(f"Unexpected token '{token}'", token, []))
|
||||
error_sink.add_error(UnexpectedTokenParsingError(f"Unexpected token '{token}'", token, []))
|
||||
|
||||
if isinstance(tree, ParenthesisNode):
|
||||
tree = tree.node
|
||||
value = self.get_return_value_body(context.sheerka, self.parser_input.as_text(), tree, tree)
|
||||
|
||||
ret = self.sheerka.ret(
|
||||
self.name,
|
||||
not self.has_error,
|
||||
value)
|
||||
value = self.get_return_value_body(context.sheerka,
|
||||
parser_input.as_text(),
|
||||
tree,
|
||||
tree,
|
||||
error_sink.sink)
|
||||
|
||||
ret = context.sheerka.ret(self.name,
|
||||
not error_sink.has_error,
|
||||
value)
|
||||
|
||||
return ret
|
||||
|
||||
def parse_input(self):
|
||||
return self.parse_or()
|
||||
def parse_input(self, context, parser_input, error_sink):
|
||||
return self.parse_or(context, parser_input, error_sink)
|
||||
|
||||
def parse_or(self):
|
||||
start = self.parser_input.pos
|
||||
expr = self.parse_and()
|
||||
token = self.parser_input.token
|
||||
def parse_or(self, context, parser_input, error_sink):
|
||||
start = parser_input.pos
|
||||
expr = self.parse_and(context, parser_input, error_sink)
|
||||
token = parser_input.token
|
||||
if token.type != TokenKind.IDENTIFIER or token.value != "or":
|
||||
return expr
|
||||
|
||||
parts = [expr]
|
||||
while token.type == TokenKind.IDENTIFIER and token.value == "or":
|
||||
self.parser_input.next_token()
|
||||
expr = self.parse_and()
|
||||
parser_input.next_token()
|
||||
expr = self.parse_and(context, parser_input, error_sink)
|
||||
if expr is None:
|
||||
self.add_error(UnexpectedEofParsingError("When parsing 'or'"))
|
||||
end = self.parser_input.pos
|
||||
error_sink.add_error(UnexpectedEofParsingError("When parsing 'or'"))
|
||||
end = parser_input.pos
|
||||
self.clean_parenthesis_nodes(parts)
|
||||
return OrNode(start, end, self.parser_input.tokens[start: end + 1], *parts)
|
||||
return OrNode(start, end, parser_input.tokens[start: end + 1], *parts)
|
||||
parts.append(expr)
|
||||
token = self.parser_input.token
|
||||
token = parser_input.token
|
||||
|
||||
end = parts[-1].end
|
||||
self.clean_parenthesis_nodes(parts)
|
||||
return OrNode(start, end, self.parser_input.tokens[start: end + 1], *parts)
|
||||
return OrNode(start, end, parser_input.tokens[start: end + 1], *parts)
|
||||
|
||||
def parse_and(self):
|
||||
start = self.parser_input.pos
|
||||
expr = self.parse_not()
|
||||
token = self.parser_input.token
|
||||
def parse_and(self, context, parser_input, error_sink):
|
||||
start = parser_input.pos
|
||||
expr = self.parse_not(context, parser_input, error_sink)
|
||||
token = parser_input.token
|
||||
if token.type != TokenKind.IDENTIFIER or token.value != "and":
|
||||
return expr
|
||||
|
||||
parts = [expr]
|
||||
while token.type == TokenKind.IDENTIFIER and token.value == "and":
|
||||
self.parser_input.next_token()
|
||||
expr = self.parse_not()
|
||||
parser_input.next_token()
|
||||
expr = self.parse_not(context, parser_input, error_sink)
|
||||
if expr is None:
|
||||
self.add_error(UnexpectedEofParsingError("When parsing 'and'"))
|
||||
end = self.parser_input.pos
|
||||
error_sink.add_error(UnexpectedEofParsingError("When parsing 'and'"))
|
||||
end = parser_input.pos
|
||||
self.clean_parenthesis_nodes(parts)
|
||||
return AndNode(start, end, self.parser_input.tokens[start: end + 1], *parts)
|
||||
return AndNode(start, end, parser_input.tokens[start: end + 1], *parts)
|
||||
parts.append(expr)
|
||||
token = self.parser_input.token
|
||||
token = parser_input.token
|
||||
|
||||
end = parts[-1].end
|
||||
self.clean_parenthesis_nodes(parts)
|
||||
return AndNode(start, end, self.parser_input.tokens[start: end + 1], *parts)
|
||||
return AndNode(start, end, parser_input.tokens[start: end + 1], *parts)
|
||||
|
||||
def parse_not(self):
|
||||
token = self.parser_input.token
|
||||
start = self.parser_input.pos
|
||||
def parse_not(self, context, parser_input, error_sink):
|
||||
token = parser_input.token
|
||||
start = parser_input.pos
|
||||
if token.type == TokenKind.IDENTIFIER and token.value == "not":
|
||||
self.parser_input.next_token()
|
||||
parsed = self.parse_not()
|
||||
parser_input.next_token()
|
||||
parsed = self.parse_not(context, parser_input, error_sink)
|
||||
node = parsed.node if isinstance(parsed, ParenthesisNode) else parsed
|
||||
return NotNode(start,
|
||||
parsed.end,
|
||||
self.parser_input.tokens[start: parsed.end + 1],
|
||||
parser_input.tokens[start: parsed.end + 1],
|
||||
node)
|
||||
else:
|
||||
return self.parse_names()
|
||||
return self.parse_names(context, parser_input, error_sink)
|
||||
|
||||
def parse_names(self):
|
||||
def parse_names(self, context, parser_input, error_sink):
|
||||
|
||||
def stop():
|
||||
return token.type == TokenKind.EOF or \
|
||||
paren_count == 0 and token.type == TokenKind.RPAR or \
|
||||
token.type == TokenKind.IDENTIFIER and token.value in ("and", "or", "not")
|
||||
|
||||
token = self.parser_input.token
|
||||
token = parser_input.token
|
||||
if token.type == TokenKind.EOF:
|
||||
return None
|
||||
|
||||
if token.type == TokenKind.LPAR:
|
||||
start = self.parser_input.pos
|
||||
self.parser_input.next_token()
|
||||
expr = self.parse_or()
|
||||
token = self.parser_input.token
|
||||
start = parser_input.pos
|
||||
parser_input.next_token()
|
||||
expr = self.parse_or(context, parser_input, error_sink)
|
||||
token = parser_input.token
|
||||
if token.type != TokenKind.RPAR:
|
||||
self.error_sink.append(
|
||||
error_sink.add_error(
|
||||
UnexpectedTokenParsingError(f"Unexpected token '{token}'", token, [TokenKind.RPAR]))
|
||||
return expr
|
||||
end = self.parser_input.pos
|
||||
self.parser_input.next_token()
|
||||
end = parser_input.pos
|
||||
parser_input.next_token()
|
||||
return ParenthesisNode(start, end, None, expr)
|
||||
|
||||
buffer = []
|
||||
paren_count = 0
|
||||
last_paren = None
|
||||
start = self.parser_input.pos
|
||||
start = parser_input.pos
|
||||
end = parser_input.pos
|
||||
last_is_whitespace = False
|
||||
while not stop():
|
||||
buffer.append(token)
|
||||
last_is_whitespace = token.type == TokenKind.WHITESPACE
|
||||
end += 1
|
||||
if token.type == TokenKind.LPAR:
|
||||
last_paren = token
|
||||
paren_count += 1
|
||||
if token.type == TokenKind.RPAR:
|
||||
paren_count -= 1
|
||||
self.parser_input.next_token(False)
|
||||
token = self.parser_input.token
|
||||
parser_input.next_token(False)
|
||||
token = parser_input.token
|
||||
|
||||
if len(buffer) == 0:
|
||||
if last_is_whitespace:
|
||||
end -= 1
|
||||
|
||||
if start == end:
|
||||
if token.type != TokenKind.RPAR:
|
||||
self.error_sink.append(LeftPartNotFoundError())
|
||||
error_sink.add_error(LeftPartNotFoundError())
|
||||
return None
|
||||
|
||||
if paren_count != 0:
|
||||
self.error_sink.append(ParenthesisMismatchError(last_paren))
|
||||
error_sink.add_error(ParenthesisMismatchError(last_paren))
|
||||
return None
|
||||
|
||||
if buffer[-1].type == TokenKind.WHITESPACE:
|
||||
buffer.pop()
|
||||
|
||||
end = start + len(buffer) - 1
|
||||
return NameExprNode(start, end, buffer)
|
||||
if self.expr_parser:
|
||||
new_parsing_input = ParserInput(
|
||||
None,
|
||||
tokens=parser_input.tokens,
|
||||
length=parser_input.length,
|
||||
start=start,
|
||||
end=end - 1,
|
||||
yield_oef=False).reset()
|
||||
new_parsing_input.next_token()
|
||||
return self.expr_parser.parse_input(context, new_parsing_input, error_sink)
|
||||
else:
|
||||
return NameExprNode(start, end - 1, parser_input.tokens[start:end])
|
||||
|
||||
def compile_conjunctions(self, context, conjunctions, who):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user