]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Tools/compiler/astgen.py
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Tools / compiler / astgen.py
CommitLineData
4710c53d 1"""Generate ast module from specification\r
2\r
3This script generates the ast module from a simple specification,\r
4which makes it easy to accomodate changes in the grammar. This\r
5approach would be quite reasonable if the grammar changed often.\r
6Instead, it is rather complex to generate the appropriate code. And\r
7the Node interface has changed more often than the grammar.\r
8"""\r
9\r
10import fileinput\r
11import re\r
12import sys\r
13from StringIO import StringIO\r
14\r
15SPEC = "ast.txt"\r
16COMMA = ", "\r
17\r
18def load_boilerplate(file):\r
19 f = open(file)\r
20 buf = f.read()\r
21 f.close()\r
22 i = buf.find('### ''PROLOGUE')\r
23 j = buf.find('### ''EPILOGUE')\r
24 pro = buf[i+12:j].strip()\r
25 epi = buf[j+12:].strip()\r
26 return pro, epi\r
27\r
28def strip_default(arg):\r
29 """Return the argname from an 'arg = default' string"""\r
30 i = arg.find('=')\r
31 if i == -1:\r
32 return arg\r
33 t = arg[:i].strip()\r
34 return t\r
35\r
36P_NODE = 1\r
37P_OTHER = 2\r
38P_NESTED = 3\r
39P_NONE = 4\r
40\r
41class NodeInfo:\r
42 """Each instance describes a specific AST node"""\r
43 def __init__(self, name, args):\r
44 self.name = name\r
45 self.args = args.strip()\r
46 self.argnames = self.get_argnames()\r
47 self.argprops = self.get_argprops()\r
48 self.nargs = len(self.argnames)\r
49 self.init = []\r
50\r
51 def get_argnames(self):\r
52 if '(' in self.args:\r
53 i = self.args.find('(')\r
54 j = self.args.rfind(')')\r
55 args = self.args[i+1:j]\r
56 else:\r
57 args = self.args\r
58 return [strip_default(arg.strip())\r
59 for arg in args.split(',') if arg]\r
60\r
61 def get_argprops(self):\r
62 """Each argument can have a property like '*' or '!'\r
63\r
64 XXX This method modifies the argnames in place!\r
65 """\r
66 d = {}\r
67 hardest_arg = P_NODE\r
68 for i in range(len(self.argnames)):\r
69 arg = self.argnames[i]\r
70 if arg.endswith('*'):\r
71 arg = self.argnames[i] = arg[:-1]\r
72 d[arg] = P_OTHER\r
73 hardest_arg = max(hardest_arg, P_OTHER)\r
74 elif arg.endswith('!'):\r
75 arg = self.argnames[i] = arg[:-1]\r
76 d[arg] = P_NESTED\r
77 hardest_arg = max(hardest_arg, P_NESTED)\r
78 elif arg.endswith('&'):\r
79 arg = self.argnames[i] = arg[:-1]\r
80 d[arg] = P_NONE\r
81 hardest_arg = max(hardest_arg, P_NONE)\r
82 else:\r
83 d[arg] = P_NODE\r
84 self.hardest_arg = hardest_arg\r
85\r
86 if hardest_arg > P_NODE:\r
87 self.args = self.args.replace('*', '')\r
88 self.args = self.args.replace('!', '')\r
89 self.args = self.args.replace('&', '')\r
90\r
91 return d\r
92\r
93 def gen_source(self):\r
94 buf = StringIO()\r
95 print >> buf, "class %s(Node):" % self.name\r
96 self._gen_init(buf)\r
97 print >> buf\r
98 self._gen_getChildren(buf)\r
99 print >> buf\r
100 self._gen_getChildNodes(buf)\r
101 print >> buf\r
102 self._gen_repr(buf)\r
103 buf.seek(0, 0)\r
104 return buf.read()\r
105\r
106 def _gen_init(self, buf):\r
107 if self.args:\r
108 argtuple = '(' in self.args\r
109 args = self.args if not argtuple else ''.join(self.argnames)\r
110 print >> buf, " def __init__(self, %s, lineno=None):" % args\r
111 else:\r
112 print >> buf, " def __init__(self, lineno=None):"\r
113 if self.argnames:\r
114 if argtuple:\r
115 for idx, name in enumerate(self.argnames):\r
116 print >> buf, " self.%s = %s[%s]" % (name, args, idx)\r
117 else:\r
118 for name in self.argnames:\r
119 print >> buf, " self.%s = %s" % (name, name)\r
120 print >> buf, " self.lineno = lineno"\r
121 # Copy the lines in self.init, indented four spaces. The rstrip()\r
122 # business is to get rid of the four spaces if line happens to be\r
123 # empty, so that reindent.py is happy with the output.\r
124 for line in self.init:\r
125 print >> buf, (" " + line).rstrip()\r
126\r
127 def _gen_getChildren(self, buf):\r
128 print >> buf, " def getChildren(self):"\r
129 if len(self.argnames) == 0:\r
130 print >> buf, " return ()"\r
131 else:\r
132 if self.hardest_arg < P_NESTED:\r
133 clist = COMMA.join(["self.%s" % c\r
134 for c in self.argnames])\r
135 if self.nargs == 1:\r
136 print >> buf, " return %s," % clist\r
137 else:\r
138 print >> buf, " return %s" % clist\r
139 else:\r
140 if len(self.argnames) == 1:\r
141 print >> buf, " return tuple(flatten(self.%s))" % self.argnames[0]\r
142 else:\r
143 print >> buf, " children = []"\r
144 template = " children.%s(%sself.%s%s)"\r
145 for name in self.argnames:\r
146 if self.argprops[name] == P_NESTED:\r
147 print >> buf, template % ("extend", "flatten(",\r
148 name, ")")\r
149 else:\r
150 print >> buf, template % ("append", "", name, "")\r
151 print >> buf, " return tuple(children)"\r
152\r
153 def _gen_getChildNodes(self, buf):\r
154 print >> buf, " def getChildNodes(self):"\r
155 if len(self.argnames) == 0:\r
156 print >> buf, " return ()"\r
157 else:\r
158 if self.hardest_arg < P_NESTED:\r
159 clist = ["self.%s" % c\r
160 for c in self.argnames\r
161 if self.argprops[c] == P_NODE]\r
162 if len(clist) == 0:\r
163 print >> buf, " return ()"\r
164 elif len(clist) == 1:\r
165 print >> buf, " return %s," % clist[0]\r
166 else:\r
167 print >> buf, " return %s" % COMMA.join(clist)\r
168 else:\r
169 print >> buf, " nodelist = []"\r
170 template = " nodelist.%s(%sself.%s%s)"\r
171 for name in self.argnames:\r
172 if self.argprops[name] == P_NONE:\r
173 tmp = (" if self.%s is not None:\n"\r
174 " nodelist.append(self.%s)")\r
175 print >> buf, tmp % (name, name)\r
176 elif self.argprops[name] == P_NESTED:\r
177 print >> buf, template % ("extend", "flatten_nodes(",\r
178 name, ")")\r
179 elif self.argprops[name] == P_NODE:\r
180 print >> buf, template % ("append", "", name, "")\r
181 print >> buf, " return tuple(nodelist)"\r
182\r
183 def _gen_repr(self, buf):\r
184 print >> buf, " def __repr__(self):"\r
185 if self.argnames:\r
186 fmt = COMMA.join(["%s"] * self.nargs)\r
187 if '(' in self.args:\r
188 fmt = '(%s)' % fmt\r
189 vals = ["repr(self.%s)" % name for name in self.argnames]\r
190 vals = COMMA.join(vals)\r
191 if self.nargs == 1:\r
192 vals = vals + ","\r
193 print >> buf, ' return "%s(%s)" %% (%s)' % \\r
194 (self.name, fmt, vals)\r
195 else:\r
196 print >> buf, ' return "%s()"' % self.name\r
197\r
198rx_init = re.compile('init\((.*)\):')\r
199\r
200def parse_spec(file):\r
201 classes = {}\r
202 cur = None\r
203 for line in fileinput.input(file):\r
204 if line.strip().startswith('#'):\r
205 continue\r
206 mo = rx_init.search(line)\r
207 if mo is None:\r
208 if cur is None:\r
209 # a normal entry\r
210 try:\r
211 name, args = line.split(':')\r
212 except ValueError:\r
213 continue\r
214 classes[name] = NodeInfo(name, args)\r
215 cur = None\r
216 else:\r
217 # some code for the __init__ method\r
218 cur.init.append(line)\r
219 else:\r
220 # some extra code for a Node's __init__ method\r
221 name = mo.group(1)\r
222 cur = classes[name]\r
223 return sorted(classes.values(), key=lambda n: n.name)\r
224\r
225def main():\r
226 prologue, epilogue = load_boilerplate(sys.argv[-1])\r
227 print prologue\r
228 print\r
229 classes = parse_spec(SPEC)\r
230 for info in classes:\r
231 print info.gen_source()\r
232 print epilogue\r
233\r
234if __name__ == "__main__":\r
235 main()\r
236 sys.exit(0)\r
237\r
238### PROLOGUE\r
239"""Python abstract syntax node definitions\r
240\r
241This file is automatically generated by Tools/compiler/astgen.py\r
242"""\r
243from consts import CO_VARARGS, CO_VARKEYWORDS\r
244\r
245def flatten(seq):\r
246 l = []\r
247 for elt in seq:\r
248 t = type(elt)\r
249 if t is tuple or t is list:\r
250 for elt2 in flatten(elt):\r
251 l.append(elt2)\r
252 else:\r
253 l.append(elt)\r
254 return l\r
255\r
256def flatten_nodes(seq):\r
257 return [n for n in flatten(seq) if isinstance(n, Node)]\r
258\r
259nodes = {}\r
260\r
261class Node:\r
262 """Abstract base class for ast nodes."""\r
263 def getChildren(self):\r
264 pass # implemented by subclasses\r
265 def __iter__(self):\r
266 for n in self.getChildren():\r
267 yield n\r
268 def asList(self): # for backwards compatibility\r
269 return self.getChildren()\r
270 def getChildNodes(self):\r
271 pass # implemented by subclasses\r
272\r
273class EmptyNode(Node):\r
274 pass\r
275\r
276class Expression(Node):\r
277 # Expression is an artificial node class to support "eval"\r
278 nodes["expression"] = "Expression"\r
279 def __init__(self, node):\r
280 self.node = node\r
281\r
282 def getChildren(self):\r
283 return self.node,\r
284\r
285 def getChildNodes(self):\r
286 return self.node,\r
287\r
288 def __repr__(self):\r
289 return "Expression(%s)" % (repr(self.node))\r
290\r
291### EPILOGUE\r
292for name, obj in globals().items():\r
293 if isinstance(obj, type) and issubclass(obj, Node):\r
294 nodes[name.lower()] = obj\r