blob: 301e7d947e8cbdc8438b80100161c6a31160c317 [file] [log] [blame]
Brad Bishopbf066a62016-10-19 08:09:44 -04001#!/usr/bin/env python
2
3import sys
4import os
5import re
6import argparse
7import yaml
8
9valid_c_name_pattern = re.compile('[\W_]+')
10ignore_list = ['description']
11all_names = []
12
13
14def 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
23class 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
32class 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
40class MatchRender(object):
Brad Bishopc038e012016-10-19 13:02:24 -040041 def __init__(self, name, signature, fltr, action):
Brad Bishopbf066a62016-10-19 08:09:44 -040042 self.name = valid_c_name_pattern.sub('_', name).lower()
43 self.signature = signature
Brad Bishop3d57f502016-10-19 12:18:41 -040044 self.fltr = fltr
Brad Bishopc038e012016-10-19 13:02:24 -040045 self.action = action
Brad Bishopbf066a62016-10-19 08:09:44 -040046
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 Bishop49aefb32016-10-19 11:54:14 -040060 fd.write(' std::make_tuple(\n')
Brad Bishopbf066a62016-10-19 08:09:44 -040061 for s in sig:
62 fd.write(' %s' % s)
Brad Bishop3d57f502016-10-19 12:18:41 -040063 fd.write(',\n')
64 self.fltr(fd)
Brad Bishopc038e012016-10-19 13:02:24 -040065 fd.write(',\n')
66 self.action(fd)
67 fd.write('\n')
Brad Bishop49aefb32016-10-19 11:54:14 -040068 fd.write(' ),\n')
Brad Bishopbf066a62016-10-19 08:09:44 -040069 fd.write(' },\n')
70
71
Brad Bishop3d57f502016-10-19 12:18:41 -040072class 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 Bishopafbd28e2016-10-21 22:37:17 -040081 self.name = fltr.get('type')
Brad Bishop3d57f502016-10-19 12:18:41 -040082 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 Bishopc038e012016-10-19 13:02:24 -040097
98class ActionRender(FilterRender):
99 namespace = 'actions'
100 default = 'noop'
101
102 def __init__(self, action):
103 FilterRender.__init__(self, action)
Brad Bishop3d57f502016-10-19 12:18:41 -0400104
105
Brad Bishopbf066a62016-10-19 08:09:44 -0400106class MatchEventParse(object):
107 def __init__(self, match):
108 self.name = match['name']
109 self.signature = match['signature']
Brad Bishop3d57f502016-10-19 12:18:41 -0400110 self.fltr = match.get('filter')
Brad Bishopc038e012016-10-19 13:02:24 -0400111 self.action = match.get('action')
Brad Bishopbf066a62016-10-19 08:09:44 -0400112
113 def __call__(self):
114 return MatchRender(
115 self.name,
Brad Bishop3d57f502016-10-19 12:18:41 -0400116 self.signature,
Brad Bishopc038e012016-10-19 13:02:24 -0400117 FilterRender(self.fltr),
118 ActionRender(self.action))
Brad Bishopbf066a62016-10-19 08:09:44 -0400119
120
121class 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
135class 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
143if __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 Bishop09fc2562016-10-21 22:58:08 -0400152 default=os.path.join('example', 'events'),
153 help='Location of files to process.')
Brad Bishopbf066a62016-10-19 08:09:44 -0400154
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
169const 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