Exemplo n.º 1
0
class TigrParser(AbstractParser):
    def __init__(self, drawer, exception_handler):
        super().__init__(drawer)
        self.regex_pattern = r'(^[a-zA-Z]\b)\s+?(-?\b\d+\.?\d?\b)?\s*?([#|//].*)?$'
        self.__output_log = []
        self.exception_handler = exception_handler
        try:
            self.command_builder = CommandBuilder()
        except Exception as e:
            self.exception_handler.display_and_exit(e)

    @property
    def output_log(self):
        # readonly
        return self.__output_log

    def parse(self, raw_source):
        if type(
                raw_source
        ) == str:  # defensively handles edge case where a single command was passed as a string
            raw_source = [raw_source]

        for line_number in range(0, len(raw_source) - 1):
            current_line = self.__prepare_line(raw_source[line_number])
            if self.__is_line_blank(current_line):
                continue

            try:
                command, data = self.__parse_line(current_line)

                prepared_command = self.command_builder.prepare_command(
                    command, data)

                output = prepared_command.execute(self.drawer)
                self._log_drawer_output(output)
            except Exception as e:
                self.exception_handler.display_and_exit(
                    e, line_number=line_number, line=current_line)

    def __prepare_line(self, line):
        return line.strip()

    def __is_line_blank(self, line):
        return not line

    def __parse_line(self, line):
        match = re.findall(self.regex_pattern, line)
        if match:
            groups = match[0]
            command = groups[0].upper()
            if groups[1]:
                data = int(round(float(groups[1])))
                """ Parser accepts decimals but silently rounds them in the background - all numbers passed are
                stored as integers"""
            else:
                data = None

            return command, data
        else:
            raise SyntaxError(f"Invalid Syntax")

    def _log_drawer_output(self, output):
        self.__output_log.append(output)