Refactored to allow ConceptEvaluator
This commit is contained in:
+48
-9
@@ -1,3 +1,4 @@
|
||||
from core.builtin_concepts import BuiltinConcepts
|
||||
from parsers.BaseParser import BaseParser, Node, ErrorNode
|
||||
from dataclasses import dataclass
|
||||
import ast
|
||||
@@ -12,23 +13,50 @@ class PythonErrorNode(ErrorNode):
|
||||
source: str
|
||||
exception: Exception
|
||||
|
||||
def __post_init__(self):
|
||||
log.debug("-> PythonErrorNode: " + str(self.exception))
|
||||
# def __post_init__(self):
|
||||
# log.debug("-> PythonErrorNode: " + str(self.exception))
|
||||
|
||||
|
||||
@dataclass()
|
||||
class PythonNode(Node):
|
||||
source: str
|
||||
ast: ast.AST
|
||||
ast_: ast.AST
|
||||
|
||||
# def __repr__(self):
|
||||
# return "PythonNode(source='" + self.source + "', ast=" + self.get_dump(self.ast_) + ")"
|
||||
|
||||
def __repr__(self):
|
||||
return "PythonNode(" + ast.dump(self.ast) + ")"
|
||||
# return "PythonNode(" + self.source + ")"
|
||||
ast_type = "expr" if isinstance(self.ast_, ast.Expression) else "module"
|
||||
return "PythonNode(" + ast_type + "='" + self.source + "')"
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, PythonNode):
|
||||
return False
|
||||
|
||||
if self.source != other.source:
|
||||
return False
|
||||
|
||||
self_dump = self.get_dump(self.ast_)
|
||||
other_dump = self.get_dump(other.ast_)
|
||||
|
||||
return self_dump == other_dump
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.source, self.ast_.hash))
|
||||
|
||||
@staticmethod
|
||||
def get_dump(ast_):
|
||||
dump = ast.dump(ast_)
|
||||
for to_remove in [", ctx=Load()", ", kind=None", ", type_ignores=[]"]:
|
||||
dump = dump.replace(to_remove, "")
|
||||
return dump
|
||||
|
||||
|
||||
class PythonParser(BaseParser):
|
||||
"""
|
||||
Parse Python scripts
|
||||
"""
|
||||
|
||||
def __init__(self, source="<undef>"):
|
||||
|
||||
BaseParser.__init__(self, "PythonParser")
|
||||
@@ -38,6 +66,8 @@ class PythonParser(BaseParser):
|
||||
text = text if isinstance(text, str) else self.get_text_from_tokens(text)
|
||||
text = text.strip()
|
||||
|
||||
sheerka = context.sheerka
|
||||
|
||||
# first, try to parse an expression
|
||||
res, tree, error = self.try_parse_expression(text)
|
||||
if not res:
|
||||
@@ -47,10 +77,19 @@ class PythonParser(BaseParser):
|
||||
self.has_error = True
|
||||
error_node = PythonErrorNode(text, error)
|
||||
self.error_sink.append(error_node)
|
||||
return error_node
|
||||
|
||||
log.debug("Recognized python code.")
|
||||
return PythonNode(text, tree)
|
||||
ret = sheerka.ret(
|
||||
self.name,
|
||||
not self.has_error,
|
||||
sheerka.new(
|
||||
BuiltinConcepts.PARSER_RESULT,
|
||||
parser=self,
|
||||
source=text,
|
||||
body=self.error_sink if self.has_error else PythonNode(text, tree),
|
||||
try_parsed=None))
|
||||
|
||||
self.log_result(log, text, ret)
|
||||
return ret
|
||||
|
||||
def try_parse_expression(self, text):
|
||||
try:
|
||||
@@ -91,6 +130,7 @@ class PythonGetNamesVisitor(ast.NodeVisitor):
|
||||
"""
|
||||
This visitor will find all the name declared in the ast
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.names = set()
|
||||
log.debug("Searching for names.")
|
||||
@@ -98,4 +138,3 @@ class PythonGetNamesVisitor(ast.NodeVisitor):
|
||||
def visit_Name(self, node):
|
||||
log.debug(f"Found name : {node.id}")
|
||||
self.names.add(node.id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user