Brad Bishop | bf066a6 | 2016-10-19 08:09:44 -0400 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | import sys |
| 4 | import os |
| 5 | import re |
| 6 | import argparse |
| 7 | import yaml |
| 8 | |
| 9 | valid_c_name_pattern = re.compile('[\W_]+') |
| 10 | ignore_list = ['description'] |
| 11 | all_names = [] |
| 12 | |
| 13 | |
| 14 | def get_parser(x, fmt, lmbda=lambda x: x.capitalize()): |
| 15 | try: |
| 16 | return getattr( |
| 17 | sys.modules[__name__], |
| 18 | '%s' % (fmt.format(lmbda(x)))) |
| 19 | except AttributeError: |
| 20 | raise NotImplementedError("Don't know how to parse '%s'" % x) |
| 21 | |
| 22 | |
| 23 | class RenderList(list): |
| 24 | def __init__(self, renderers): |
| 25 | self.extend(renderers) |
| 26 | |
| 27 | def __call__(self, fd): |
| 28 | for x in self: |
| 29 | x(fd) |
| 30 | |
| 31 | |
| 32 | class ParseList(list): |
| 33 | def __init__(self, parsers): |
| 34 | self.extend(parsers) |
| 35 | |
| 36 | def __call__(self): |
| 37 | return RenderList([x() for x in self]) |
| 38 | |
| 39 | |
| 40 | class MatchRender(object): |
| 41 | def __init__(self, name, signature): |
| 42 | self.name = valid_c_name_pattern.sub('_', name).lower() |
| 43 | self.signature = signature |
| 44 | |
| 45 | if self.name in all_names: |
| 46 | raise RuntimeError('The name "%s" is not unique.' % name) |
| 47 | else: |
| 48 | all_names.append(self.name) |
| 49 | |
| 50 | def __call__(self, fd): |
| 51 | sig = ['%s=\'%s\'' % (k, v) for k, v in self.signature.iteritems()] |
| 52 | sig = ['%s,' % x for x in sig[:-1]] + [sig[-1]] |
| 53 | sig = ['"%s"' % x for x in sig] |
| 54 | sig = ['%s\n' % x for x in sig[:-1]] + [sig[-1]] |
| 55 | |
| 56 | fd.write(' {\n') |
| 57 | fd.write(' "%s",\n' % self.name) |
Brad Bishop | 49aefb3 | 2016-10-19 11:54:14 -0400 | [diff] [blame^] | 58 | fd.write(' std::make_tuple(\n') |
Brad Bishop | bf066a6 | 2016-10-19 08:09:44 -0400 | [diff] [blame] | 59 | for s in sig: |
| 60 | fd.write(' %s' % s) |
Brad Bishop | 49aefb3 | 2016-10-19 11:54:14 -0400 | [diff] [blame^] | 61 | fd.write('\n') |
| 62 | fd.write(' ),\n') |
Brad Bishop | bf066a6 | 2016-10-19 08:09:44 -0400 | [diff] [blame] | 63 | fd.write(' },\n') |
| 64 | |
| 65 | |
| 66 | class MatchEventParse(object): |
| 67 | def __init__(self, match): |
| 68 | self.name = match['name'] |
| 69 | self.signature = match['signature'] |
| 70 | |
| 71 | def __call__(self): |
| 72 | return MatchRender( |
| 73 | self.name, |
| 74 | self.signature) |
| 75 | |
| 76 | |
| 77 | class EventsParse(object): |
| 78 | def __init__(self, event): |
| 79 | self.delegate = None |
| 80 | cls = event['type'] |
| 81 | if cls not in ignore_list: |
| 82 | fmt = '{0}EventParse' |
| 83 | self.delegate = get_parser(cls, fmt)(event) |
| 84 | |
| 85 | def __call__(self): |
| 86 | if self.delegate: |
| 87 | return self.delegate() |
| 88 | return lambda x: None |
| 89 | |
| 90 | |
| 91 | class DictParse(ParseList): |
| 92 | def __init__(self, data): |
| 93 | fmt = '{0}Parse' |
| 94 | parse = set(data.iterkeys()).difference(ignore_list) |
| 95 | ParseList.__init__( |
| 96 | self, [get_parser(x, fmt)(*data[x]) for x in parse]) |
| 97 | |
| 98 | |
| 99 | if __name__ == '__main__': |
| 100 | parser = argparse.ArgumentParser( |
| 101 | description='Phosphor Inventory Manager (PIM) YAML ' |
| 102 | 'scanner and code generator.') |
| 103 | parser.add_argument( |
| 104 | '-o', '--output', dest='output', |
| 105 | default='generated.hpp', help='Output file name.') |
| 106 | parser.add_argument( |
| 107 | '-d', '--dir', dest='inputdir', |
| 108 | default='examples', help='Location of files to process.') |
| 109 | |
| 110 | args = parser.parse_args() |
| 111 | |
| 112 | yaml_files = filter( |
| 113 | lambda x: x.endswith('.yaml'), |
| 114 | os.listdir(args.inputdir)) |
| 115 | |
| 116 | def get_parsers(x): |
| 117 | with open(os.path.join(args.inputdir, x), 'r') as fd: |
| 118 | return DictParse(yaml.load(fd.read())) |
| 119 | |
| 120 | head = """// This file was auto generated. Do not edit. |
| 121 | |
| 122 | #pragma once |
| 123 | |
| 124 | const Manager::Events Manager::_events{ |
| 125 | """ |
| 126 | |
| 127 | tail = """}; |
| 128 | """ |
| 129 | |
| 130 | r = ParseList([get_parsers(x) for x in yaml_files])() |
| 131 | r.insert(0, lambda x: x.write(head)) |
| 132 | r.append(lambda x: x.write(tail)) |
| 133 | |
| 134 | with open(args.output, 'w') as fd: |
| 135 | r(fd) |
| 136 | |
| 137 | # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 |