blob: 8350d3ad36eee3cc32d1e61de6e482fd4f8dce24 [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 Bishop3d57f502016-10-19 12:18:41 -040041 def __init__(self, name, signature, fltr):
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 Bishopbf066a62016-10-19 08:09:44 -040045
46 if self.name in all_names:
47 raise RuntimeError('The name "%s" is not unique.' % name)
48 else:
49 all_names.append(self.name)
50
51 def __call__(self, fd):
52 sig = ['%s=\'%s\'' % (k, v) for k, v in self.signature.iteritems()]
53 sig = ['%s,' % x for x in sig[:-1]] + [sig[-1]]
54 sig = ['"%s"' % x for x in sig]
55 sig = ['%s\n' % x for x in sig[:-1]] + [sig[-1]]
56
57 fd.write(' {\n')
58 fd.write(' "%s",\n' % self.name)
Brad Bishop49aefb32016-10-19 11:54:14 -040059 fd.write(' std::make_tuple(\n')
Brad Bishopbf066a62016-10-19 08:09:44 -040060 for s in sig:
61 fd.write(' %s' % s)
Brad Bishop3d57f502016-10-19 12:18:41 -040062 fd.write(',\n')
63 self.fltr(fd)
Brad Bishop49aefb32016-10-19 11:54:14 -040064 fd.write(' ),\n')
Brad Bishopbf066a62016-10-19 08:09:44 -040065 fd.write(' },\n')
66
67
Brad Bishop3d57f502016-10-19 12:18:41 -040068class FilterRender(object):
69 namespace = 'filters'
70 default = 'none'
71
72 def __init__(self, fltr):
73 self.args = None
74 if fltr is None:
75 self.name = self.default
76 else:
77 self.name = fltr.get('name')
78 self.args = fltr.get('args')
79
80 def __call__(self, fd):
81 def fmt(x):
82 if x.get('type') is None:
83 return '"%s"' % x['value']
84 return str(x['value'])
85
86 fd.write(' %s::%s' % (self.namespace, self.name))
87 if self.args:
88 fd.write('(')
89 buf = ','.join(([fmt(x) for x in self.args]))
90 fd.write(buf)
91 fd.write(')')
92
93 fd.write('\n')
94
95
Brad Bishopbf066a62016-10-19 08:09:44 -040096class MatchEventParse(object):
97 def __init__(self, match):
98 self.name = match['name']
99 self.signature = match['signature']
Brad Bishop3d57f502016-10-19 12:18:41 -0400100 self.fltr = match.get('filter')
Brad Bishopbf066a62016-10-19 08:09:44 -0400101
102 def __call__(self):
103 return MatchRender(
104 self.name,
Brad Bishop3d57f502016-10-19 12:18:41 -0400105 self.signature,
106 FilterRender(self.fltr))
Brad Bishopbf066a62016-10-19 08:09:44 -0400107
108
109class EventsParse(object):
110 def __init__(self, event):
111 self.delegate = None
112 cls = event['type']
113 if cls not in ignore_list:
114 fmt = '{0}EventParse'
115 self.delegate = get_parser(cls, fmt)(event)
116
117 def __call__(self):
118 if self.delegate:
119 return self.delegate()
120 return lambda x: None
121
122
123class DictParse(ParseList):
124 def __init__(self, data):
125 fmt = '{0}Parse'
126 parse = set(data.iterkeys()).difference(ignore_list)
127 ParseList.__init__(
128 self, [get_parser(x, fmt)(*data[x]) for x in parse])
129
130
131if __name__ == '__main__':
132 parser = argparse.ArgumentParser(
133 description='Phosphor Inventory Manager (PIM) YAML '
134 'scanner and code generator.')
135 parser.add_argument(
136 '-o', '--output', dest='output',
137 default='generated.hpp', help='Output file name.')
138 parser.add_argument(
139 '-d', '--dir', dest='inputdir',
140 default='examples', help='Location of files to process.')
141
142 args = parser.parse_args()
143
144 yaml_files = filter(
145 lambda x: x.endswith('.yaml'),
146 os.listdir(args.inputdir))
147
148 def get_parsers(x):
149 with open(os.path.join(args.inputdir, x), 'r') as fd:
150 return DictParse(yaml.load(fd.read()))
151
152 head = """// This file was auto generated. Do not edit.
153
154#pragma once
155
156const Manager::Events Manager::_events{
157"""
158
159 tail = """};
160"""
161
162 r = ParseList([get_parsers(x) for x in yaml_files])()
163 r.insert(0, lambda x: x.write(head))
164 r.append(lambda x: x.write(tail))
165
166 with open(args.output, 'w') as fd:
167 r(fd)
168
169# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4