|
#!/usr/bin/env python3 |
|
from dataclasses import dataclass, field |
|
import sys |
|
from typing import ClassVar |
|
|
|
|
|
@dataclass |
|
class Gen: |
|
|
|
_fname: str |
|
_lines: list[str] = field(default_factory=lambda: ["!_TAG_FILE_SORTED\t1\t"]) |
|
|
|
END_CHAR_TO_TY: ClassVar = {"(": "f", ":": "v"} |
|
|
|
@staticmethod |
|
def __san(line: str): |
|
return line.replace("\\", "\\\\").replace("/", r"\/") |
|
|
|
@staticmethod |
|
def __get_sym_def(line: str, init: str, end_char: str): |
|
line = line.strip() |
|
if not line.startswith(init): |
|
return None |
|
s = line[len(init) :] |
|
return ( |
|
s[: s.index(end_char)].strip(), |
|
rf"/\V{Gen.__san(line)}/ norm ^", |
|
Gen.END_CHAR_TO_TY[end_char], |
|
) |
|
|
|
@staticmethod |
|
def __get_var_def(line: str): |
|
return Gen.__get_sym_def(line, "const ", ":") or Gen.__get_sym_def( |
|
line, "var ", ":" |
|
) |
|
|
|
@staticmethod |
|
def __get_fn_def(line: str): |
|
return Gen.__get_sym_def(line, "fn ", "(") or Gen.__get_sym_def( |
|
line, "task ", "(" |
|
) |
|
|
|
@staticmethod |
|
def __get_for_def(line: str) -> tuple[str, str, str] | None: |
|
line = line.strip() |
|
if not (line.startswith("for ") or line.startswith("for(")): |
|
return None |
|
start = line.find("|", 3) |
|
stop = line.find("|", start + 1) |
|
return line[start + 1 : stop].strip(), rf"/\V{Gen.__san(line)}/ norm ^", "v" |
|
|
|
@staticmethod |
|
def __try_line(line: str): |
|
return ( |
|
Gen.__get_var_def(line) or Gen.__get_fn_def(line) or Gen.__get_for_def(line) |
|
) |
|
|
|
def gen_tag_line(self, line: str): |
|
if not (name_addr := self.__try_line(line)): |
|
return |
|
name, addr, ty = name_addr |
|
self._lines.append(f'{name}\t{self._fname}\t{addr}\t;"\t{ty}\n') |
|
|
|
def write_out(self): |
|
with open("tags", "w") as f: |
|
f.writelines(sorted(self._lines)) |
|
|
|
|
|
def main(): |
|
fname = sys.argv[1] |
|
with open(fname, "r") as f: |
|
lines = f.readlines() |
|
|
|
gen = Gen(fname) |
|
for line in lines: |
|
gen.gen_tag_line(line) |
|
gen.write_out() |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |