blob: a97798d9a5ea8ef12bf88cbfc1b5664ba7825674 [file] [log] [blame]
Jeremy Hyltonfa974a92000-03-06 18:50:48 +00001"""Parse tree transformation module.
2
3Transforms Python source code into an abstract syntax tree (AST)
4defined in the ast module.
5
6The simplest ways to invoke this module are via parse and parseFile.
7parse(buf) -> AST
8parseFile(path) -> AST
9"""
10
Jeremy Hylton9c048f92000-10-13 21:58:13 +000011# Original version written by Greg Stein (gstein@lyra.org)
12# and Bill Tutt (rassilon@lima.mudlib.org)
13# February 1997.
Jeremy Hyltonf968e852000-02-04 00:25:23 +000014#
Jeremy Hylton9c048f92000-10-13 21:58:13 +000015# Modifications and improvements for Python 2.0 by Jeremy Hylton and
16# Mark Hammond
17
18# Portions of this file are:
19# Copyright (C) 1997-1998 Greg Stein. All Rights Reserved.
20#
21# This module is provided under a BSD-ish license. See
22# http://www.opensource.org/licenses/bsd-license.html
23# and replace OWNER, ORGANIZATION, and YEAR as appropriate.
24
25
Jeremy Hyltonf968e852000-02-04 00:25:23 +000026# The output tree has the following nodes:
27#
28# Source Python line #'s appear at the end of each of all of these nodes
29# If a line # doesn't apply, there will be a None instead.
30#
31# module: doc, node
32# stmt: [ node1, ..., nodeN ]
33# function: name, argnames, defaults, flags, doc, codeNode
34# lambda: argnames, defaults, flags, codeNode
35# classdef: name, bases, doc, codeNode
36# pass:
37# break:
38# continue:
39# for: assignNode, listNode, bodyNode, elseNode
40# while: testNode, bodyNode, elseNode
41# if: [ (testNode, suiteNode), ... ], elseNode
42# exec: expr1Node, expr2Node, expr3Node
43# from: modname, [ name1, ..., nameN ]
44# import: [ name1, ..., nameN ]
45# raise: expr1Node, expr2Node, expr3Node
46# tryfinally: trySuiteNode, finSuiteNode
47# tryexcept: trySuiteNode, [ (exprNode, assgnNode, suiteNode), ... ], elseNode
48# return: valueNode
49# const: value
Jeremy Hylton9c048f92000-10-13 21:58:13 +000050# print: [ node1, ..., nodeN ] [, dest]
51# printnl: [ node1, ..., nodeN ] [, dest]
Jeremy Hyltonf968e852000-02-04 00:25:23 +000052# discard: exprNode
Jeremy Hylton9c048f92000-10-13 21:58:13 +000053# augassign: node, op, expr
Jeremy Hyltonf968e852000-02-04 00:25:23 +000054# assign: [ node1, ..., nodeN ], exprNode
55# ass_tuple: [ node1, ..., nodeN ]
56# ass_list: [ node1, ..., nodeN ]
57# ass_name: name, flags
58# ass_attr: exprNode, attrname, flags
59# list: [ node1, ..., nodeN ]
60# dict: [ (key1, val1), ..., (keyN, valN) ]
61# not: exprNode
62# compare: exprNode, [ (op, node), ..., (op, node) ]
63# name: name
64# global: [ name1, ..., nameN ]
65# backquote: node
66# getattr: exprNode, attrname
67# call_func: node, [ arg1, ..., argN ]
68# keyword: name, exprNode
69# subscript: exprNode, flags, [ sub1, ..., subN ]
70# ellipsis:
71# sliceobj: [ node1, ..., nodeN ]
72# slice: exprNode, flags, lowerNode, upperNode
73# assert: expr1, expr2
74#
75# Compiled as "binary" ops:
76# tuple: [ node1, ..., nodeN ]
77# or: [ node1, ..., nodeN ]
78# and: [ node1, ..., nodeN ]
79# bitor: [ node1, ..., nodeN ]
80# bitxor: [ node1, ..., nodeN ]
81# bitand: [ node1, ..., nodeN ]
82#
83# Operations easily evaluateable on constants:
84# <<: exprNode, shiftNode
85# >>: exprNode, shiftNode
86# +: leftNode, rightNode
87# -: leftNode, rightNode
88# *: leftNode, rightNode
89# /: leftNode, rightNode
90# %: leftNode, rightNode
91# power: leftNode, rightNode
92# unary+: node
93# unary-: node
94# invert: node
95#
96
Jeremy Hyltonf968e852000-02-04 00:25:23 +000097import ast
98import parser
Jeremy Hylton9c048f92000-10-13 21:58:13 +000099# Care must be taken to use only symbols and tokens defined in Python
100# 1.5.2 for code branches executed in 1.5.2
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000101import symbol
102import token
103import string
104
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000105error = 'walker.error'
106
Jeremy Hylton9605c112000-02-08 18:57:32 +0000107from consts import CO_VARARGS, CO_VARKEYWORDS
108from consts import OP_ASSIGN, OP_DELETE, OP_APPLY
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000109
Jeremy Hyltonfa974a92000-03-06 18:50:48 +0000110def parseFile(path):
111 f = open(path)
112 src = f.read()
113 f.close()
114 return parse(src)
115
116def parse(buf):
117 return Transformer().parsesuite(buf)
118
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000119def asList(nodes):
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000120 l = []
121 for item in nodes:
122 if hasattr(item, "asList"):
123 l.append(item.asList())
124 else:
125 if type(item) is type( (None, None) ):
126 l.append(tuple(asList(item)))
127 elif type(item) is type( [] ):
128 l.append(asList(item))
129 else:
130 l.append(item)
131 return l
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000132
133def Node(*args):
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000134 kind = args[0]
135 if ast.nodes.has_key(kind):
136 try:
137 return apply(ast.nodes[kind], args[1:])
138 except TypeError:
139 print ast.nodes[kind], len(args), args
140 raise
141 else:
142 raise error, "Can't find appropriate Node type."
143 #return apply(ast.Node, args)
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000144
145class Transformer:
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000146 """Utility object for transforming Python parse trees.
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000147
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000148 Exposes the following methods:
149 tree = transform(ast_tree)
150 tree = parsesuite(text)
151 tree = parseexpr(text)
152 tree = parsefile(fileob | filename)
153 """
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000154
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000155 def __init__(self):
156 self._dispatch = { }
157 for value, name in symbol.sym_name.items():
158 if hasattr(self, name):
159 self._dispatch[value] = getattr(self, name)
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000160
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000161 def transform(self, tree):
162 """Transform an AST into a modified parse tree."""
163 if type(tree) != type(()) and type(tree) != type([]):
164 tree = parser.ast2tuple(tree,1)
165 return self.compile_node(tree)
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000166
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000167 def parsesuite(self, text):
168 """Return a modified parse tree for the given suite text."""
169 # Hack for handling non-native line endings on non-DOS like OSs.
170 text = string.replace(text, '\x0d', '')
171 return self.transform(parser.suite(text))
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000172
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000173 def parseexpr(self, text):
174 """Return a modified parse tree for the given expression text."""
175 return self.transform(parser.expr(text))
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000176
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000177 def parsefile(self, file):
178 """Return a modified parse tree for the contents of the given file."""
179 if type(file) == type(''):
180 file = open(file)
181 return self.parsesuite(file.read())
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000182
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000183 # --------------------------------------------------------------
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000184 #
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000185 # PRIVATE METHODS
186 #
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000187
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000188 def compile_node(self, node):
189 ### emit a line-number node?
190 n = node[0]
191 if n == symbol.single_input:
192 return self.single_input(node[1:])
193 if n == symbol.file_input:
194 return self.file_input(node[1:])
195 if n == symbol.eval_input:
196 return self.eval_input(node[1:])
197 if n == symbol.lambdef:
198 return self.lambdef(node[1:])
199 if n == symbol.funcdef:
200 return self.funcdef(node[1:])
201 if n == symbol.classdef:
202 return self.classdef(node[1:])
203
204 raise error, ('unexpected node type', n)
205
206 def single_input(self, node):
207 ### do we want to do anything about being "interactive" ?
208
209 # NEWLINE | simple_stmt | compound_stmt NEWLINE
210 n = node[0][0]
211 if n != token.NEWLINE:
212 return self.com_stmt(node[0])
213
214 return Node('pass')
215
216 def file_input(self, nodelist):
217 doc = self.get_docstring(nodelist, symbol.file_input)
218 stmts = [ ]
219 for node in nodelist:
220 if node[0] != token.ENDMARKER and node[0] != token.NEWLINE:
221 self.com_append_stmt(stmts, node)
222 return Node('module', doc, Node('stmt', stmts))
223
224 def eval_input(self, nodelist):
225 # from the built-in function input()
226 ### is this sufficient?
227 return self.com_node(nodelist[0])
228
229 def funcdef(self, nodelist):
230 # funcdef: 'def' NAME parameters ':' suite
231 # parameters: '(' [varargslist] ')'
232
233 lineno = nodelist[1][2]
234 name = nodelist[1][1]
235 args = nodelist[2][2]
236
237 if args[0] == symbol.varargslist:
238 names, defaults, flags = self.com_arglist(args[1:])
239 else:
240 names = defaults = ()
241 flags = 0
242 doc = self.get_docstring(nodelist[4])
243
244 # code for function
245 code = self.com_node(nodelist[4])
246
247 n = Node('function', name, names, defaults, flags, doc, code)
248 n.lineno = lineno
249 return n
250
251 def lambdef(self, nodelist):
252 # lambdef: 'lambda' [varargslist] ':' test
253 if nodelist[2][0] == symbol.varargslist:
254 names, defaults, flags = self.com_arglist(nodelist[2][1:])
255 else:
256 names = defaults = ()
257 flags = 0
258
259 # code for lambda
260 code = self.com_node(nodelist[-1])
261
262 n = Node('lambda', names, defaults, flags, code)
263 n.lineno = nodelist[1][2]
264 return n
265
266 def classdef(self, nodelist):
267 # classdef: 'class' NAME ['(' testlist ')'] ':' suite
268
269 name = nodelist[1][1]
270 doc = self.get_docstring(nodelist[-1])
271 if nodelist[2][0] == token.COLON:
272 bases = []
273 else:
274 bases = self.com_bases(nodelist[3])
275
276 # code for class
277 code = self.com_node(nodelist[-1])
278
279 n = Node('class', name, bases, doc, code)
280 n.lineno = nodelist[1][2]
281 return n
282
283 def stmt(self, nodelist):
284 return self.com_stmt(nodelist[0])
285
286 small_stmt = stmt
287 flow_stmt = stmt
288 compound_stmt = stmt
289
290 def simple_stmt(self, nodelist):
291 # small_stmt (';' small_stmt)* [';'] NEWLINE
292 stmts = [ ]
293 for i in range(0, len(nodelist), 2):
294 self.com_append_stmt(stmts, nodelist[i])
295 return Node('stmt', stmts)
296
297 def parameters(self, nodelist):
298 raise error
299
300 def varargslist(self, nodelist):
301 raise error
302
303 def fpdef(self, nodelist):
304 raise error
305
306 def fplist(self, nodelist):
307 raise error
308
309 def dotted_name(self, nodelist):
310 raise error
311
312 def comp_op(self, nodelist):
313 raise error
314
315 def trailer(self, nodelist):
316 raise error
317
318 def sliceop(self, nodelist):
319 raise error
320
321 def argument(self, nodelist):
322 raise error
323
324 # --------------------------------------------------------------
325 #
326 # STATEMENT NODES (invoked by com_node())
327 #
328
329 def expr_stmt(self, nodelist):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000330 # augassign testlist | testlist ('=' testlist)*
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000331 exprNode = self.com_node(nodelist[-1])
332 if len(nodelist) == 1:
333 return Node('discard', exprNode)
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000334 if nodelist[1][0] == token.EQUAL:
335 nodes = [ ]
336 for i in range(0, len(nodelist) - 2, 2):
337 nodes.append(self.com_assign(nodelist[i], OP_ASSIGN))
338 n = Node('assign', nodes, exprNode)
339 n.lineno = nodelist[1][2]
340 else:
341 lval = self.com_augassign(nodelist[0])
342 op = self.com_augassign_op(nodelist[1])
343 n = Node('augassign', lval, op[1], exprNode)
344 n.lineno = op[2]
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000345 return n
346
347 def print_stmt(self, nodelist):
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000348 # print ([ test (',' test)* [','] ] | '>>' test [ (',' test)+ [','] ])
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000349 items = [ ]
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000350 if len(nodelist) == 1:
351 start = 1
352 dest = None
353 elif nodelist[1][0] == token.RIGHTSHIFT:
354 assert len(nodelist) == 3 \
355 or nodelist[3][0] == token.COMMA
356 dest = self.com_node(nodelist[2])
357 start = 4
358 else:
359 dest = None
360 start = 1
361 for i in range(start, len(nodelist), 2):
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000362 items.append(self.com_node(nodelist[i]))
363 if nodelist[-1][0] == token.COMMA:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000364 n = Node('print', items, dest)
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000365 n.lineno = nodelist[0][2]
366 return n
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000367 n = Node('printnl', items, dest)
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000368 n.lineno = nodelist[0][2]
369 return n
370
371 def del_stmt(self, nodelist):
372 return self.com_assign(nodelist[1], OP_DELETE)
373
374 def pass_stmt(self, nodelist):
375 # pass:
376 n = Node('pass')
377 n.lineno = nodelist[0][2]
378 return n
379
380 def break_stmt(self, nodelist):
381 # break:
382 n = Node('break')
383 n.lineno = nodelist[0][2]
384 return n
385
386 def continue_stmt(self, nodelist):
387 # continue
388 n = Node('continue')
389 n.lineno = nodelist[0][2]
390 return n
391
392 def return_stmt(self, nodelist):
393 # return: [testlist]
394 if len(nodelist) < 2:
395 n = Node('return', Node('const', None))
396 n.lineno = nodelist[0][2]
397 return n
398 n = Node('return', self.com_node(nodelist[1]))
399 n.lineno = nodelist[0][2]
400 return n
401
402 def raise_stmt(self, nodelist):
403 # raise: [test [',' test [',' test]]]
404 if len(nodelist) > 5:
405 expr3 = self.com_node(nodelist[5])
406 else:
407 expr3 = None
408 if len(nodelist) > 3:
409 expr2 = self.com_node(nodelist[3])
410 else:
411 expr2 = None
412 if len(nodelist) > 1:
413 expr1 = self.com_node(nodelist[1])
414 else:
415 expr1 = None
416 n = Node('raise', expr1, expr2, expr3)
417 n.lineno = nodelist[0][2]
418 return n
419
420 def import_stmt(self, nodelist):
421 # import_stmt: 'import' dotted_as_name (',' dotted_as_name)* |
422 # from: 'from' dotted_name 'import'
423 # ('*' | import_as_name (',' import_as_name)*)
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000424 if nodelist[0][1] == 'from':
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000425 names = []
426 if nodelist[3][0] == token.NAME:
427 for i in range(3, len(nodelist), 2):
428 names.append((nodelist[i][1], None))
429 else:
430 for i in range(3, len(nodelist), 2):
431 names.append(self.com_import_as_name(nodelist[i][1]))
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000432 n = Node('from', self.com_dotted_name(nodelist[1]), names)
433 n.lineno = nodelist[0][2]
434 return n
435
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000436 if nodelist[1][0] == symbol.dotted_name:
437 names = [(self.com_dotted_name(nodelist[1][1:]), None)]
438 else:
439 names = []
440 for i in range(1, len(nodelist), 2):
441 names.append(self.com_dotted_as_name(nodelist[i]))
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000442 n = Node('import', names)
443 n.lineno = nodelist[0][2]
444 return n
445
446 def global_stmt(self, nodelist):
447 # global: NAME (',' NAME)*
448 names = [ ]
449 for i in range(1, len(nodelist), 2):
450 names.append(nodelist[i][1])
451 n = Node('global', names)
452 n.lineno = nodelist[0][2]
453 return n
454
455 def exec_stmt(self, nodelist):
456 # exec_stmt: 'exec' expr ['in' expr [',' expr]]
457 expr1 = self.com_node(nodelist[1])
458 if len(nodelist) >= 4:
459 expr2 = self.com_node(nodelist[3])
460 if len(nodelist) >= 6:
461 expr3 = self.com_node(nodelist[5])
462 else:
463 expr3 = None
464 else:
465 expr2 = expr3 = None
466
467 n = Node('exec', expr1, expr2, expr3)
468 n.lineno = nodelist[0][2]
469 return n
470
471 def assert_stmt(self, nodelist):
472 # 'assert': test, [',' test]
473 expr1 = self.com_node(nodelist[1])
474 if (len(nodelist) == 4):
475 expr2 = self.com_node(nodelist[3])
476 else:
477 expr2 = Node('name', 'None')
478 n = Node('assert', expr1, expr2)
479 n.lineno = nodelist[0][2]
480 return n
481
482 def if_stmt(self, nodelist):
483 # if: test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
484 tests = [ ]
485 for i in range(0, len(nodelist) - 3, 4):
486 testNode = self.com_node(nodelist[i + 1])
487 suiteNode = self.com_node(nodelist[i + 3])
488 tests.append((testNode, suiteNode))
489
490 if len(nodelist) % 4 == 3:
491 elseNode = self.com_node(nodelist[-1])
492## elseNode.lineno = nodelist[-1][1][2]
493 else:
494 elseNode = None
495 n = Node('if', tests, elseNode)
496 n.lineno = nodelist[0][2]
497 return n
498
499 def while_stmt(self, nodelist):
500 # 'while' test ':' suite ['else' ':' suite]
501
502 testNode = self.com_node(nodelist[1])
503 bodyNode = self.com_node(nodelist[3])
504
505 if len(nodelist) > 4:
506 elseNode = self.com_node(nodelist[6])
507 else:
508 elseNode = None
509
510 n = Node('while', testNode, bodyNode, elseNode)
511 n.lineno = nodelist[0][2]
512 return n
513
514 def for_stmt(self, nodelist):
515 # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite]
516
517 assignNode = self.com_assign(nodelist[1], OP_ASSIGN)
518 listNode = self.com_node(nodelist[3])
519 bodyNode = self.com_node(nodelist[5])
520
521 if len(nodelist) > 8:
522 elseNode = self.com_node(nodelist[8])
523 else:
524 elseNode = None
525
526 n = Node('for', assignNode, listNode, bodyNode, elseNode)
527 n.lineno = nodelist[0][2]
528 return n
529
530 def try_stmt(self, nodelist):
531 # 'try' ':' suite (except_clause ':' suite)+ ['else' ':' suite]
532 # | 'try' ':' suite 'finally' ':' suite
533 if nodelist[3][0] != symbol.except_clause:
534 return self.com_try_finally(nodelist)
535
536 return self.com_try_except(nodelist)
537
538 def suite(self, nodelist):
539 # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT
540 if len(nodelist) == 1:
541 return self.com_stmt(nodelist[0])
542
543 stmts = [ ]
544 for node in nodelist:
545 if node[0] == symbol.stmt:
546 self.com_append_stmt(stmts, node)
547 return Node('stmt', stmts)
548
549 # --------------------------------------------------------------
550 #
551 # EXPRESSION NODES (invoked by com_node())
552 #
553
554 def testlist(self, nodelist):
555 # testlist: expr (',' expr)* [',']
556 # exprlist: expr (',' expr)* [',']
557 return self.com_binary('tuple', nodelist)
558
559 exprlist = testlist
560
561 def test(self, nodelist):
562 # and_test ('or' and_test)* | lambdef
563 if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
564 return self.lambdef(nodelist[0])
565 return self.com_binary('or', nodelist)
566
567 def and_test(self, nodelist):
568 # not_test ('and' not_test)*
569 return self.com_binary('and', nodelist)
570
571 def not_test(self, nodelist):
572 # 'not' not_test | comparison
573 result = self.com_node(nodelist[-1])
574 if len(nodelist) == 2:
575 n = Node('not', result)
576 n.lineno = nodelist[0][2]
577 return n
578 return result
579
580 def comparison(self, nodelist):
581 # comparison: expr (comp_op expr)*
582 node = self.com_node(nodelist[0])
583 if len(nodelist) == 1:
584 return node
585
586 results = [ ]
587 for i in range(2, len(nodelist), 2):
588 nl = nodelist[i-1]
589
590 # comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '=='
591 # | 'in' | 'not' 'in' | 'is' | 'is' 'not'
592 n = nl[1]
593 if n[0] == token.NAME:
594 type = n[1]
595 if len(nl) == 3:
596 if type == 'not':
597 type = 'not in'
598 else:
599 type = 'is not'
600 else:
601 type = _cmp_types[n[0]]
602
603 lineno = nl[1][2]
604 results.append((type, self.com_node(nodelist[i])))
605
606 # we need a special "compare" node so that we can distinguish
607 # 3 < x < 5 from (3 < x) < 5
608 # the two have very different semantics and results (note that the
609 # latter form is always true)
610
611 n = Node('compare', node, results)
612 n.lineno = lineno
613 return n
614
615 def expr(self, nodelist):
616 # xor_expr ('|' xor_expr)*
617 return self.com_binary('bitor', nodelist)
618
619 def xor_expr(self, nodelist):
620 # xor_expr ('^' xor_expr)*
621 return self.com_binary('bitxor', nodelist)
622
623 def and_expr(self, nodelist):
624 # xor_expr ('&' xor_expr)*
625 return self.com_binary('bitand', nodelist)
626
627 def shift_expr(self, nodelist):
628 # shift_expr ('<<'|'>>' shift_expr)*
629 node = self.com_node(nodelist[0])
630 for i in range(2, len(nodelist), 2):
631 right = self.com_node(nodelist[i])
632 if nodelist[i-1][0] == token.LEFTSHIFT:
633 node = Node('<<', [node, right])
634 node.lineno = nodelist[1][2]
635 else:
636 node = Node('>>', [node, right])
637 node.lineno = nodelist[1][2]
638 return node
639
640 def arith_expr(self, nodelist):
641 node = self.com_node(nodelist[0])
642 for i in range(2, len(nodelist), 2):
643 right = self.com_node(nodelist[i])
644 if nodelist[i-1][0] == token.PLUS:
645 node = Node('+', [node, right])
646 node.lineno = nodelist[1][2]
647 else:
648 node = Node('-', [node, right])
649 node.lineno = nodelist[1][2]
650 return node
651
652 def term(self, nodelist):
653 node = self.com_node(nodelist[0])
654 for i in range(2, len(nodelist), 2):
655 right = self.com_node(nodelist[i])
656 if nodelist[i-1][0] == token.STAR:
657 node = Node('*', [node, right])
658 node.lineno = nodelist[1][2]
659 elif nodelist[i-1][0] == token.SLASH:
660 node = Node('/', [node, right])
661 node.lineno = nodelist[1][2]
662 else:
663 node = Node('%', [node, right])
664 node.lineno = nodelist[1][2]
665 return node
666
667 def factor(self, nodelist):
668 t = nodelist[0][0]
669 node = self.com_node(nodelist[-1])
670 if t == token.PLUS:
671 node = Node('unary+', node)
672 node.lineno = nodelist[0][2]
673 elif t == token.MINUS:
674 node = Node('unary-', node)
675 node.lineno = nodelist[0][2]
676 elif t == token.TILDE:
677 node = Node('invert', node)
678 node.lineno = nodelist[0][2]
679 return node
680
681 def power(self, nodelist):
682 # power: atom trailer* ('**' factor)*
683 node = self.com_node(nodelist[0])
684 for i in range(1, len(nodelist)):
685 if nodelist[i][0] == token.DOUBLESTAR:
686 n = Node('power', [node, self.com_node(nodelist[i+1])])
687 n.lineno = nodelist[i][2]
688 return n
689
690 node = self.com_apply_trailer(node, nodelist[i])
691
692 return node
693
694 def atom(self, nodelist):
695 t = nodelist[0][0]
696 if t == token.LPAR:
697 if nodelist[1][0] == token.RPAR:
698 n = Node('tuple', ())
699 n.lineno = nodelist[0][2]
700 return n
701 return self.com_node(nodelist[1])
702
703 if t == token.LSQB:
704 if nodelist[1][0] == token.RSQB:
705 n = Node('list', ())
706 n.lineno = nodelist[0][2]
707 return n
708 return self.com_list_constructor(nodelist[1])
709
710 if t == token.LBRACE:
711 if nodelist[1][0] == token.RBRACE:
712 return Node('dict', ())
713 return self.com_dictmaker(nodelist[1])
714
715 if t == token.BACKQUOTE:
716 n = Node('backquote', self.com_node(nodelist[1]))
717 n.lineno = nodelist[0][2]
718 return n
719
720 if t == token.NUMBER:
721 ### need to verify this matches compile.c
722 k = eval(nodelist[0][1])
723 n = Node('const', k)
724 n.lineno = nodelist[0][2]
725 return n
726
727 if t == token.STRING:
728 ### need to verify this matches compile.c
729 k = ''
730 for node in nodelist:
731 k = k + eval(node[1])
732 n = Node('const', k)
733 n.lineno = nodelist[0][2]
734 return n
735
736 if t == token.NAME:
737 ### any processing to do?
738 n = Node('name', nodelist[0][1])
739 n.lineno = nodelist[0][2]
740 return n
741
742 raise error, "unknown node type"
743
744 # --------------------------------------------------------------
745 #
746 # INTERNAL PARSING UTILITIES
747 #
748
749 def com_node(self, node):
750 # Note: compile.c has handling in com_node for del_stmt, pass_stmt,
751 # break_stmt, stmt, small_stmt, flow_stmt, simple_stmt,
752 # and compound_stmt.
753 # We'll just dispatch them.
754
755 #
756 # A ';' at the end of a line can make a NEWLINE token appear here,
757 # Render it harmless. (genc discards ('discard', ('const', xxxx)) Nodes)
758 #
759 if node[0] == token.NEWLINE:
760 return Node('discard', Node('const', None))
761
762 if node[0] not in _legal_node_types:
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000763 raise error, 'illegal node passed to com_node: %s' % `node`
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000764
Jeremy Hylton20516082000-09-01 20:33:26 +0000765# print "dispatch", self._dispatch[node[0]].__name__, node
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000766 return self._dispatch[node[0]](node[1:])
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000767
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000768 def com_arglist(self, nodelist):
769 # varargslist:
770 # (fpdef ['=' test] ',')* ('*' NAME [',' ('**'|'*' '*') NAME]
771 # | fpdef ['=' test] (',' fpdef ['=' test])* [',']
772 # | ('**'|'*' '*') NAME)
773 # fpdef: NAME | '(' fplist ')'
774 # fplist: fpdef (',' fpdef)* [',']
775 names = [ ]
776 defaults = [ ]
777 flags = 0
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000778
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000779 i = 0
780 while i < len(nodelist):
781 node = nodelist[i]
782 if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
783 if node[0] == token.STAR:
784 node = nodelist[i+1]
785 if node[0] == token.NAME:
786 names.append(node[1])
787 flags = flags | CO_VARARGS
788 i = i + 3
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000789
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000790 if i < len(nodelist):
791 # should be DOUBLESTAR or STAR STAR
792 if nodelist[i][0] == token.DOUBLESTAR:
793 node = nodelist[i+1]
794 else:
795 node = nodelist[i+2]
796 names.append(node[1])
797 flags = flags | CO_VARKEYWORDS
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000798
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000799 break
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000800
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000801 # fpdef: NAME | '(' fplist ')'
802 names.append(self.com_fpdef(node))
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000803
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000804 i = i + 1
805 if i >= len(nodelist):
806 break
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000807
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000808 if nodelist[i][0] == token.EQUAL:
809 defaults.append(self.com_node(nodelist[i + 1]))
810 i = i + 2
811 elif len(defaults):
812 # Treat "(a=1, b)" as "(a=1, b=None)"
813 defaults.append(Node('const', None))
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000814
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000815 i = i + 1
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000816
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000817 return names, defaults, flags
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000818
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000819 def com_fpdef(self, node):
820 # fpdef: NAME | '(' fplist ')'
821 if node[1][0] == token.LPAR:
822 return self.com_fplist(node[2])
823 return node[1][1]
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000824
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000825 def com_fplist(self, node):
826 # fplist: fpdef (',' fpdef)* [',']
827 if len(node) == 2:
828 return self.com_fpdef(node[1])
829 list = [ ]
830 for i in range(1, len(node), 2):
831 list.append(self.com_fpdef(node[i]))
832 return tuple(list)
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000833
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000834 def com_dotted_name(self, node):
835 # String together the dotted names and return the string
836 name = ""
837 for n in node:
838 if type(n) == type(()) and n[0] == 1:
839 name = name + n[1] + '.'
840 return name[:-1]
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000841
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000842 def com_dotted_as_name(self, node):
843 dot = self.com_dotted_name(node[1])
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000844 if len(node) <= 2:
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000845 return dot, None
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000846 if node[0] == symbol.dotted_name:
847 pass
848 else:
849 assert node[2][1] == 'as'
850 assert node[3][0] == token.NAME
851 return dot, node[3][1]
Jeremy Hylton20516082000-09-01 20:33:26 +0000852
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000853 def com_import_as_name(self, node):
Jeremy Hylton4e1be722000-10-12 20:23:23 +0000854 if node == '*':
855 return '*', None
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000856 if node[0] == token.NAME:
857 return node[1], None
858 assert len(node) == 4
859 assert node[2][1] == 'as'
860 assert node[3][0] == token.NAME
861 return node[1][1], node[3][1]
Jeremy Hylton20516082000-09-01 20:33:26 +0000862
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000863 def com_bases(self, node):
864 bases = [ ]
865 for i in range(1, len(node), 2):
866 bases.append(self.com_node(node[i]))
867 return bases
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000868
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000869 def com_try_finally(self, nodelist):
870 # try_fin_stmt: "try" ":" suite "finally" ":" suite
871 n = Node('tryfinally', self.com_node(nodelist[2]), self.com_node(nodelist[5]))
872 n.lineno = nodelist[0][2]
873 return n
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000874
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000875 def com_try_except(self, nodelist):
876 # try_except: 'try' ':' suite (except_clause ':' suite)* ['else' suite]
877 #tryexcept: [TryNode, [except_clauses], elseNode)]
878 stmt = self.com_node(nodelist[2])
879 clauses = []
880 elseNode = None
881 for i in range(3, len(nodelist), 3):
882 node = nodelist[i]
883 if node[0] == symbol.except_clause:
884 # except_clause: 'except' [expr [',' expr]] */
885 if len(node) > 2:
886 expr1 = self.com_node(node[2])
887 if len(node) > 4:
888 expr2 = self.com_assign(node[4], OP_ASSIGN)
889 else:
890 expr2 = None
891 else:
892 expr1 = expr2 = None
893 clauses.append((expr1, expr2, self.com_node(nodelist[i+2])))
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000894
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000895 if node[0] == token.NAME:
896 elseNode = self.com_node(nodelist[i+2])
897 n = Node('tryexcept', self.com_node(nodelist[2]), clauses, elseNode)
898 n.lineno = nodelist[0][2]
899 return n
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000900
Jeremy Hylton9c048f92000-10-13 21:58:13 +0000901 def com_augassign_op(self, node):
902 assert node[0] == symbol.augassign
903 return node[1]
904
905 def com_augassign(self, node):
906 """Return node suitable for lvalue of augmented assignment
907
908 Names, slices, and attributes are the only allowable nodes.
909 """
910 l = self.com_node(node)
911 if l[0] in ('name', 'slice', 'subscript', 'getattr'):
912 return l
913 raise SyntaxError, "can't assign to %s" % l[0]
914
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000915 def com_assign(self, node, assigning):
916 # return a node suitable for use as an "lvalue"
917 # loop to avoid trivial recursion
918 while 1:
919 t = node[0]
920 if t == symbol.exprlist or t == symbol.testlist:
921 if len(node) > 2:
922 return self.com_assign_tuple(node, assigning)
923 node = node[1]
924 elif t in _assign_types:
925 if len(node) > 2:
926 raise SyntaxError, "can't assign to operator"
927 node = node[1]
928 elif t == symbol.power:
929 if node[1][0] != symbol.atom:
930 raise SyntaxError, "can't assign to operator"
931 if len(node) > 2:
932 primary = self.com_node(node[1])
933 for i in range(2, len(node)-1):
934 ch = node[i]
935 if ch[0] == token.DOUBLESTAR:
936 raise SyntaxError, "can't assign to operator"
937 primary = self.com_apply_trailer(primary, ch)
938 return self.com_assign_trailer(primary, node[-1], assigning)
939 node = node[1]
940 elif t == symbol.atom:
941 t = node[1][0]
942 if t == token.LPAR:
943 node = node[2]
944 if node[0] == token.RPAR:
945 raise SyntaxError, "can't assign to ()"
946 elif t == token.LSQB:
947 node = node[2]
948 if node[0] == token.RSQB:
949 raise SyntaxError, "can't assign to []"
950 return self.com_assign_list(node, assigning)
951 elif t == token.NAME:
952 return self.com_assign_name(node[1], assigning)
953 else:
954 raise SyntaxError, "can't assign to literal"
955 else:
956 raise SyntaxError, "bad assignment"
957
958 def com_assign_tuple(self, node, assigning):
959 assigns = [ ]
960 for i in range(1, len(node), 2):
961 assigns.append(self.com_assign(node[i], assigning))
962 return Node('ass_tuple', assigns)
963
964 def com_assign_list(self, node, assigning):
965 assigns = [ ]
966 for i in range(1, len(node), 2):
967 assigns.append(self.com_assign(node[i], assigning))
968 return Node('ass_list', assigns)
969
970 def com_assign_name(self, node, assigning):
971 n = Node('ass_name', node[1], assigning)
972 n.lineno = node[2]
973 return n
974
975 def com_assign_trailer(self, primary, node, assigning):
Jeremy Hyltonf968e852000-02-04 00:25:23 +0000976 t = node[1][0]
977 if t == token.LPAR:
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000978 raise SyntaxError, "can't assign to function call"
979 if t == token.DOT:
980 return self.com_assign_attr(primary, node[2], assigning)
981 if t == token.LSQB:
982 return self.com_subscriptlist(primary, node[2], assigning)
983 raise SyntaxError, "unknown trailer type: %s" % t
984
985 def com_assign_attr(self, primary, node, assigning):
986 return Node('ass_attr', primary, node[1], assigning)
987
988 def com_binary(self, type, nodelist):
989 "Compile 'NODE (OP NODE)*' into (type, [ node1, ..., nodeN ])."
990 if len(nodelist) == 1:
991 return self.com_node(nodelist[0])
992 items = [ ]
993 for i in range(0, len(nodelist), 2):
994 items.append(self.com_node(nodelist[i]))
995 return Node(type, items)
996
997 def com_stmt(self, node):
Jeremy Hylton572bdce2000-09-20 02:47:28 +0000998 result = self.com_node(node)
999 try:
1000 result[0]
1001 except:
1002 print node[0]
1003 if result[0] == 'stmt':
1004 return result
1005 return Node('stmt', [ result ])
1006
1007 def com_append_stmt(self, stmts, node):
1008 result = self.com_node(node)
1009 try:
1010 result[0]
1011 except:
1012 print node
1013 if result[0] == 'stmt':
1014 stmts[len(stmts):] = result[1]
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001015 else:
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001016 stmts.append(result)
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001017
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001018 if hasattr(symbol, 'list_for'):
1019 def com_list_constructor(self, nodelist):
1020 # listmaker: test ( list_for | (',' test)* [','] )
1021 values = [ ]
1022 for i in range(1, len(nodelist)):
1023 if nodelist[i][0] == symbol.list_for:
1024 assert len(nodelist[i:]) == 1
1025 return self.com_list_comprehension(values[0],
1026 nodelist[i])
1027 elif nodelist[i][0] == token.COMMA:
1028 continue
1029 values.append(self.com_node(nodelist[i]))
1030 return Node('list', values)
1031
1032 def com_list_comprehension(self, expr, node):
1033 # list_iter: list_for | list_if
1034 # list_for: 'for' exprlist 'in' testlist [list_iter]
1035 # list_if: 'if' test [list_iter]
1036 lineno = node[1][2]
1037 fors = []
1038 while node:
1039 if node[1][1] == 'for':
1040 assignNode = self.com_assign(node[2], OP_ASSIGN)
1041 listNode = self.com_node(node[4])
1042 newfor = Node('listcomp_for', assignNode,
1043 listNode, [])
1044 newfor.lineno = node[1][2]
1045 fors.append(newfor)
1046 if len(node) == 5:
1047 node = None
1048 else:
1049 node = self.com_list_iter(node[5])
1050 elif node[1][1] == 'if':
1051 test = self.com_node(node[2])
1052 newif = Node('listcomp_if', test)
1053 newif.lineno = node[1][2]
1054 newfor.ifs.append(newif)
1055 if len(node) == 3:
1056 node = None
1057 else:
1058 node = self.com_list_iter(node[3])
1059 else:
1060 raise SyntaxError, \
1061 ("unexpected list comprehension element: %s %d"
1062 % (node, lineno))
1063 n = Node('listcomp', expr, fors)
1064 n.lineno = lineno
1065 return n
1066
1067 def com_list_iter(self, node):
1068 assert node[0] == symbol.list_iter
1069 return node[1]
1070 else:
1071 def com_list_constructor(self, nodelist):
1072 values = [ ]
1073 for i in range(1, len(nodelist), 2):
1074 values.append(self.com_node(nodelist[i]))
1075 return Node('list', values)
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001076
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001077 def com_dictmaker(self, nodelist):
1078 # dictmaker: test ':' test (',' test ':' value)* [',']
1079 items = [ ]
1080 for i in range(1, len(nodelist), 4):
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001081 items.append((self.com_node(nodelist[i]),
1082 self.com_node(nodelist[i+2])))
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001083 return Node('dict', items)
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001084
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001085 def com_apply_trailer(self, primaryNode, nodelist):
1086 t = nodelist[1][0]
1087 if t == token.LPAR:
1088 return self.com_call_function(primaryNode, nodelist[2])
1089 if t == token.DOT:
1090 return self.com_select_member(primaryNode, nodelist[2])
1091 if t == token.LSQB:
1092 return self.com_subscriptlist(primaryNode, nodelist[2], OP_APPLY)
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001093
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001094 raise SyntaxError, 'unknown node type: %s' % t
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001095
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001096 def com_select_member(self, primaryNode, nodelist):
1097 if nodelist[0] != token.NAME:
1098 raise SyntaxError, "member must be a name"
1099 n = Node('getattr', primaryNode, nodelist[1])
1100 n.lineno = nodelist[2]
1101 return n
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001102
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001103 def com_call_function(self, primaryNode, nodelist):
1104 if nodelist[0] == token.RPAR:
1105 return Node('call_func', primaryNode, [ ])
1106 args = [ ]
1107 kw = 0
1108 len_nodelist = len(nodelist)
1109 for i in range(1, len_nodelist, 2):
1110 node = nodelist[i]
1111 if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
1112 break
1113 kw, result = self.com_argument(node, kw)
1114 args.append(result)
Jeremy Hyltonbe317e62000-05-02 22:32:59 +00001115 else:
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001116 i = i + 1 # No broken by star arg, so skip the last one we processed.
1117 if i < len_nodelist and nodelist[i][0] == token.COMMA:
1118 # need to accept an application that looks like "f(a, b,)"
1119 i = i + 1
1120 star_node = dstar_node = None
1121 while i < len_nodelist:
1122 tok = nodelist[i]
1123 ch = nodelist[i+1]
1124 i = i + 3
1125 if tok[0]==token.STAR:
1126 if star_node is not None:
1127 raise SyntaxError, 'already have the varargs indentifier'
1128 star_node = self.com_node(ch)
1129 elif tok[0]==token.DOUBLESTAR:
1130 if dstar_node is not None:
1131 raise SyntaxError, 'already have the kwargs indentifier'
1132 dstar_node = self.com_node(ch)
1133 else:
1134 raise SyntaxError, 'unknown node type: %s' % tok
Jeremy Hyltonbe317e62000-05-02 22:32:59 +00001135
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001136 return Node('call_func', primaryNode, args, star_node, dstar_node)
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001137
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001138 def com_argument(self, nodelist, kw):
1139 if len(nodelist) == 2:
1140 if kw:
1141 raise SyntaxError, "non-keyword arg after keyword arg"
1142 return 0, self.com_node(nodelist[1])
1143 result = self.com_node(nodelist[3])
1144 n = nodelist[1]
1145 while len(n) == 2 and n[0] != token.NAME:
1146 n = n[1]
1147 if n[0] != token.NAME:
1148 raise SyntaxError, "keyword can't be an expression (%s)"%n[0]
1149 node = Node('keyword', n[1], result)
1150 node.lineno = n[2]
1151 return 1, node
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001152
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001153 def com_subscriptlist(self, primary, nodelist, assigning):
1154 # slicing: simple_slicing | extended_slicing
1155 # simple_slicing: primary "[" short_slice "]"
1156 # extended_slicing: primary "[" slice_list "]"
1157 # slice_list: slice_item ("," slice_item)* [","]
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001158
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001159 # backwards compat slice for '[i:j]'
1160 if len(nodelist) == 2:
1161 sub = nodelist[1]
1162 if (sub[1][0] == token.COLON or \
1163 (len(sub) > 2 and sub[2][0] == token.COLON)) and \
1164 sub[-1][0] != symbol.sliceop:
1165 return self.com_slice(primary, sub, assigning)
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001166
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001167 subscripts = [ ]
1168 for i in range(1, len(nodelist), 2):
1169 subscripts.append(self.com_subscript(nodelist[i]))
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001170
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001171 return Node('subscript', primary, assigning, subscripts)
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001172
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001173 def com_subscript(self, node):
1174 # slice_item: expression | proper_slice | ellipsis
1175 ch = node[1]
1176 if ch[0] == token.DOT and node[2][0] == token.DOT:
1177 return Node('ellipsis')
1178 if ch[0] == token.COLON or len(node) > 2:
1179 return self.com_sliceobj(node)
1180 return self.com_node(ch)
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001181
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001182 def com_sliceobj(self, node):
1183 # proper_slice: short_slice | long_slice
1184 # short_slice: [lower_bound] ":" [upper_bound]
1185 # long_slice: short_slice ":" [stride]
1186 # lower_bound: expression
1187 # upper_bound: expression
1188 # stride: expression
1189 #
1190 # Note: a stride may be further slicing...
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001191
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001192 items = [ ]
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001193
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001194 if node[1][0] == token.COLON:
1195 items.append(Node('const', None))
1196 i = 2
1197 else:
1198 items.append(self.com_node(node[1]))
1199 # i == 2 is a COLON
1200 i = 3
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001201
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001202 if i < len(node) and node[i][0] == symbol.test:
1203 items.append(self.com_node(node[i]))
1204 i = i + 1
1205 else:
1206 items.append(Node('const', None))
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001207
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001208 # a short_slice has been built. look for long_slice now by looking
1209 # for strides...
1210 for j in range(i, len(node)):
1211 ch = node[j]
1212 if len(ch) == 2:
1213 items.append(Node('const', None))
1214 else:
1215 items.append(self.com_node(ch[2]))
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001216
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001217 return Node('sliceobj', items)
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001218
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001219 def com_slice(self, primary, node, assigning):
1220 # short_slice: [lower_bound] ":" [upper_bound]
1221 lower = upper = None
1222 if len(node) == 3:
1223 if node[1][0] == token.COLON:
1224 upper = self.com_node(node[2])
1225 else:
1226 lower = self.com_node(node[1])
1227 elif len(node) == 4:
1228 lower = self.com_node(node[1])
1229 upper = self.com_node(node[3])
1230 return Node('slice', primary, assigning, lower, upper)
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001231
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001232 def get_docstring(self, node, n=None):
1233 if n is None:
1234 n = node[0]
1235 node = node[1:]
1236 if n == symbol.suite:
1237 if len(node) == 1:
1238 return self.get_docstring(node[0])
1239 for sub in node:
1240 if sub[0] == symbol.stmt:
1241 return self.get_docstring(sub)
1242 return None
1243 if n == symbol.file_input:
1244 for sub in node:
1245 if sub[0] == symbol.stmt:
1246 return self.get_docstring(sub)
1247 return None
1248 if n == symbol.atom:
1249 if node[0][0] == token.STRING:
1250 s = ''
1251 for t in node:
1252 s = s + eval(t[1])
1253 return s
1254 return None
1255 if n == symbol.stmt or n == symbol.simple_stmt or n == symbol.small_stmt:
1256 return self.get_docstring(node[0])
1257 if n in _doc_nodes and len(node) == 1:
1258 return self.get_docstring(node[0])
1259 return None
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001260
1261
1262_doc_nodes = [
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001263 symbol.expr_stmt,
1264 symbol.testlist,
1265 symbol.test,
1266 symbol.and_test,
1267 symbol.not_test,
1268 symbol.comparison,
1269 symbol.expr,
1270 symbol.xor_expr,
1271 symbol.and_expr,
1272 symbol.shift_expr,
1273 symbol.arith_expr,
1274 symbol.term,
1275 symbol.factor,
1276 symbol.power,
1277 ]
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001278
1279# comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '=='
1280# | 'in' | 'not' 'in' | 'is' | 'is' 'not'
1281_cmp_types = {
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001282 token.LESS : '<',
1283 token.GREATER : '>',
1284 token.EQEQUAL : '==',
1285 token.EQUAL : '==',
1286 token.LESSEQUAL : '<=',
1287 token.GREATEREQUAL : '>=',
1288 token.NOTEQUAL : '!=',
1289 }
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001290
1291_legal_node_types = [
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001292 symbol.funcdef,
1293 symbol.classdef,
1294 symbol.stmt,
1295 symbol.small_stmt,
1296 symbol.flow_stmt,
1297 symbol.simple_stmt,
1298 symbol.compound_stmt,
1299 symbol.expr_stmt,
1300 symbol.print_stmt,
1301 symbol.del_stmt,
1302 symbol.pass_stmt,
1303 symbol.break_stmt,
1304 symbol.continue_stmt,
1305 symbol.return_stmt,
1306 symbol.raise_stmt,
1307 symbol.import_stmt,
1308 symbol.global_stmt,
1309 symbol.exec_stmt,
1310 symbol.assert_stmt,
1311 symbol.if_stmt,
1312 symbol.while_stmt,
1313 symbol.for_stmt,
1314 symbol.try_stmt,
1315 symbol.suite,
1316 symbol.testlist,
1317 symbol.test,
1318 symbol.and_test,
1319 symbol.not_test,
1320 symbol.comparison,
1321 symbol.exprlist,
1322 symbol.expr,
1323 symbol.xor_expr,
1324 symbol.and_expr,
1325 symbol.shift_expr,
1326 symbol.arith_expr,
1327 symbol.term,
1328 symbol.factor,
1329 symbol.power,
1330 symbol.atom,
1331 ]
Jeremy Hyltonf968e852000-02-04 00:25:23 +00001332
1333_assign_types = [
Jeremy Hylton572bdce2000-09-20 02:47:28 +00001334 symbol.test,
1335 symbol.and_test,
1336 symbol.not_test,
1337 symbol.comparison,
1338 symbol.expr,
1339 symbol.xor_expr,
1340 symbol.and_expr,
1341 symbol.shift_expr,
1342 symbol.arith_expr,
1343 symbol.term,
1344 symbol.factor,
1345 ]
Jeremy Hylton9c048f92000-10-13 21:58:13 +00001346
1347import types
1348_names = {}
1349for k, v in symbol.sym_name.items():
1350 _names[k] = v
1351for k, v in token.tok_name.items():
1352 _names[k] = v
1353
1354def debug_tree(tree):
1355 l = []
1356 for elt in tree:
1357 if type(elt) == types.IntType:
1358 l.append(_names.get(elt, elt))
1359 elif type(elt) == types.StringType:
1360 l.append(elt)
1361 else:
1362 l.append(debug_tree(elt))
1363 return l