1#!/usr/bin/env python3 2 3import argparse 4import re 5 6 7class Layout(object): 8 def __init__(self, layout, variant=None): 9 self.layout = layout 10 self.variant = variant 11 if '(' in layout: 12 assert variant is None 13 # parse a layout(variant) string 14 match = re.match(r'([^(]+)\(([^)]+)\)', layout) 15 self.layout = match.groups()[0] 16 self.variant = match.groups()[1] 17 18 def __str__(self): 19 if self.variant: 20 return '{}({})'.format(self.layout, self.variant) 21 else: 22 return '{}'.format(self.layout) 23 24 25def read_file(path): 26 '''Returns a list of two-layout tuples [(layout1, layout2), ...]''' 27 28 # This parses both input files, one with two elements, one with four elements, 29 # all separated by tabs 30 pattern = re.compile(r'([^\t]+)\s+([^\t]+)\s*([^\t]*)\s*([^\t]*)') 31 32 layouts = [] 33 for line in open(path): 34 match = re.match(pattern, line.strip()) 35 groups = [g for g in match.groups() if g] # drop empty groups 36 if len(groups) == 2: 37 l1 = Layout(groups[0]) 38 l2 = Layout(groups[1]) 39 else: 40 l1 = Layout(groups[0], groups[1]) 41 l2 = Layout(groups[2], groups[3]) 42 layouts.append((l1, l2)) 43 return layouts 44 45 46# ml_s 47def write_fixed_layout(dest, mappings, write_header): 48 if write_header: 49 dest.write('! model layout = symbols\n') 50 for l1, l2 in mappings: 51 dest.write(' * {} = pc+{}\n'.format(l1, l2)) 52 53 54# mln_s 55def write_layout_n(dest, mappings, number, write_header): 56 if write_header: 57 dest.write('! model layout[{}] = symbols\n'.format(number)) 58 59 # symbols is one of 60 # +layout(variant):2 ... where the map-to-layout has a proper variant 61 # +layout%(v[2]):2 ... where the map-to-layout does not have a variant 62 # and where the number is 1, we have a base and drop the suffix, i.e. 63 # the above becomes 64 # pc+layout(variant) 65 # pc+layout%(v[1]) 66 67 base = 'pc' if number == 1 else '' 68 suffix = '' if number == 1 else ':{}'.format(number) 69 70 for l1, l2 in mappings: 71 second_layout = str(l2) if l2.variant else '{}%(v[{}])'.format(l2.layout, number) 72 dest.write(' * {} = {}+{}{}\n'.format(l1, base, second_layout, suffix)) 73 74 75# mlv_s 76def write_fixed_layout_variant(dest, mappings, write_header): 77 if write_header: 78 dest.write('! model layout variant = symbols\n') 79 for l1, l2 in mappings: 80 dest.write(' * {} {} = pc+{}\n'.format(l1.layout, l1.variant, l2)) 81 82 83# mlnvn_s 84def write_layout_n_variant_n(dest, mappings, number, write_header): 85 if write_header: 86 dest.write('! model layout[{}] variant[{}] = symbols\n'.format(number, number)) 87 88 # symbols is 89 # +layout(variant):2 90 # and where the number is 1, we have a base and drop the suffix, i.e. 91 # the above becomes 92 # pc+layout(variant) 93 # This part is only executed for the variantMappings.lst 94 95 base = 'pc' if number == 1 else '' 96 suffix = '' if number == 1 else ':{}'.format(number) 97 98 for l1, l2 in mappings: 99 second_layout = str(l2) if l2.variant else '{}%(v[{}])'.format(l2.layout, number) 100 dest.write(' * {} {} = {}+{}{}\n'.format(l1.layout, l1.variant, base, second_layout, suffix)) 101 102 103def map_variant(dest, files, want='mls', number=None): 104 for idx, f in enumerate(files): 105 write_header = idx == 0 106 107 mappings = read_file(f) 108 if want == 'mls': 109 if number is None: 110 write_fixed_layout(dest, mappings, write_header) 111 else: 112 write_layout_n(dest, mappings, number, write_header) 113 elif want == 'mlvs': 114 if number is None: 115 write_fixed_layout_variant(dest, mappings, write_header) 116 else: 117 write_layout_n_variant_n(dest, mappings, number, write_header) 118 else: 119 raise NotImplementedError() 120 121 122if __name__ == '__main__': 123 parser = argparse.ArgumentParser('variant mapping script') 124 parser.add_argument('--want', type=str, 125 choices=['mls', 'mlvs']) 126 parser.add_argument('--number', type=int, default=None) 127 128 parser.add_argument('dest', type=str) 129 parser.add_argument('files', nargs='+', type=str) 130 ns = parser.parse_args() 131 132 with open(ns.dest, 'w') as fd: 133 map_variant(fd, ns.files, ns.want, ns.number) 134