mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 11:49:12 +00:00 
			
		
		
		
	Co-authored-by: Guido van Rossum <guido@python.org> Co-authored-by: Lysandros Nikolaou <lisandrosnik@gmail.com>
		
			
				
	
	
		
			66 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			66 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#!/usr/bin/env python3.8
 | 
						|
 | 
						|
"""Produce a report about the most-memoable types.
 | 
						|
 | 
						|
Reads a list of statistics from stdin.  Each line must be two numbers,
 | 
						|
being a type and a count.  We then read some other files and produce a
 | 
						|
list sorted by most frequent type.
 | 
						|
 | 
						|
There should also be something to recognize left-recursive rules.
 | 
						|
"""
 | 
						|
 | 
						|
import os
 | 
						|
import re
 | 
						|
import sys
 | 
						|
 | 
						|
from typing import Dict
 | 
						|
 | 
						|
reporoot = os.path.dirname(os.path.dirname(__file__))
 | 
						|
parse_c = os.path.join(reporoot, "peg_extension", "parse.c")
 | 
						|
 | 
						|
 | 
						|
class TypeMapper:
 | 
						|
    """State used to map types to names."""
 | 
						|
 | 
						|
    def __init__(self, filename: str) -> None:
 | 
						|
        self.table: Dict[int, str] = {}
 | 
						|
        with open(filename) as f:
 | 
						|
            for line in f:
 | 
						|
                match = re.match(r"#define (\w+)_type (\d+)", line)
 | 
						|
                if match:
 | 
						|
                    name, type = match.groups()
 | 
						|
                    if "left" in line.lower():
 | 
						|
                        name += " // Left-recursive"
 | 
						|
                    self.table[int(type)] = name
 | 
						|
 | 
						|
    def lookup(self, type: int) -> str:
 | 
						|
        return self.table.get(type, str(type))
 | 
						|
 | 
						|
 | 
						|
def main() -> None:
 | 
						|
    mapper = TypeMapper(parse_c)
 | 
						|
    table = []
 | 
						|
    filename = sys.argv[1]
 | 
						|
    with open(filename) as f:
 | 
						|
        for lineno, line in enumerate(f, 1):
 | 
						|
            line = line.strip()
 | 
						|
            if not line or line.startswith("#"):
 | 
						|
                continue
 | 
						|
            parts = line.split()
 | 
						|
            # Extra fields ignored
 | 
						|
            if len(parts) < 2:
 | 
						|
                print(f"{lineno}: bad input ({line!r})")
 | 
						|
                continue
 | 
						|
            try:
 | 
						|
                type, count = map(int, parts[:2])
 | 
						|
            except ValueError as err:
 | 
						|
                print(f"{lineno}: non-integer input ({line!r})")
 | 
						|
                continue
 | 
						|
            table.append((type, count))
 | 
						|
    table.sort(key=lambda values: -values[1])
 | 
						|
    for type, count in table:
 | 
						|
        print(f"{type:4d} {count:9d} {mapper.lookup(type)}")
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    main()
 |