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): |
Brad Bishop | c038e01 | 2016-10-19 13:02:24 -0400 | [diff] [blame] | 41 | def __init__(self, name, signature, fltr, action): |
Brad Bishop | bf066a6 | 2016-10-19 08:09:44 -0400 | [diff] [blame] | 42 | self.name = valid_c_name_pattern.sub('_', name).lower() |
| 43 | self.signature = signature |
Brad Bishop | 3d57f50 | 2016-10-19 12:18:41 -0400 | [diff] [blame] | 44 | self.fltr = fltr |
Brad Bishop | c038e01 | 2016-10-19 13:02:24 -0400 | [diff] [blame] | 45 | self.action = action |
Brad Bishop | bf066a6 | 2016-10-19 08:09:44 -0400 | [diff] [blame] | 46 | |
| 47 | if self.name in all_names: |
| 48 | raise RuntimeError('The name "%s" is not unique.' % name) |
| 49 | else: |
| 50 | all_names.append(self.name) |
| 51 | |
| 52 | def __call__(self, fd): |
| 53 | sig = ['%s=\'%s\'' % (k, v) for k, v in self.signature.iteritems()] |
| 54 | sig = ['%s,' % x for x in sig[:-1]] + [sig[-1]] |
| 55 | sig = ['"%s"' % x for x in sig] |
| 56 | sig = ['%s\n' % x for x in sig[:-1]] + [sig[-1]] |
| 57 | |
| 58 | fd.write(' {\n') |
| 59 | fd.write(' "%s",\n' % self.name) |
Brad Bishop | 49aefb3 | 2016-10-19 11:54:14 -0400 | [diff] [blame] | 60 | fd.write(' std::make_tuple(\n') |
Brad Bishop | bf066a6 | 2016-10-19 08:09:44 -0400 | [diff] [blame] | 61 | for s in sig: |
| 62 | fd.write(' %s' % s) |
Brad Bishop | 3d57f50 | 2016-10-19 12:18:41 -0400 | [diff] [blame] | 63 | fd.write(',\n') |
| 64 | self.fltr(fd) |
Brad Bishop | c038e01 | 2016-10-19 13:02:24 -0400 | [diff] [blame] | 65 | fd.write(',\n') |
| 66 | self.action(fd) |
| 67 | fd.write('\n') |
Brad Bishop | 49aefb3 | 2016-10-19 11:54:14 -0400 | [diff] [blame] | 68 | fd.write(' ),\n') |
Brad Bishop | bf066a6 | 2016-10-19 08:09:44 -0400 | [diff] [blame] | 69 | fd.write(' },\n') |
| 70 | |
| 71 | |
Brad Bishop | 3d57f50 | 2016-10-19 12:18:41 -0400 | [diff] [blame] | 72 | class FilterRender(object): |
| 73 | namespace = 'filters' |
| 74 | default = 'none' |
| 75 | |
| 76 | def __init__(self, fltr): |
| 77 | self.args = None |
| 78 | if fltr is None: |
| 79 | self.name = self.default |
| 80 | else: |
Brad Bishop | afbd28e | 2016-10-21 22:37:17 -0400 | [diff] [blame] | 81 | self.name = fltr.get('type') |
Brad Bishop | 3d57f50 | 2016-10-19 12:18:41 -0400 | [diff] [blame] | 82 | self.args = fltr.get('args') |
| 83 | |
| 84 | def __call__(self, fd): |
| 85 | def fmt(x): |
| 86 | if x.get('type') is None: |
| 87 | return '"%s"' % x['value'] |
| 88 | return str(x['value']) |
| 89 | |
| 90 | fd.write(' %s::%s' % (self.namespace, self.name)) |
| 91 | if self.args: |
| 92 | fd.write('(') |
| 93 | buf = ','.join(([fmt(x) for x in self.args])) |
| 94 | fd.write(buf) |
| 95 | fd.write(')') |
| 96 | |
Brad Bishop | c038e01 | 2016-10-19 13:02:24 -0400 | [diff] [blame] | 97 | |
| 98 | class ActionRender(FilterRender): |
| 99 | namespace = 'actions' |
| 100 | default = 'noop' |
| 101 | |
| 102 | def __init__(self, action): |
| 103 | FilterRender.__init__(self, action) |
Brad Bishop | 3d57f50 | 2016-10-19 12:18:41 -0400 | [diff] [blame] | 104 | |
| 105 | |
Brad Bishop | bf066a6 | 2016-10-19 08:09:44 -0400 | [diff] [blame] | 106 | class MatchEventParse(object): |
| 107 | def __init__(self, match): |
| 108 | self.name = match['name'] |
| 109 | self.signature = match['signature'] |
Brad Bishop | 3d57f50 | 2016-10-19 12:18:41 -0400 | [diff] [blame] | 110 | self.fltr = match.get('filter') |
Brad Bishop | c038e01 | 2016-10-19 13:02:24 -0400 | [diff] [blame] | 111 | self.action = match.get('action') |
Brad Bishop | bf066a6 | 2016-10-19 08:09:44 -0400 | [diff] [blame] | 112 | |
| 113 | def __call__(self): |
| 114 | return MatchRender( |
| 115 | self.name, |
Brad Bishop | 3d57f50 | 2016-10-19 12:18:41 -0400 | [diff] [blame] | 116 | self.signature, |
Brad Bishop | c038e01 | 2016-10-19 13:02:24 -0400 | [diff] [blame] | 117 | FilterRender(self.fltr), |
| 118 | ActionRender(self.action)) |
Brad Bishop | bf066a6 | 2016-10-19 08:09:44 -0400 | [diff] [blame] | 119 | |
| 120 | |
| 121 | class EventsParse(object): |
| 122 | def __init__(self, event): |
| 123 | self.delegate = None |
| 124 | cls = event['type'] |
| 125 | if cls not in ignore_list: |
| 126 | fmt = '{0}EventParse' |
| 127 | self.delegate = get_parser(cls, fmt)(event) |
| 128 | |
| 129 | def __call__(self): |
| 130 | if self.delegate: |
| 131 | return self.delegate() |
| 132 | return lambda x: None |
| 133 | |
| 134 | |
| 135 | class DictParse(ParseList): |
| 136 | def __init__(self, data): |
| 137 | fmt = '{0}Parse' |
| 138 | parse = set(data.iterkeys()).difference(ignore_list) |
| 139 | ParseList.__init__( |
| 140 | self, [get_parser(x, fmt)(*data[x]) for x in parse]) |
| 141 | |
| 142 | |
| 143 | if __name__ == '__main__': |
| 144 | parser = argparse.ArgumentParser( |
| 145 | description='Phosphor Inventory Manager (PIM) YAML ' |
| 146 | 'scanner and code generator.') |
| 147 | parser.add_argument( |
| 148 | '-o', '--output', dest='output', |
| 149 | default='generated.hpp', help='Output file name.') |
| 150 | parser.add_argument( |
| 151 | '-d', '--dir', dest='inputdir', |
Brad Bishop | 09fc256 | 2016-10-21 22:58:08 -0400 | [diff] [blame^] | 152 | default=os.path.join('example', 'events'), |
| 153 | help='Location of files to process.') |
Brad Bishop | bf066a6 | 2016-10-19 08:09:44 -0400 | [diff] [blame] | 154 | |
| 155 | args = parser.parse_args() |
| 156 | |
| 157 | yaml_files = filter( |
| 158 | lambda x: x.endswith('.yaml'), |
| 159 | os.listdir(args.inputdir)) |
| 160 | |
| 161 | def get_parsers(x): |
| 162 | with open(os.path.join(args.inputdir, x), 'r') as fd: |
| 163 | return DictParse(yaml.load(fd.read())) |
| 164 | |
| 165 | head = """// This file was auto generated. Do not edit. |
| 166 | |
| 167 | #pragma once |
| 168 | |
| 169 | const Manager::Events Manager::_events{ |
| 170 | """ |
| 171 | |
| 172 | tail = """}; |
| 173 | """ |
| 174 | |
| 175 | r = ParseList([get_parsers(x) for x in yaml_files])() |
| 176 | r.insert(0, lambda x: x.write(head)) |
| 177 | r.append(lambda x: x.write(tail)) |
| 178 | |
| 179 | with open(args.output, 'w') as fd: |
| 180 | r(fd) |
| 181 | |
| 182 | # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 |