1#!/usr/bin/env python3.8 2 3"""Produce a report about the most-memoable types. 4 5Reads a list of statistics from stdin. Each line must be two numbers, 6being a type and a count. We then read some other files and produce a 7list sorted by most frequent type. 8 9There should also be something to recognize left-recursive rules. 10""" 11 12import os 13import re 14import sys 15 16from typing import Dict 17 18reporoot = os.path.dirname(os.path.dirname(__file__)) 19parse_c = os.path.join(reporoot, "peg_extension", "parse.c") 20 21 22class TypeMapper: 23 """State used to map types to names.""" 24 25 def __init__(self, filename: str) -> None: 26 self.table: Dict[int, str] = {} 27 with open(filename) as f: 28 for line in f: 29 match = re.match(r"#define (\w+)_type (\d+)", line) 30 if match: 31 name, type = match.groups() 32 if "left" in line.lower(): 33 name += " // Left-recursive" 34 self.table[int(type)] = name 35 36 def lookup(self, type: int) -> str: 37 return self.table.get(type, str(type)) 38 39 40def main() -> None: 41 mapper = TypeMapper(parse_c) 42 table = [] 43 filename = sys.argv[1] 44 with open(filename) as f: 45 for lineno, line in enumerate(f, 1): 46 line = line.strip() 47 if not line or line.startswith("#"): 48 continue 49 parts = line.split() 50 # Extra fields ignored 51 if len(parts) < 2: 52 print(f"{lineno}: bad input ({line!r})") 53 continue 54 try: 55 type, count = map(int, parts[:2]) 56 except ValueError as err: 57 print(f"{lineno}: non-integer input ({line!r})") 58 continue 59 table.append((type, count)) 60 table.sort(key=lambda values: -values[1]) 61 for type, count in table: 62 print(f"{type:4d} {count:9d} {mapper.lookup(type)}") 63 64 65if __name__ == "__main__": 66 main() 67