Introduced ParserInput
This commit is contained in:
+76
-73
@@ -4,6 +4,7 @@ from dataclasses import dataclass
|
||||
|
||||
import core.utils
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from core.sheerka.services.SheerkaExecute import ParserInput, SheerkaExecute
|
||||
from core.tokenizer import LexerError, TokenKind
|
||||
from parsers.BaseParser import BaseParser, Node, ErrorNode
|
||||
from parsers.BnfNodeParser import ConceptNode
|
||||
@@ -28,7 +29,7 @@ class PythonNode(Node):
|
||||
self.concepts = concepts or {} # when concepts are recognized in the expression
|
||||
|
||||
# def __repr__(self):
|
||||
# return "PythonNode(source='" + self.source + "', ast=" + self.get_dump(self.ast_) + ")"
|
||||
# return "PythonNode(parser_input='" + self.parser_input + "', ast=" + self.get_dump(self.ast_) + ")"
|
||||
|
||||
def __repr__(self):
|
||||
ast_type = "expr" if isinstance(self.ast_, ast.Expression) else "module"
|
||||
@@ -57,77 +58,6 @@ class PythonNode(Node):
|
||||
return dump
|
||||
|
||||
|
||||
class PythonParser(BaseParser):
|
||||
"""
|
||||
Parse Python scripts
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
BaseParser.__init__(self, "Python", 50)
|
||||
self.source = kwargs.get("source", "<undef>")
|
||||
|
||||
def parse(self, context, parser_input):
|
||||
sheerka = context.sheerka
|
||||
tree = None
|
||||
|
||||
python_switcher = {
|
||||
TokenKind.CONCEPT: lambda t: core.utils.encode_concept(t.value)
|
||||
}
|
||||
|
||||
try:
|
||||
tracker = {}
|
||||
source = self.get_input_as_text(parser_input, python_switcher, tracker)
|
||||
source = source.strip()
|
||||
parser_input = parser_input if isinstance(parser_input, str) else source
|
||||
|
||||
# first, try to parse an expression
|
||||
res, tree, error = self.try_parse_expression(source)
|
||||
if not res:
|
||||
# then try to parse a statement
|
||||
res, tree, error = self.try_parse_statement(source)
|
||||
if not res:
|
||||
error_node = PythonErrorNode(parser_input, error)
|
||||
self.error_sink.append(error_node)
|
||||
|
||||
except LexerError as e:
|
||||
self.error_sink.append(e)
|
||||
|
||||
if self.has_error:
|
||||
ret = sheerka.ret(
|
||||
self.name,
|
||||
False,
|
||||
sheerka.new(
|
||||
BuiltinConcepts.NOT_FOR_ME,
|
||||
body=parser_input,
|
||||
reason=self.error_sink))
|
||||
else:
|
||||
ret = sheerka.ret(
|
||||
self.name,
|
||||
True,
|
||||
sheerka.new(
|
||||
BuiltinConcepts.PARSER_RESULT,
|
||||
parser=self,
|
||||
source=parser_input,
|
||||
body=PythonNode(parser_input, tree, tracker),
|
||||
try_parsed=None))
|
||||
|
||||
self.log_result(context, parser_input, ret)
|
||||
return ret
|
||||
|
||||
def try_parse_expression(self, text):
|
||||
try:
|
||||
return True, ast.parse(text, f"<{self.source}>", 'eval'), None
|
||||
except Exception as error:
|
||||
return False, None, error
|
||||
|
||||
def try_parse_statement(self, text):
|
||||
try:
|
||||
return True, ast.parse(text, f"<{self.source}>", 'exec'), None
|
||||
except Exception as error:
|
||||
return False, None, error
|
||||
|
||||
|
||||
class PythonGetNamesVisitor(ast.NodeVisitor):
|
||||
"""
|
||||
This visitor will find all the name declared in the ast
|
||||
@@ -206,7 +136,8 @@ class LexerNodeParserHelperForPython:
|
||||
with context.push(self, desc="Trying Python for '" + to_parse + "'") as sub_context:
|
||||
sub_context.add_inputs(to_parse=to_parse)
|
||||
python_parser = PythonParser()
|
||||
result = python_parser.parse(sub_context, to_parse)
|
||||
parser_input = context.sheerka.services[SheerkaExecute.NAME].get_parser_input(to_parse)
|
||||
result = python_parser.parse(sub_context, parser_input)
|
||||
sub_context.add_values(return_values=result)
|
||||
|
||||
if result.status:
|
||||
@@ -216,3 +147,75 @@ class LexerNodeParserHelperForPython:
|
||||
return python_node
|
||||
|
||||
return result.body # the error
|
||||
|
||||
|
||||
class PythonParser(BaseParser):
|
||||
"""
|
||||
Parse Python scripts
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
BaseParser.__init__(self, "Python", 50)
|
||||
self.source = kwargs.get("source", "<undef>")
|
||||
|
||||
def parse(self, context, parser_input: ParserInput):
|
||||
sheerka = context.sheerka
|
||||
tree = None
|
||||
tracker = {} # to keep track of concept tokens (c:xxx:)
|
||||
|
||||
python_switcher = {
|
||||
TokenKind.CONCEPT: lambda t: core.utils.encode_concept(t.value)
|
||||
}
|
||||
|
||||
try:
|
||||
parser_input.reset()
|
||||
|
||||
source_code = parser_input.as_text(python_switcher, tracker)
|
||||
source_code = source_code.strip()
|
||||
|
||||
# first, try to parse an expression
|
||||
res, tree, error = self.try_parse_expression(source_code)
|
||||
if not res:
|
||||
# then try to parse a statement
|
||||
res, tree, error = self.try_parse_statement(source_code)
|
||||
if not res:
|
||||
error_node = PythonErrorNode(parser_input.as_text(), error)
|
||||
self.error_sink.append(error_node)
|
||||
|
||||
except LexerError as e:
|
||||
self.error_sink.append(e)
|
||||
|
||||
if self.has_error:
|
||||
ret = sheerka.ret(
|
||||
self.name,
|
||||
False,
|
||||
sheerka.new(
|
||||
BuiltinConcepts.NOT_FOR_ME,
|
||||
body=parser_input.as_text(),
|
||||
reason=self.error_sink))
|
||||
else:
|
||||
ret = sheerka.ret(
|
||||
self.name,
|
||||
True,
|
||||
sheerka.new(
|
||||
BuiltinConcepts.PARSER_RESULT,
|
||||
parser=self,
|
||||
source=parser_input.as_text(),
|
||||
body=PythonNode(source_code, tree, tracker),
|
||||
try_parsed=None))
|
||||
|
||||
self.log_result(context, parser_input.as_text(), ret)
|
||||
return ret
|
||||
|
||||
def try_parse_expression(self, text):
|
||||
try:
|
||||
return True, ast.parse(text, f"<{self.source}>", 'eval'), None
|
||||
except Exception as error:
|
||||
return False, None, error
|
||||
|
||||
def try_parse_statement(self, text):
|
||||
try:
|
||||
return True, ast.parse(text, f"<{self.source}>", 'exec'), None
|
||||
except Exception as error:
|
||||
return False, None, error
|
||||
|
||||
Reference in New Issue
Block a user