(root)/
Python-3.11.7/
Tools/
c-analyzer/
table-file.py
       1  
       2  def iter_clean_lines(lines):
       3      lines = iter(lines)
       4      for line in lines:
       5          line = line.strip()
       6          if line.startswith('# XXX'):
       7              continue
       8          yield line
       9  
      10  
      11  def parse_table_lines(lines):
      12      lines = iter_clean_lines(lines)
      13  
      14      for line in lines:
      15          if line.startswith(('####', '#----')):
      16              kind = 0 if line[1] == '#' else 1
      17              try:
      18                  line = next(lines).strip()
      19              except StopIteration:
      20                  line = ''
      21              if not line.startswith('# '):
      22                  raise NotImplementedError(line)
      23              yield kind, line[2:].lstrip()
      24              continue
      25  
      26          maybe = None
      27          while line.startswith('#'):
      28              if line != '#' and line[1] == ' ':
      29                  maybe = line[2:].lstrip()
      30              try:
      31                  line = next(lines).strip()
      32              except StopIteration:
      33                  return
      34              if not line:
      35                  break
      36          else:
      37              if line:
      38                  if maybe:
      39                      yield 2, maybe
      40                  yield 'row', line
      41  
      42  
      43  def iter_sections(lines):
      44      header = None
      45      section = []
      46      for kind, value in parse_table_lines(lines):
      47          if kind == 'row':
      48              if not section:
      49                  if header is None:
      50                      header = value
      51                      continue
      52                  raise NotImplementedError(value)
      53              yield tuple(section), value
      54          else:
      55              if header is None:
      56                  header = False
      57              section[kind:] = [value]
      58  
      59  
      60  def collect_sections(lines):
      61      sections = {}
      62      for section, row in iter_sections(lines):
      63          if section not in sections:
      64              sections[section] = [row]
      65          else:
      66              sections[section].append(row)
      67      return sections
      68  
      69  
      70  def collate_sections(lines):
      71      collated = {}
      72      for section, rows in collect_sections(lines).items():
      73          parent = collated
      74          current = ()
      75          for name in section:
      76              current += (name,)
      77              try:
      78                  child, secrows, totalrows = parent[name]
      79              except KeyError:
      80                  child = {}
      81                  secrows = []
      82                  totalrows = []
      83                  parent[name] = (child, secrows, totalrows)
      84              parent = child
      85              if current == section:
      86                  secrows.extend(rows)
      87              totalrows.extend(rows)
      88      return collated
      89  
      90  
      91  #############################
      92  # the commands
      93  
      94  def cmd_count_by_section(lines):
      95      div = ' ' + '-' * 50
      96      total = 0
      97      def render_tree(root, depth=0):
      98          nonlocal total
      99          indent = '    ' * depth
     100          for name, data in root.items():
     101              subroot, rows, totalrows = data
     102              sectotal = f'({len(totalrows)})' if totalrows != rows else ''
     103              count = len(rows) if rows else ''
     104              if depth == 0:
     105                  yield div
     106              yield f'{sectotal:>7} {count:>4}  {indent}{name}'
     107              yield from render_tree(subroot, depth+1)
     108              total += len(rows)
     109      sections = collate_sections(lines)
     110      yield from render_tree(sections)
     111      yield div
     112      yield f'(total: {total})'
     113  
     114  
     115  #############################
     116  # the script
     117  
     118  def parse_args(argv=None, prog=None):
     119      import argparse
     120      parser = argparse.ArgumentParser(prog=prog)
     121      parser.add_argument('filename')
     122  
     123      args = parser.parse_args(argv)
     124      ns = vars(args)
     125  
     126      return ns
     127  
     128  
     129  def main(filename):
     130      with open(filename) as infile:
     131          for line in cmd_count_by_section(infile):
     132              print(line)
     133  
     134  
     135  if __name__ == '__main__':
     136      kwargs = parse_args()
     137      main(**kwargs)