From: Lucie Scarlet Date: Sun, 8 Sep 2024 15:44:40 +0000 (+0200) Subject: Compilation almost works X-Git-Url: https://git.chaotic.ninja/gitweb/lucie/?a=commitdiff_plain;h=refs%2Fheads%2Fmaster;p=remilia.git Compilation almost works Issue fixed: `!include`ing more than once on one line works really nice. Issue introduced: `!include`ing more than once in a file over several lines throws an error. ...I truly have made a masterpiece --- diff --git a/consts.py b/consts.py index c85e46b..f4195a6 100644 --- a/consts.py +++ b/consts.py @@ -2,3 +2,4 @@ KW_IMPORT = "!include" SIZEOF = len(KW_IMPORT) + 2 FILE_EXT = ".rem" HTML_EXT = ".html" +FLAG_DEBUG = True diff --git a/importer.py b/importer.py index f07efbe..715581a 100644 --- a/importer.py +++ b/importer.py @@ -2,6 +2,9 @@ from typing import Self, Optional from io import TextIOWrapper from exceptions import * from consts import * +import logging + +logger: logging.Logger = logging.getLogger(__name__) class Remilia: @@ -11,10 +14,14 @@ class Remilia: def parse_file(self: Self) -> bool: done: bool = False - with open(self.src) as src: - imports: dict[int, list[int]] = {} - import_paths: dict[int, list[str]] = {} - for i, line in enumerate(src.readlines(), 1): + cont: bool = False + with open(self.src) as srccnt: + src: list[str] = srccnt.readlines() + logger.debug(f"{src = }") + imports: dict[int, list[int]] = {} + import_paths: dict[int, list[str]] = {} + while True: + for i, line in enumerate(src, 1): if KW_IMPORT in line: inter: list[int] = [] inter.append(line.index(KW_IMPORT)) @@ -32,26 +39,40 @@ class Remilia: try: asz: int = loc + SIZEOF end: int = line.index('"', asz + 1) - print(f"{end = }") + logger.debug(f"{end = }") new_path: str = line[asz:end] - print(f"{new_path = }") + logger.debug(f"{new_path = }") paths.append(new_path) except ValueError: raise UnterminatedQuoteException( f"Could not find another quote at line {i}" ) import_paths[i] = paths + logger.debug(f"{imports = }") + logger.debug(f"{import_paths = }") if len(imports) == 0: done = True - if not done: - self.__read_and_replace(imports, import_paths) - return done + logger.debug(f"{done = }") + logger.debug(f"{len(imports) = }") + logger.debug(f"{imports.keys() = }") + for i in list(imports.keys()): + logger.debug(f"{i = }") + if not done: + self.__read_and_replace(imports, import_paths) + cont = True + imports.pop(i) + import_paths.pop(i) + if cont: + logger.debug(f"if cont: {imports = }") + logger.debug(f"if cont: {import_paths = }") + cont = False + if len(imports) == 0 and len(import_paths) == 0: + return True + continue + if done: + return True - def printall(self): - self.parse_file() - - # TODO: make this private - def import_file(self: Self, path: str) -> None: + def __import_file(self: Self, path: str) -> None: if path in self.__seen_files: raise CircularImportException( f"Circular import! I've already seen file {path}!" @@ -61,31 +82,48 @@ class Remilia: def __read_and_replace( self: Self, imports: dict[int, list[int]], import_paths: dict[int, list[str]] ) -> None: - with open(self.src.replace(FILE_EXT, HTML_EXT), "rw") as src: - final_str: str = "" + final_str: str = "" + logger.debug(f"{self.__seen_files = }") + with open(self.src, "r") as src: for i, line in enumerate(src.readlines(), 1): + tmp: str = line if i in imports.keys(): + delta: int = 0 for n, __import in enumerate(imports[i]): + logger.debug("=" * 20) + logger.debug(f"{__import = }") + logger.debug(f"{delta = }") + logger.debug(f"{tmp[__import] = }") + logger.debug(f"{tmp[__import - delta] = }") + logger.debug(f"{tmp = }") + logger.debug(f"{line = }") + fc: str = self.__get_file_contents(import_paths[i][n]) + lenfc: int = len(fc) repl_str = ( - line[:__import] - + self.__get_file_contents(import_paths[i][n]) - + line[__import + len(import_paths[i][n]) + 1] + tmp[: __import - delta] + + fc + + tmp[ + (__import - delta) + + SIZEOF + + len(import_paths[i][n]) + + 2 : + ] ) - pass + logger.debug(f"{repl_str = }") + tmp = repl_str + if n < len(imports[i]) - 1: + delta = lenfc - imports[i][n + 1] + 2 + if n == len(imports[i]) - 1: + final_str += repl_str + logger.debug("=" * 20) + if i not in imports.keys(): + final_str += line + logger.debug(f"{final_str = }") + with open(self.src.replace(FILE_EXT, HTML_EXT), "w") as f: + f.write(final_str) def __get_file_contents(self: Self, file: str) -> str: - self.import_file(file) + logger.debug(f"{file = }") + self.__import_file(file) with open(file) as f: - return f.read() - - -def replace_at_location(original_string, start_index, length, replacement_string): - # Calculate the end index of the string to be replaced - end_index = start_index + length - - # Create the new string by slicing and concatenating - new_string = ( - original_string[:start_index] + replacement_string + original_string[end_index:] - ) - - return new_string + return "".join(f.readlines()) diff --git a/remilia b/remilia index bf3c03b..d4c55cb 100644 --- a/remilia +++ b/remilia @@ -1,23 +1,30 @@ #!/usr/bin/env python3 from importer import Remilia +from consts import FLAG_DEBUG +import logging import sys -def mmain() -> int: +logger: logging.Logger = logging.getLogger(__name__) + +def main() -> int: if len(sys.argv) < 2: print(f"Usage: {sys.argv[0]} ") return -1 compiler: Remilia = Remilia(sys.argv[1]) - while True: - done: bool = compiler.parse_file() - if done: break + compiler.parse_file() + + print(f"Compiled {sys.argv[1]}") return 0 -def main() -> int: - test: Remilia = Remilia("./test.txt") - test.import_file("./test2.txt") - test.printall() +def debugmain() -> int: + compiler: Remilia = Remilia("./test1.rem") + compiler.parse_file() + print(f"Compiled ./test1.rem") return 0 if __name__ == '__main__': - raise SystemExit(main()) + logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, format="%(levelname)-8s [%(filename)s:%(lineno)d] %(message)s") + if FLAG_DEBUG: fn = debugmain + else: fn = main + raise SystemExit(fn())