mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 15:41:43 +00:00 
			
		
		
		
	
		
			
	
	
		
			67 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			67 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()
							 |