from dataclasses import dataclass from core.tokenizer import TokenKind, Keywords from core.sheerka_logger import get_logger import logging @dataclass() class Node: pass @dataclass() class NopNode(Node): pass def __repr__(self): return "nop" class NotInitializedNode(Node): pass def __repr__(self): return "**N/A**" @dataclass() class ErrorNode(Node): pass @dataclass() class UnexpectedTokenErrorNode(ErrorNode): message: str expected_tokens: list class BaseParser: PREFIX = "parsers." def __init__(self, name): self.log = get_logger("parsers." + self.__class__.__name__) self.init_log = get_logger("init." + self.PREFIX + self.__class__.__name__) self.verbose_log = get_logger("verbose." + self.PREFIX + self.__class__.__name__) self.name = self.PREFIX + name self.has_error = False self.error_sink = [] def __eq__(self, other): if not isinstance(other, self.__class__): return False return self.name == other.name def __hash__(self): return hash(self.name) def parse(self, context, text): pass def log_result(self, context, source, ret): if not self.log.isEnabledFor(logging.DEBUG): return if ret.status: value = context.return_value_to_str(ret) context.log(self.log, f"Recognized '{source}' as {value}", self.name) else: context.log(self.log, f"Failed to recognize '{source}'", self.name) def log_multiple_results(self, context, source, list_of_ret): if not self.log.isEnabledFor(logging.DEBUG): return context.log(self.log, f"Recognized '{source}' as multiple concepts", self.name) for r in list_of_ret: value = context.return_value_to_str(r) context.log(self.log, f" Recognized '{value}'", self.name) @staticmethod def get_text_from_tokens(tokens, custom_switcher=None): if tokens is None: return "" res = "" if not hasattr(tokens, "__iter__"): tokens = [tokens] switcher = { TokenKind.KEYWORD: lambda t: Keywords(t.value).value, TokenKind.CONCEPT: lambda t: "c:" + t.value + ":", } if custom_switcher: switcher.update(custom_switcher) for token in tokens: value = switcher.get(token.type, lambda t: t.value)(token) res += value return res