Undo botched api -> pxd
[cython.git] / Cython / Compiler / Parsing.py
1 #
2 #   Pyrex Parser
3 #
4
5 import os, re
6 from string import join, replace
7 from types import ListType, TupleType
8 from Scanning import PyrexScanner
9 import Nodes
10 import ExprNodes
11 from ModuleNode import ModuleNode
12 from Errors import error, InternalError
13
14 def p_ident(s, message = "Expected an identifier"):
15     if s.sy == 'IDENT':
16         name = s.systring
17         s.next()
18         return name
19     else:
20         s.error(message)
21
22 def p_ident_list(s):
23     names = []
24     while s.sy == 'IDENT':
25         names.append(s.systring)
26         s.next()
27         if s.sy <> ',':
28             break
29         s.next()
30     return names
31
32 #------------------------------------------
33 #
34 #   Expressions
35 #
36 #------------------------------------------
37
38 def p_binop_expr(s, ops, p_sub_expr):
39     #print "p_binop_expr:", ops, p_sub_expr ###
40     n1 = p_sub_expr(s)
41     #print "p_binop_expr(%s):" % p_sub_expr, s.sy ###
42     while s.sy in ops:
43         op = s.sy
44         pos = s.position()
45         s.next()
46         n2 = p_sub_expr(s)
47         n1 = ExprNodes.binop_node(pos, op, n1, n2)
48     return n1
49
50 #expression: or_test [if or_test else test] | lambda_form
51
52 def p_simple_expr(s):
53     pos = s.position()
54     expr = p_or_test(s)
55     if s.sy == 'if':
56         s.next()
57         test = p_or_test(s)
58         if s.sy == 'else':
59             s.next()
60             other = p_test(s)
61             return ExprNodes.CondExprNode(pos, test=test, true_val=expr, false_val=other)
62         else:
63             s.error("Expected 'else'")
64     else:
65         return expr
66         
67 #test: or_test | lambda_form
68         
69 def p_test(s):
70     return p_or_test(s)
71
72 #or_test: and_test ('or' and_test)*
73
74 def p_or_test(s):
75     #return p_binop_expr(s, ('or',), p_and_test)
76     return p_rassoc_binop_expr(s, ('or',), p_and_test)
77
78 def p_rassoc_binop_expr(s, ops, p_subexpr):
79     n1 = p_subexpr(s)
80     if s.sy in ops:
81         pos = s.position()
82         op = s.sy
83         s.next()
84         n2 = p_rassoc_binop_expr(s, ops, p_subexpr)
85         n1 = ExprNodes.binop_node(pos, op, n1, n2)
86     return n1
87
88 #and_test: not_test ('and' not_test)*
89
90 def p_and_test(s):
91     #return p_binop_expr(s, ('and',), p_not_test)
92     return p_rassoc_binop_expr(s, ('and',), p_not_test)
93
94 #not_test: 'not' not_test | comparison
95
96 def p_not_test(s):
97     if s.sy == 'not':
98         pos = s.position()
99         s.next()
100         return ExprNodes.NotNode(pos, operand = p_not_test(s))
101     else:
102         return p_comparison(s)
103
104 #comparison: expr (comp_op expr)*
105 #comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
106
107 def p_comparison(s):
108     n1 = p_bit_expr(s)
109     if s.sy in comparison_ops:
110         pos = s.position()
111         op = p_cmp_op(s)
112         n2 = p_bit_expr(s)
113         n1 = ExprNodes.PrimaryCmpNode(pos, 
114             operator = op, operand1 = n1, operand2 = n2)
115         if s.sy in comparison_ops:
116             n1.cascade = p_cascaded_cmp(s)
117     return n1
118
119 def p_cascaded_cmp(s):
120     pos = s.position()
121     op = p_cmp_op(s)
122     n2 = p_bit_expr(s)
123     result = ExprNodes.CascadedCmpNode(pos, 
124         operator = op, operand2 = n2)
125     if s.sy in comparison_ops:
126         result.cascade = p_cascaded_cmp(s)
127     return result
128
129 def p_cmp_op(s):
130     if s.sy == 'not':
131         s.next()
132         s.expect('in')
133         op = 'not_in'
134     elif s.sy == 'is':
135         s.next()
136         if s.sy == 'not':
137             s.next()
138             op = 'is_not'
139         else:
140             op = 'is'
141     else:
142         op = s.sy
143         s.next()
144     if op == '<>':
145         op = '!='
146     return op
147     
148 comparison_ops = (
149     '<', '>', '==', '>=', '<=', '<>', '!=', 
150     'in', 'is', 'not'
151 )
152
153 #expr: xor_expr ('|' xor_expr)*
154
155 def p_bit_expr(s):
156     return p_binop_expr(s, ('|',), p_xor_expr)
157
158 #xor_expr: and_expr ('^' and_expr)*
159
160 def p_xor_expr(s):
161     return p_binop_expr(s, ('^',), p_and_expr)
162
163 #and_expr: shift_expr ('&' shift_expr)*
164
165 def p_and_expr(s):
166     return p_binop_expr(s, ('&',), p_shift_expr)
167
168 #shift_expr: arith_expr (('<<'|'>>') arith_expr)*
169
170 def p_shift_expr(s):
171     return p_binop_expr(s, ('<<', '>>'), p_arith_expr)
172
173 #arith_expr: term (('+'|'-') term)*
174
175 def p_arith_expr(s):
176     return p_binop_expr(s, ('+', '-'), p_term)
177
178 #term: factor (('*'|'/'|'%') factor)*
179
180 def p_term(s):
181     return p_binop_expr(s, ('*', '/', '%', '//'), p_factor)
182
183 #factor: ('+'|'-'|'~'|'&'|typecast|sizeof) factor | power
184
185 def p_factor(s):
186     sy = s.sy
187     if sy in ('+', '-', '~'):
188         op = s.sy
189         pos = s.position()
190         s.next()
191         return ExprNodes.unop_node(pos, op, p_factor(s))
192     elif sy == '&':
193         pos = s.position()
194         s.next()
195         arg = p_factor(s)
196         return ExprNodes.AmpersandNode(pos, operand = arg)
197     elif sy == "<":
198         return p_typecast(s)
199     elif sy == 'IDENT' and s.systring == "sizeof":
200         return p_sizeof(s)
201     else:
202         return p_power(s)
203
204 def p_typecast(s):
205     # s.sy == "<"
206     pos = s.position()
207     s.next()
208     base_type = p_c_base_type(s)
209     declarator = p_c_declarator(s, empty = 1)
210     if s.sy == '?':
211         s.next()
212         typecheck = 1
213     else:
214         typecheck = 0
215     s.expect(">")
216     operand = p_factor(s)
217     return ExprNodes.TypecastNode(pos, 
218         base_type = base_type, 
219         declarator = declarator,
220         operand = operand,
221         typecheck = typecheck)
222
223 def p_sizeof(s):
224     # s.sy == ident "sizeof"
225     pos = s.position()
226     s.next()
227     s.expect('(')
228     if looking_at_type(s) or looking_at_dotted_name(s):
229         base_type = p_c_base_type(s)
230         declarator = p_c_declarator(s, empty = 1)
231         node = ExprNodes.SizeofTypeNode(pos, 
232             base_type = base_type, declarator = declarator)
233     else:
234         operand = p_simple_expr(s)
235         node = ExprNodes.SizeofVarNode(pos, operand = operand)
236     s.expect(')')
237     return node
238
239 #power: atom trailer* ('**' factor)*
240
241 def p_power(s):
242     n1 = p_atom(s)
243     while s.sy in ('(', '[', '.'):
244         n1 = p_trailer(s, n1)
245     if s.sy == '**':
246         pos = s.position()
247         s.next()
248         n2 = p_factor(s)
249         n1 = ExprNodes.binop_node(pos, '**', n1, n2)
250     return n1
251
252 #trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
253
254 def p_trailer(s, node1):
255     pos = s.position()
256     if s.sy == '(':
257         return p_call(s, node1)
258     elif s.sy == '[':
259         return p_index(s, node1)
260     else: # s.sy == '.'
261         s.next()
262         name = p_ident(s)
263         return ExprNodes.AttributeNode(pos, 
264             obj = node1, attribute = name)
265
266 # arglist:  argument (',' argument)* [',']
267 # argument: [test '='] test       # Really [keyword '='] test
268
269 def p_call(s, function):
270     # s.sy == '('
271     pos = s.position()
272     s.next()
273     positional_args = []
274     keyword_args = []
275     star_arg = None
276     starstar_arg = None
277     while s.sy not in ('*', '**', ')'):
278         arg = p_simple_expr(s)
279         if s.sy == '=':
280             s.next()
281             if not arg.is_name:
282                 s.error("Expected an identifier before '='",
283                     pos = arg.pos)
284             keyword = ExprNodes.StringNode(arg.pos, 
285                 value = arg.name)
286             arg = p_simple_expr(s)
287             keyword_args.append((keyword, arg))
288         else:
289             if keyword_args:
290                 s.error("Non-keyword arg following keyword arg",
291                     pos = arg.pos)
292             positional_args.append(arg)
293         if s.sy <> ',':
294             break
295         s.next()
296     if s.sy == '*':
297         s.next()
298         star_arg = p_simple_expr(s)
299         if s.sy == ',':
300             s.next()
301     if s.sy == '**':
302         s.next()
303         starstar_arg = p_simple_expr(s)
304         if s.sy == ',':
305             s.next()
306     s.expect(')')
307     if not (keyword_args or star_arg or starstar_arg):
308         return ExprNodes.SimpleCallNode(pos,
309             function = function,
310             args = positional_args)
311     else:
312         arg_tuple = None
313         keyword_dict = None
314         if positional_args or not star_arg:
315             arg_tuple = ExprNodes.TupleNode(pos, 
316                 args = positional_args)
317         if star_arg:
318             star_arg_tuple = ExprNodes.AsTupleNode(pos, arg = star_arg)
319             if arg_tuple:
320                 arg_tuple = ExprNodes.binop_node(pos, 
321                     operator = '+', operand1 = arg_tuple,
322                     operand2 = star_arg_tuple)
323             else:
324                 arg_tuple = star_arg_tuple
325         if keyword_args:
326             keyword_dict = ExprNodes.DictNode(pos,
327                 key_value_pairs = keyword_args)
328         return ExprNodes.GeneralCallNode(pos, 
329             function = function,
330             positional_args = arg_tuple,
331             keyword_args = keyword_dict,
332             starstar_arg = starstar_arg)
333
334 #lambdef: 'lambda' [varargslist] ':' test
335
336 #subscriptlist: subscript (',' subscript)* [',']
337
338 def p_index(s, base):
339     # s.sy == '['
340     pos = s.position()
341     s.next()
342     subscripts = p_subscript_list(s)
343     if len(subscripts) == 1 and len(subscripts[0]) == 2:
344         start, stop = subscripts[0]
345         result = ExprNodes.SliceIndexNode(pos, 
346             base = base, start = start, stop = stop)
347     else:
348         indexes = make_slice_nodes(pos, subscripts)
349         if len(indexes) == 1:
350             index = indexes[0]
351         else:
352             index = ExprNodes.TupleNode(pos, args = indexes)
353         result = ExprNodes.IndexNode(pos,
354             base = base, index = index)
355     s.expect(']')
356     return result
357
358 def p_subscript_list(s):
359     items = [p_subscript(s)]
360     while s.sy == ',':
361         s.next()
362         if s.sy == ']':
363             break
364         items.append(p_subscript(s))
365     return items
366
367 #subscript: '.' '.' '.' | test | [test] ':' [test] [':' [test]]
368
369 def p_subscript(s):
370     # Parse a subscript and return a list of
371     # 1, 2 or 3 ExprNodes, depending on how
372     # many slice elements were encountered.
373     pos = s.position()
374     if s.sy == '.':
375         expect_ellipsis(s)
376         return [ExprNodes.EllipsisNode(pos)]
377     else:
378         start = p_slice_element(s, (':',))
379         if s.sy <> ':':
380             return [start]
381         s.next()
382         stop = p_slice_element(s, (':', ',', ']'))
383         if s.sy <> ':':
384             return [start, stop]
385         s.next()
386         step = p_slice_element(s, (':', ',', ']'))
387         return [start, stop, step]
388
389 def p_slice_element(s, follow_set):
390     # Simple expression which may be missing iff
391     # it is followed by something in follow_set.
392     if s.sy not in follow_set:
393         return p_simple_expr(s)
394     else:
395         return None
396
397 def expect_ellipsis(s):
398     s.expect('.')
399     s.expect('.')
400     s.expect('.')
401
402 def make_slice_nodes(pos, subscripts):
403     # Convert a list of subscripts as returned
404     # by p_subscript_list into a list of ExprNodes,
405     # creating SliceNodes for elements with 2 or
406     # more components.
407     result = []
408     for subscript in subscripts:
409         if len(subscript) == 1:
410             result.append(subscript[0])
411         else:
412             result.append(make_slice_node(pos, *subscript))
413     return result
414
415 def make_slice_node(pos, start, stop = None, step = None):
416     if not start:
417         start = ExprNodes.NoneNode(pos)
418     if not stop:
419         stop = ExprNodes.NoneNode(pos)
420     if not step:
421         step = ExprNodes.NoneNode(pos)
422     return ExprNodes.SliceNode(pos,
423         start = start, stop = stop, step = step)
424
425 #atom: '(' [testlist] ')' | '[' [listmaker] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+
426
427 def p_atom(s):
428     pos = s.position()
429     sy = s.sy
430     if sy == '(':
431         s.next()
432         if s.sy == ')':
433             result = ExprNodes.TupleNode(pos, args = [])
434         else:
435             result = p_expr(s)
436         s.expect(')')
437         return result
438     elif sy == '[':
439         return p_list_maker(s)
440     elif sy == '{':
441         return p_dict_maker(s)
442     elif sy == '`':
443         return p_backquote_expr(s)
444     elif sy == 'INT':
445         value = s.systring
446         s.next()
447         return ExprNodes.IntNode(pos, value = value)
448     elif sy == 'LONG':
449         value = s.systring
450         s.next()
451         return ExprNodes.LongNode(pos, value = value)
452     elif sy == 'FLOAT':
453         value = s.systring
454         s.next()
455         return ExprNodes.FloatNode(pos, value = value)
456     elif sy == 'IMAG':
457         value = s.systring[:-1]
458         s.next()
459         return ExprNodes.ImagNode(pos, value = value)
460     elif sy == 'STRING' or sy == 'BEGIN_STRING':
461         kind, value = p_cat_string_literal(s)
462         if kind == 'c':
463             return ExprNodes.CharNode(pos, value = value)
464         else:
465             return ExprNodes.StringNode(pos, value = value)
466     elif sy == 'IDENT':
467         name = s.systring
468         s.next()
469         if name == "None":
470             return ExprNodes.NoneNode(pos)
471         elif name == "True":
472             return ExprNodes.BoolNode(pos, value=1)
473         elif name == "False":
474             return ExprNodes.BoolNode(pos, value=0)
475         else:
476             return p_name(s, name)
477     elif sy == 'NULL':
478         s.next()
479         return ExprNodes.NullNode(pos)
480     else:
481         s.error("Expected an identifier or literal")
482
483 def p_name(s, name):
484     pos = s.position()
485     if not s.compile_time_expr:
486         try:
487             value = s.compile_time_env.lookup_here(name)
488         except KeyError:
489             pass
490         else:
491             rep = repr(value)
492             if isinstance(value, int):
493                 return ExprNodes.IntNode(pos, value = rep)
494             elif isinstance(value, long):
495                 return ExprNodes.LongNode(pos, value = rep)
496             elif isinstance(value, float):
497                 return ExprNodes.FloatNode(pos, value = rep)
498             elif isinstance(value, str):
499                 return ExprNodes.StringNode(pos, value = rep[1:-1])
500             else:
501                 error(pos, "Invalid type for compile-time constant: %s"
502                     % value.__class__.__name__)
503     return ExprNodes.NameNode(pos, name = name)
504
505 def p_cat_string_literal(s):
506     # A sequence of one or more adjacent string literals.
507     # Returns (kind, value) where kind in ('', 'c', 'r')
508     kind, value = p_string_literal(s)
509     if kind <> 'c':
510         strings = [value]
511         while s.sy == 'STRING' or s.sy == 'BEGIN_STRING':
512             next_kind, next_value = p_string_literal(s)
513             if next_kind == 'c':
514                 self.error(
515                     "Cannot concatenate char literal with another string or char literal")
516             strings.append(next_value)
517         value = ''.join(strings)
518     return kind, value
519
520 def p_opt_string_literal(s):
521     if s.sy == 'STRING' or s.sy == 'BEGIN_STRING':
522         return p_string_literal(s)
523     else:
524         return None
525
526 def p_string_literal(s):
527     # A single string or char literal.
528     # Returns (kind, value) where kind in ('', 'c', 'r', 'u')
529     if s.sy == 'STRING':
530         value = unquote(s.systring)
531         s.next()
532         return value
533     # s.sy == 'BEGIN_STRING'
534     pos = s.position()
535     #is_raw = s.systring[:1].lower() == "r"
536     kind = s.systring[:1].lower()
537     if kind not in "cru":
538         kind = ''
539     chars = []
540     while 1:
541         s.next()
542         sy = s.sy
543         #print "p_string_literal: sy =", sy, repr(s.systring) ###
544         if sy == 'CHARS':
545             systr = s.systring
546             if len(systr) == 1 and systr in "'\"\n":
547                 chars.append('\\')
548             if kind == 'u' and not isinstance(systr, unicode):
549                 systr = systr.decode("UTF-8")
550             chars.append(systr)
551         elif sy == 'ESCAPE':
552             systr = s.systring
553             if kind == 'r':
554                 if systr == '\\\n':
555                     chars.append(r'\\\n')
556                 elif systr == r'\"':
557                     chars.append(r'\\\"')
558                 elif systr == r'\\':
559                     chars.append(r'\\\\')
560                 else:
561                     chars.append('\\' + systr)
562             else:
563                 c = systr[1]
564                 if c in "'\"\\abfnrtv01234567":
565                     chars.append(systr)
566                 elif c == 'x':
567                     chars.append('\\x0' + systr[2:])
568                 elif c == '\n':
569                     pass
570                 elif c == 'u':
571                     chars.append(systr)
572                 else:
573                     chars.append(r'\\' + systr[1:])
574         elif sy == 'NEWLINE':
575             chars.append(r'\n')
576         elif sy == 'END_STRING':
577             break
578         elif sy == 'EOF':
579             s.error("Unclosed string literal", pos = pos)
580         else:
581             s.error(
582                 "Unexpected token %r:%r in string literal" %
583                     (sy, s.systring))
584     s.next()
585     if kind == 'u':
586         value = u''.join(chars)
587     else:
588         value = ''.join(chars)
589     #print "p_string_literal: value =", repr(value) ###
590     return kind, value
591
592 def unquote(s):
593     is_raw = 0
594     if s[:1].lower() == "r":
595         is_raw = 1
596         s = s[1:]
597     q = s[:3]
598     if q == '"""' or q == "'''":
599         s = s[3:-3]
600     else:
601         s = s[1:-1]
602     if is_raw:
603         s = s.replace('\\', '\\\\')
604         s = s.replace('\n', '\\\n')
605     else:
606         # Split into double quotes, newlines, escape sequences 
607         # and spans of regular chars
608         l1 = re.split(r'((?:\\[0-7]{1,3})|(?:\\x[0-9A-Fa-f]{2})|(?:\\.)|(?:\\\n)|(?:\n)|")', s)
609         print "unquote: l1 =", l1 ###
610         l2 = []
611         for item in l1:
612             if item == '"' or item == '\n':
613                 l2.append('\\' + item)
614             elif item == '\\\n':
615                 pass
616             elif item[:1] == '\\':
617                 if len(item) == 2:
618                     if item[1] in '"\\abfnrtv':
619                         l2.append(item)
620                     else:
621                         l2.append(item[1])
622                 elif item[1:2] == 'x':
623                     l2.append('\\x0' + item[2:])
624                 else:
625                     # octal escape
626                     l2.append(item)
627             else:
628                 l2.append(item)
629         s = "".join(l2)
630     return s
631         
632 # list_display          ::=     "[" [listmaker] "]"
633 # listmaker     ::=     expression ( list_for | ( "," expression )* [","] )
634 # list_iter     ::=     list_for | list_if
635 # list_for      ::=     "for" expression_list "in" testlist [list_iter]
636 # list_if       ::=     "if" test [list_iter]
637         
638 def p_list_maker(s):
639     # s.sy == '['
640     pos = s.position()
641     s.next()
642     if s.sy == ']':
643         s.expect(']')
644         return ExprNodes.ListNode(pos, args = [])
645     expr = p_simple_expr(s)
646     if s.sy == 'for':
647         loop = p_list_for(s)
648         s.expect(']')
649         inner_loop = loop
650         while not isinstance(inner_loop.body, Nodes.PassStatNode):
651             inner_loop = inner_loop.body
652             if isinstance(inner_loop, Nodes.IfStatNode):
653                  inner_loop = inner_loop.if_clauses[0]
654         append = ExprNodes.ListComprehensionAppendNode( pos, expr = expr )
655         inner_loop.body = Nodes.ExprStatNode(pos, expr = append)
656         return ExprNodes.ListComprehensionNode(pos, loop = loop, append = append)
657     else:
658         exprs = [expr]
659         if s.sy == ',':
660             s.next()
661             exprs += p_simple_expr_list(s)
662         s.expect(']')
663         return ExprNodes.ListNode(pos, args = exprs)
664         
665 def p_list_iter(s):
666     if s.sy == 'for':
667         return p_list_for(s)
668     elif s.sy == 'if':
669         return p_list_if(s)
670     else:
671         return Nodes.PassStatNode(s.position())
672
673 def p_list_for(s):
674     # s.sy == 'for'
675     pos = s.position()
676     s.next()
677     kw = p_for_bounds(s)
678     kw['else_clause'] = None
679     kw['body'] = p_list_iter(s)
680     return Nodes.ForStatNode(pos, **kw)
681         
682 def p_list_if(s):
683     # s.sy == 'if'
684     pos = s.position()
685     s.next()
686     test = p_test(s)
687     return Nodes.IfStatNode(pos, 
688         if_clauses = [Nodes.IfClauseNode(pos, condition = test, body = p_list_iter(s))],
689         else_clause = None )
690     
691 #dictmaker: test ':' test (',' test ':' test)* [',']
692
693 def p_dict_maker(s):
694     # s.sy == '{'
695     pos = s.position()
696     s.next()
697     items = []
698     while s.sy <> '}':
699         key = p_simple_expr(s)
700         s.expect(':')
701         value = p_simple_expr(s)
702         items.append((key, value))
703         if s.sy <> ',':
704             break
705         s.next()
706     s.expect('}')
707     return ExprNodes.DictNode(pos, key_value_pairs = items)
708
709 def p_backquote_expr(s):
710     # s.sy == '`'
711     pos = s.position()
712     s.next()
713     arg = p_expr(s)
714     s.expect('`')
715     return ExprNodes.BackquoteNode(pos, arg = arg)
716
717 def p_simple_expr_list(s):
718     exprs = []
719     while s.sy not in expr_terminators:
720         exprs.append(p_simple_expr(s))
721         if s.sy <> ',':
722             break
723         s.next()
724     return exprs
725
726 def p_expr(s):
727     pos = s.position()
728     expr = p_simple_expr(s)
729     if s.sy == ',':
730         s.next()
731         exprs = [expr] + p_simple_expr_list(s)
732         return ExprNodes.TupleNode(pos, args = exprs)
733     else:
734         return expr
735
736
737 #testlist: test (',' test)* [',']
738 # differs from p_expr only in the fact that it cannot contain conditional expressions
739
740 def p_testlist(s):
741     pos = s.position()
742     expr = p_test(s)
743     if s.sy == ',':
744         exprs = [expr]
745         while s.sy == ',':
746             s.next()
747             exprs.append(p_test(s))
748         return ExprNodes.TupleNode(pos, args = exprs)
749     else:
750         return expr
751         
752 expr_terminators = (')', ']', '}', ':', '=', 'NEWLINE')
753
754 #-------------------------------------------------------
755 #
756 #   Statements
757 #
758 #-------------------------------------------------------
759
760 def p_global_statement(s):
761     # assume s.sy == 'global'
762     pos = s.position()
763     s.next()
764     names = p_ident_list(s)
765     return Nodes.GlobalNode(pos, names = names)
766
767 def p_expression_or_assignment(s):
768     expr_list = [p_expr(s)]
769     while s.sy == '=':
770         s.next()
771         expr_list.append(p_expr(s))
772     if len(expr_list) == 1:
773         if re.match("[+*/\%^\&|-]=", s.sy):
774             lhs = expr_list[0]
775             if not isinstance(lhs, (ExprNodes.AttributeNode, ExprNodes.IndexNode, ExprNodes.NameNode) ):
776                 error(lhs.pos, "Illegal operand for inplace operation.")
777             operator = s.sy[0]
778             s.next()
779             rhs = p_expr(s)
780             return Nodes.InPlaceAssignmentNode(lhs.pos, operator = operator, lhs = lhs, rhs = rhs)
781         expr = expr_list[0]
782         if isinstance(expr, ExprNodes.StringNode):
783             return Nodes.PassStatNode(expr.pos)
784         else:
785             return Nodes.ExprStatNode(expr.pos, expr = expr)
786     else:
787         expr_list_list = []
788         flatten_parallel_assignments(expr_list, expr_list_list)
789         nodes = []
790         for expr_list in expr_list_list:
791             lhs_list = expr_list[:-1]
792             rhs = expr_list[-1]
793             if len(lhs_list) == 1:
794                 node = Nodes.SingleAssignmentNode(rhs.pos, 
795                     lhs = lhs_list[0], rhs = rhs)
796             else:
797                 node = Nodes.CascadedAssignmentNode(rhs.pos,
798                     lhs_list = lhs_list, rhs = rhs)
799             nodes.append(node)
800         if len(nodes) == 1:
801             return nodes[0]
802         else:
803             return Nodes.ParallelAssignmentNode(nodes[0].pos, stats = nodes)
804
805 def flatten_parallel_assignments(input, output):
806     #  The input is a list of expression nodes, representing 
807     #  the LHSs and RHS of one (possibly cascaded) assignment 
808     #  statement. If they are all sequence constructors with 
809     #  the same number of arguments, rearranges them into a
810     #  list of equivalent assignments between the individual 
811     #  elements. This transformation is applied recursively.
812     size = find_parallel_assignment_size(input)
813     if size >= 0:
814         for i in range(size):
815             new_exprs = [expr.args[i] for expr in input]
816             flatten_parallel_assignments(new_exprs, output)
817     else:
818         output.append(input)
819
820 def find_parallel_assignment_size(input):
821     #  The input is a list of expression nodes. If 
822     #  they are all sequence constructors with the same number
823     #  of arguments, return that number, else return -1.
824     #  Produces an error message if they are all sequence
825     #  constructors but not all the same size.
826     for expr in input:
827         if not expr.is_sequence_constructor:
828             return -1
829     rhs = input[-1]
830     rhs_size = len(rhs.args)
831     for lhs in input[:-1]:
832         lhs_size = len(lhs.args)
833         if lhs_size <> rhs_size:
834             error(lhs.pos, "Unpacking sequence of wrong size (expected %d, got %d)"
835                 % (lhs_size, rhs_size))
836             return -1
837     return rhs_size
838
839 def p_print_statement(s):
840     # s.sy == 'print'
841     pos = s.position()
842     s.next()
843     if s.sy == '>>':
844         s.error("'print >>' not yet implemented")
845     args = []
846     ewc = 0
847     if s.sy not in ('NEWLINE', 'EOF'):
848         args.append(p_simple_expr(s))
849         while s.sy == ',':
850             s.next()
851             if s.sy in ('NEWLINE', 'EOF'):
852                 ewc = 1
853                 break
854             args.append(p_simple_expr(s))
855     return Nodes.PrintStatNode(pos, 
856         args = args, ends_with_comma = ewc)
857
858 def p_del_statement(s):
859     # s.sy == 'del'
860     pos = s.position()
861     s.next()
862     args = p_simple_expr_list(s)
863     return Nodes.DelStatNode(pos, args = args)
864
865 def p_pass_statement(s, with_newline = 0):
866     pos = s.position()
867     s.expect('pass')
868     if with_newline:
869         s.expect_newline("Expected a newline")
870     return Nodes.PassStatNode(pos)
871
872 def p_break_statement(s):
873     # s.sy == 'break'
874     pos = s.position()
875     s.next()
876     return Nodes.BreakStatNode(pos)
877
878 def p_continue_statement(s):
879     # s.sy == 'continue'
880     pos = s.position()
881     s.next()
882     return Nodes.ContinueStatNode(pos)
883
884 def p_return_statement(s):
885     # s.sy == 'return'
886     pos = s.position()
887     s.next()
888     if s.sy not in statement_terminators:
889         value = p_expr(s)
890     else:
891         value = None
892     return Nodes.ReturnStatNode(pos, value = value)
893
894 def p_raise_statement(s):
895     # s.sy == 'raise'
896     pos = s.position()
897     s.next()
898     exc_type = None
899     exc_value = None
900     exc_tb = None
901     if s.sy not in statement_terminators:
902         exc_type = p_simple_expr(s)
903         if s.sy == ',':
904             s.next()
905             exc_value = p_simple_expr(s)
906             if s.sy == ',':
907                 s.next()
908                 exc_tb = p_simple_expr(s)
909     if exc_type or exc_value or exc_tb:
910         return Nodes.RaiseStatNode(pos, 
911             exc_type = exc_type,
912             exc_value = exc_value,
913             exc_tb = exc_tb)
914     else:
915         return Nodes.ReraiseStatNode(pos)
916
917 def p_import_statement(s):
918     # s.sy in ('import', 'cimport')
919     pos = s.position()
920     kind = s.sy
921     s.next()
922     items = [p_dotted_name(s, as_allowed = 1)]
923     while s.sy == ',':
924         s.next()
925         items.append(p_dotted_name(s, as_allowed = 1))
926     stats = []
927     for pos, target_name, dotted_name, as_name in items:
928         if kind == 'cimport':
929             stat = Nodes.CImportStatNode(pos, 
930                 module_name = dotted_name,
931                 as_name = as_name)
932         else:
933             if as_name and "." in dotted_name:
934                 name_list = ExprNodes.ListNode(pos, args = [
935                     ExprNodes.StringNode(pos, value = "*")])
936             else:
937                 name_list = None
938             stat = Nodes.SingleAssignmentNode(pos,
939                 lhs = ExprNodes.NameNode(pos, 
940                     name = as_name or target_name),
941                 rhs = ExprNodes.ImportNode(pos, 
942                     module_name = ExprNodes.StringNode(pos,
943                         value = dotted_name),
944                     name_list = name_list))
945         stats.append(stat)
946     return Nodes.StatListNode(pos, stats = stats)
947
948 def p_from_import_statement(s):
949     # s.sy == 'from'
950     pos = s.position()
951     s.next()
952     (dotted_name_pos, _, dotted_name, _) = \
953         p_dotted_name(s, as_allowed = 0)
954     if s.sy in ('import', 'cimport'):
955         kind = s.sy
956         s.next()
957     else:
958         s.error("Expected 'import' or 'cimport'")
959     if s.sy == '*':
960         s.error("'import *' not supported")
961     imported_names = [p_imported_name(s)]
962     while s.sy == ',':
963         s.next()
964         imported_names.append(p_imported_name(s))
965     if kind == 'cimport':
966         for (name_pos, name, as_name) in imported_names:
967             local_name = as_name or name
968             s.add_type_name(local_name)
969         return Nodes.FromCImportStatNode(pos,
970             module_name = dotted_name,
971             imported_names = imported_names)
972     else:
973         imported_name_strings = []
974         items = []
975         for (name_pos, name, as_name) in imported_names:
976             imported_name_strings.append(
977                 ExprNodes.StringNode(name_pos, value = name))
978             items.append(
979                 (name,
980                  ExprNodes.NameNode(name_pos, 
981                         name = as_name or name)))
982         import_list = ExprNodes.ListNode(
983             imported_names[0][0], args = imported_name_strings)
984         return Nodes.FromImportStatNode(pos,
985             module = ExprNodes.ImportNode(dotted_name_pos,
986                 module_name = ExprNodes.StringNode(dotted_name_pos,
987                     value = dotted_name),
988                 name_list = import_list),
989             items = items)
990
991 def p_imported_name(s):
992     pos = s.position()
993     name = p_ident(s)
994     as_name = p_as_name(s)
995     return (pos, name, as_name)
996
997 def p_dotted_name(s, as_allowed):
998     pos = s.position()
999     target_name = p_ident(s)
1000     as_name = None
1001     names = [target_name]
1002     while s.sy == '.':
1003         s.next()
1004         names.append(p_ident(s))
1005     if as_allowed:
1006         as_name = p_as_name(s)
1007     return (pos, target_name, join(names, "."), as_name)
1008
1009 def p_as_name(s):
1010     if s.sy == 'IDENT' and s.systring == 'as':
1011         s.next()
1012         return p_ident(s)
1013     else:
1014         return None
1015
1016 def p_assert_statement(s):
1017     # s.sy == 'assert'
1018     pos = s.position()
1019     s.next()
1020     cond = p_simple_expr(s)
1021     if s.sy == ',':
1022         s.next()
1023         value = p_simple_expr(s)
1024     else:
1025         value = None
1026     return Nodes.AssertStatNode(pos, cond = cond, value = value)
1027
1028 statement_terminators = (';', 'NEWLINE', 'EOF')
1029
1030 def p_if_statement(s):
1031     # s.sy == 'if'
1032     pos = s.position()
1033     s.next()
1034     if_clauses = [p_if_clause(s)]
1035     while s.sy == 'elif':
1036         s.next()
1037         if_clauses.append(p_if_clause(s))
1038     else_clause = p_else_clause(s)
1039     return Nodes.IfStatNode(pos,
1040         if_clauses = if_clauses, else_clause = else_clause)
1041
1042 def p_if_clause(s):
1043     pos = s.position()
1044     test = p_simple_expr(s)
1045     body = p_suite(s)
1046     return Nodes.IfClauseNode(pos,
1047         condition = test, body = body)
1048
1049 def p_else_clause(s):
1050     if s.sy == 'else':
1051         s.next()
1052         return p_suite(s)
1053     else:
1054         return None
1055
1056 def p_while_statement(s):
1057     # s.sy == 'while'
1058     pos = s.position()
1059     s.next()
1060     test = p_simple_expr(s)
1061     body = p_suite(s)
1062     else_clause = p_else_clause(s)
1063     return Nodes.WhileStatNode(pos, 
1064         condition = test, body = body, 
1065         else_clause = else_clause)
1066
1067 def p_for_statement(s):
1068     # s.sy == 'for'
1069     pos = s.position()
1070     s.next()
1071     kw = p_for_bounds(s)
1072     kw['body'] = p_suite(s)
1073     kw['else_clause'] = p_else_clause(s)
1074     return Nodes.ForStatNode(pos, **kw)
1075             
1076 def p_for_bounds(s):
1077     target = p_for_target(s)
1078     if s.sy == 'in':
1079         s.next()
1080         iterator = p_for_iterator(s)
1081         return { 'target': target, 'iterator': iterator }
1082     elif s.sy == 'from':
1083         s.next()
1084         bound1 = p_bit_expr(s)
1085         rel1 = p_for_from_relation(s)
1086         name2_pos = s.position()
1087         name2 = p_ident(s)
1088         rel2_pos = s.position()
1089         rel2 = p_for_from_relation(s)
1090         bound2 = p_bit_expr(s)
1091         step = p_for_from_step(s)
1092         if not target.is_name:
1093             error(target.pos, 
1094                 "Target of for-from statement must be a variable name")
1095         elif name2 <> target.name:
1096             error(name2_pos,
1097                 "Variable name in for-from range does not match target")
1098         if rel1[0] <> rel2[0]:
1099             error(rel2_pos,
1100                 "Relation directions in for-from do not match")
1101         return {'target': target, 
1102                 'bound1': bound1, 
1103                 'relation1': rel1, 
1104                 'relation2': rel2,
1105                 'bound2': bound2,
1106                 'step': step }
1107
1108 def p_for_from_relation(s):
1109     if s.sy in inequality_relations:
1110         op = s.sy
1111         s.next()
1112         return op
1113     else:
1114         s.error("Expected one of '<', '<=', '>' '>='")
1115
1116 def p_for_from_step(s):
1117     if s.sy == 'by':
1118         s.next()
1119         step = p_bit_expr(s)
1120         return step
1121     else:
1122         return None
1123
1124 inequality_relations = ('<', '<=', '>', '>=')
1125
1126 def p_for_target(s):
1127     pos = s.position()
1128     expr = p_bit_expr(s)
1129     if s.sy == ',':
1130         s.next()
1131         exprs = [expr]
1132         while s.sy <> 'in':
1133             exprs.append(p_bit_expr(s))
1134             if s.sy <> ',':
1135                 break
1136             s.next()
1137         return ExprNodes.TupleNode(pos, args = exprs)
1138     else:
1139         return expr
1140
1141 def p_for_iterator(s):
1142     pos = s.position()
1143     expr = p_testlist(s)
1144     return ExprNodes.IteratorNode(pos, sequence = expr)
1145
1146 def p_try_statement(s):
1147     # s.sy == 'try'
1148     pos = s.position()
1149     s.next()
1150     body = p_suite(s)
1151     except_clauses = []
1152     else_clause = None
1153     if s.sy in ('except', 'else'):
1154         while s.sy == 'except':
1155             except_clauses.append(p_except_clause(s))
1156         if s.sy == 'else':
1157             s.next()
1158             else_clause = p_suite(s)
1159         return Nodes.TryExceptStatNode(pos,
1160             body = body, except_clauses = except_clauses,
1161             else_clause = else_clause)
1162     elif s.sy == 'finally':
1163         s.next()
1164         finally_clause = p_suite(s)
1165         return Nodes.TryFinallyStatNode(pos,
1166             body = body, finally_clause = finally_clause)
1167     else:
1168         s.error("Expected 'except' or 'finally'")
1169
1170 def p_except_clause(s):
1171     # s.sy == 'except'
1172     pos = s.position()
1173     s.next()
1174     exc_type = None
1175     exc_value = None
1176     if s.sy <> ':':
1177         exc_type = p_simple_expr(s)
1178         if s.sy == ',':
1179             s.next()
1180             exc_value = p_simple_expr(s)
1181     body = p_suite(s)
1182     return Nodes.ExceptClauseNode(pos,
1183         pattern = exc_type, target = exc_value, body = body)
1184
1185 def p_include_statement(s, level):
1186     pos = s.position()
1187     s.next() # 'include'
1188     _, include_file_name = p_string_literal(s)
1189     s.expect_newline("Syntax error in include statement")
1190     if s.compile_time_eval:
1191         include_file_path = s.context.find_include_file(include_file_name, pos)
1192         if include_file_path:
1193             f = open(include_file_path, "rU")
1194             s2 = PyrexScanner(f, include_file_path, s)
1195             try:
1196                 tree = p_statement_list(s2, level)
1197             finally:
1198                 f.close()
1199             return tree
1200         else:
1201             return None
1202     else:
1203         return Nodes.PassStatNode(pos)
1204
1205 def p_with_statement(s):
1206     pos = s.position()
1207     s.next() # 'with'
1208 #       if s.sy == 'IDENT' and s.systring in ('gil', 'nogil'):
1209     if s.sy == 'IDENT' and s.systring == 'nogil':
1210         state = s.systring
1211         s.next()
1212         body = p_suite(s)
1213         return Nodes.GILStatNode(pos, state = state, body = body)
1214     else:
1215         s.error("Only 'with gil' and 'with nogil' implemented",
1216                 pos = pos)
1217     
1218 def p_simple_statement(s):
1219     #print "p_simple_statement:", s.sy, s.systring ###
1220     if s.sy == 'global':
1221         node = p_global_statement(s)
1222     elif s.sy == 'print':
1223         node = p_print_statement(s)
1224     elif s.sy == 'del':
1225         node = p_del_statement(s)
1226     elif s.sy == 'break':
1227         node = p_break_statement(s)
1228     elif s.sy == 'continue':
1229         node = p_continue_statement(s)
1230     elif s.sy == 'return':
1231         node = p_return_statement(s)
1232     elif s.sy == 'raise':
1233         node = p_raise_statement(s)
1234     elif s.sy in ('import', 'cimport'):
1235         node = p_import_statement(s)
1236     elif s.sy == 'from':
1237         node = p_from_import_statement(s)
1238     elif s.sy == 'assert':
1239         node = p_assert_statement(s)
1240     elif s.sy == 'pass':
1241         node = p_pass_statement(s)
1242     else:
1243         node = p_expression_or_assignment(s)
1244     return node
1245
1246 def p_simple_statement_list(s):
1247     # Parse a series of simple statements on one line
1248     # separated by semicolons.
1249     stat = p_simple_statement(s)
1250     if s.sy == ';':
1251         stats = [stat]
1252         while s.sy == ';':
1253             #print "p_simple_statement_list: maybe more to follow" ###
1254             s.next()
1255             if s.sy in ('NEWLINE', 'EOF'):
1256                 break
1257             stats.append(p_simple_statement(s))
1258         stat = Nodes.StatListNode(stats[0].pos, stats = stats)
1259     s.expect_newline("Syntax error in simple statement list")
1260     return stat
1261
1262 def p_compile_time_expr(s):
1263     old = s.compile_time_expr
1264     s.compile_time_expr = 1
1265     expr = p_expr(s)
1266     s.compile_time_expr = old
1267     return expr
1268
1269 def p_DEF_statement(s):
1270     pos = s.position()
1271     denv = s.compile_time_env
1272     s.next() # 'DEF'
1273     name = p_ident(s)
1274     s.expect('=')
1275     expr = p_compile_time_expr(s)
1276     value = expr.compile_time_value(denv)
1277     #print "p_DEF_statement: %s = %r" % (name, value) ###
1278     denv.declare(name, value)
1279     s.expect_newline()
1280     return Nodes.PassStatNode(pos)
1281
1282 def p_IF_statement(s, level, cdef_flag, visibility, api):
1283     pos = s.position
1284     saved_eval = s.compile_time_eval
1285     current_eval = saved_eval
1286     denv = s.compile_time_env
1287     result = None
1288     while 1:
1289         s.next() # 'IF' or 'ELIF'
1290         expr = p_compile_time_expr(s)
1291         s.compile_time_eval = current_eval and bool(expr.compile_time_value(denv))
1292         body = p_suite(s, level, cdef_flag, visibility, api = api)
1293         if s.compile_time_eval:
1294             result = body
1295             current_eval = 0
1296         if s.sy <> 'ELIF':
1297             break
1298     if s.sy == 'ELSE':
1299         s.next()
1300         s.compile_time_eval = current_eval
1301         body = p_suite(s, level, cdef_flag, visibility, api = api)
1302         if current_eval:
1303             result = body
1304     if not result:
1305         result = Nodes.PassStatNode(pos)
1306     s.compile_time_eval = saved_eval
1307     return result
1308
1309 def p_statement(s, level, cdef_flag = 0, visibility = 'private', api = 0):
1310     if s.sy == 'ctypedef':
1311         if level not in ('module', 'module_pxd'):
1312             s.error("ctypedef statement not allowed here")
1313         if api:
1314             error(s.position(), "'api' not allowed with 'ctypedef'")
1315         return p_ctypedef_statement(s, level, visibility, api)
1316     elif s.sy == 'DEF':
1317         return p_DEF_statement(s)
1318     elif s.sy == 'IF':
1319         return p_IF_statement(s, level, cdef_flag, visibility, api)
1320     else:
1321         overridable = 0
1322         if s.sy == 'cdef':
1323             cdef_flag = 1
1324             s.next()
1325         if s.sy == 'cpdef':
1326             cdef_flag = 1
1327             overridable = 1
1328             s.next()
1329         if cdef_flag:
1330             if level not in ('module', 'module_pxd', 'function', 'c_class', 'c_class_pxd'):
1331                 s.error('cdef statement not allowed here')
1332             s.level = level
1333             return p_cdef_statement(s, level, visibility = visibility,
1334                                     api = api, overridable = overridable)
1335     #    elif s.sy == 'cpdef':
1336     #        s.next()
1337     #        return p_c_func_or_var_declaration(s, level, s.position(), visibility = visibility, api = api, overridable = True)
1338         else:
1339             if api:
1340                 error(s.pos, "'api' not allowed with this statement")
1341             elif s.sy == 'def':
1342                 if level not in ('module', 'class', 'c_class', 'property'):
1343                     s.error('def statement not allowed here')
1344                 s.level = level
1345                 return p_def_statement(s)
1346             elif s.sy == 'class':
1347                 if level <> 'module':
1348                     s.error("class definition not allowed here")
1349                 return p_class_statement(s)
1350             elif s.sy == 'include':
1351                 if level not in ('module', 'module_pxd'):
1352                     s.error("include statement not allowed here")
1353                 return p_include_statement(s, level)
1354             elif level == 'c_class' and s.sy == 'IDENT' and s.systring == 'property':
1355                 return p_property_decl(s)
1356             elif s.sy == 'pass' and level <> 'property':
1357                 return p_pass_statement(s, with_newline = 1)
1358             else:
1359                 if level in ('c_class_pxd', 'property'):
1360                     s.error("Executable statement not allowed here")
1361                 if s.sy == 'if':
1362                     return p_if_statement(s)
1363                 elif s.sy == 'while':
1364                     return p_while_statement(s)
1365                 elif s.sy == 'for':
1366                     return p_for_statement(s)
1367                 elif s.sy == 'try':
1368                     return p_try_statement(s)
1369                 elif s.sy == 'with':
1370                     return p_with_statement(s)
1371                 else:
1372                     return p_simple_statement_list(s)
1373
1374 def p_statement_list(s, level,
1375         cdef_flag = 0, visibility = 'private', api = 0):
1376     # Parse a series of statements separated by newlines.
1377     pos = s.position()
1378     stats = []
1379     while s.sy not in ('DEDENT', 'EOF'):
1380         stats.append(p_statement(s, level,
1381             cdef_flag = cdef_flag, visibility = visibility, api = api))
1382     if len(stats) == 1:
1383         return stats[0]
1384     else:
1385         return Nodes.StatListNode(pos, stats = stats)
1386
1387 def p_suite(s, level = 'other', cdef_flag = 0,
1388         visibility = 'private', with_doc = 0, with_pseudo_doc = 0, api = 0):
1389     pos = s.position()
1390     s.expect(':')
1391     doc = None
1392     stmts = []
1393     if s.sy == 'NEWLINE':
1394         s.next()
1395         s.expect_indent()
1396         if with_doc or with_pseudo_doc:
1397             doc = p_doc_string(s)
1398         body = p_statement_list(s, 
1399             level = level,
1400             cdef_flag = cdef_flag, 
1401             visibility = visibility,
1402             api = api)
1403         s.expect_dedent()
1404     else:
1405         if api:
1406             error(s.pos, "'api' not allowed with this statement")
1407         if level in ('module', 'class', 'function', 'other'):
1408             body = p_simple_statement_list(s)
1409         else:
1410             body = p_pass_statement(s)
1411             s.expect_newline("Syntax error in declarations")
1412     if with_doc:
1413         return doc, body
1414     else:
1415         return body
1416
1417 def p_c_base_type(s, self_flag = 0):
1418     # If self_flag is true, this is the base type for the
1419     # self argument of a C method of an extension type.
1420     if s.sy == '(':
1421         return p_c_complex_base_type(s)
1422     else:
1423         return p_c_simple_base_type(s, self_flag)
1424
1425 def p_calling_convention(s):
1426     if s.sy == 'IDENT' and s.systring in calling_convention_words:
1427         result = s.systring
1428         s.next()
1429         return result
1430     else:
1431         return ""
1432
1433 calling_convention_words = ("__stdcall", "__cdecl")
1434
1435 def p_c_complex_base_type(s):
1436     # s.sy == '('
1437     pos = s.position()
1438     s.next()
1439     base_type = p_c_base_type(s)
1440     declarator = p_c_declarator(s, empty = 1)
1441     s.expect(')')
1442     return Nodes.CComplexBaseTypeNode(pos, 
1443         base_type = base_type, declarator = declarator)
1444
1445 def p_c_simple_base_type(s, self_flag):
1446     #print "p_c_simple_base_type: self_flag =", self_flag
1447     is_basic = 0
1448     signed = 1
1449     longness = 0
1450     module_path = []
1451     pos = s.position()
1452     if looking_at_base_type(s):
1453         #print "p_c_simple_base_type: looking_at_base_type at", s.position()
1454         is_basic = 1
1455         signed, longness = p_sign_and_longness(s)
1456         if s.sy == 'IDENT' and s.systring in basic_c_type_names:
1457             name = s.systring
1458             s.next()
1459         else:
1460             name = 'int'
1461     elif s.looking_at_type_name() or looking_at_dotted_name(s):
1462         #print "p_c_simple_base_type: looking_at_type_name at", s.position()
1463         name = s.systring
1464         s.next()
1465         while s.sy == '.':
1466             module_path.append(name)
1467             s.next()
1468             name = p_ident(s)
1469     else:
1470         #print "p_c_simple_base_type: not looking at type at", s.position()
1471         name = None
1472     return Nodes.CSimpleBaseTypeNode(pos, 
1473         name = name, module_path = module_path,
1474         is_basic_c_type = is_basic, signed = signed,
1475         longness = longness, is_self_arg = self_flag)
1476
1477 def looking_at_type(s):
1478     return looking_at_base_type(s) or s.looking_at_type_name()
1479
1480 def looking_at_base_type(s):
1481     #print "looking_at_base_type?", s.sy, s.systring, s.position()
1482     return s.sy == 'IDENT' and s.systring in base_type_start_words
1483
1484 def looking_at_dotted_name(s):
1485     if s.sy == 'IDENT':
1486         name = s.systring
1487         s.next()
1488         result = s.sy == '.'
1489         s.put_back('IDENT', name)
1490         return result
1491     else:
1492         return 0
1493
1494 basic_c_type_names = ("void", "char", "int", "float", "double", "Py_ssize_t", "bint")
1495
1496 sign_and_longness_words = ("short", "long", "signed", "unsigned")
1497
1498 base_type_start_words = \
1499     basic_c_type_names + sign_and_longness_words
1500
1501 def p_sign_and_longness(s):
1502     signed = 1
1503     longness = 0
1504     while s.sy == 'IDENT' and s.systring in sign_and_longness_words:
1505         if s.systring == 'unsigned':
1506             signed = 0
1507         elif s.systring == 'signed':
1508             signed = 2
1509         elif s.systring == 'short':
1510             longness = -1
1511         elif s.systring == 'long':
1512             longness += 1
1513         s.next()
1514     return signed, longness
1515
1516 def p_opt_cname(s):
1517     literal = p_opt_string_literal(s)
1518     if literal:
1519         _, cname = literal
1520     else:
1521         cname = None
1522     return cname
1523
1524 def p_c_declarator(s, empty = 0, is_type = 0, cmethod_flag = 0, assignable = 0,
1525         nonempty = 0, calling_convention_allowed = 0):
1526     # If empty is true, the declarator must be empty. If nonempty is true,
1527     # the declarator must be nonempty. Otherwise we don't care.
1528     # If cmethod_flag is true, then if this declarator declares
1529     # a function, it's a C method of an extension type.
1530     pos = s.position()
1531     if s.sy == '(':
1532         s.next()
1533         if s.sy == ')' or looking_at_type(s):
1534             base = Nodes.CNameDeclaratorNode(pos, name = "", cname = None)
1535             result = p_c_func_declarator(s, pos, base, cmethod_flag)
1536         else:
1537             result = p_c_declarator(s, empty, is_type, cmethod_flag, nonempty = nonempty,
1538                 calling_convention_allowed = 1)
1539             s.expect(')')
1540     else:
1541         result = p_c_simple_declarator(s, empty, is_type, cmethod_flag, assignable, nonempty)
1542     if not calling_convention_allowed and result.calling_convention and s.sy <> '(':
1543         error(s.position(), "%s on something that is not a function"
1544             % result.calling_convention)
1545     while s.sy in ('[', '('):
1546         pos = s.position()
1547         if s.sy == '[':
1548             result = p_c_array_declarator(s, result)
1549         else: # sy == '('
1550             s.next()
1551             result = p_c_func_declarator(s, pos, result, cmethod_flag)
1552         cmethod_flag = 0
1553     return result
1554
1555 def p_c_array_declarator(s, base):
1556     pos = s.position()
1557     s.next() # '['
1558     if s.sy <> ']':
1559         dim = p_expr(s)
1560     else:
1561         dim = None
1562     s.expect(']')
1563     return Nodes.CArrayDeclaratorNode(pos, base = base, dimension = dim)
1564
1565 def p_c_func_declarator(s, pos, base, cmethod_flag):
1566     #  Opening paren has already been skipped
1567     args = p_c_arg_list(s, in_pyfunc = 0, cmethod_flag = cmethod_flag,
1568         nonempty_declarators = 0)
1569     ellipsis = p_optional_ellipsis(s)
1570     s.expect(')')
1571     nogil = p_nogil(s)
1572     exc_val, exc_check = p_exception_value_clause(s)
1573     with_gil = p_with_gil(s)
1574     return Nodes.CFuncDeclaratorNode(pos, 
1575         base = base, args = args, has_varargs = ellipsis,
1576         exception_value = exc_val, exception_check = exc_check,
1577         nogil = nogil or with_gil, with_gil = with_gil)
1578
1579 def p_c_simple_declarator(s, empty, is_type, cmethod_flag, assignable, nonempty):
1580     pos = s.position()
1581     calling_convention = p_calling_convention(s)
1582     if s.sy == '*':
1583         s.next()
1584         base = p_c_declarator(s, empty, is_type, cmethod_flag, assignable, nonempty)
1585         result = Nodes.CPtrDeclaratorNode(pos, 
1586             base = base)
1587     elif s.sy == '**': # scanner returns this as a single token
1588         s.next()
1589         base = p_c_declarator(s, empty, is_type, cmethod_flag, assignable, nonempty)
1590         result = Nodes.CPtrDeclaratorNode(pos,
1591             base = Nodes.CPtrDeclaratorNode(pos,
1592                 base = base))
1593     else:
1594         rhs = None
1595         if s.sy == 'IDENT':
1596             name = s.systring
1597             if is_type:
1598                 s.add_type_name(name)
1599             if empty:
1600                 error(s.position(), "Declarator should be empty")
1601             s.next()
1602             cname = p_opt_cname(s)
1603             if s.sy == '=' and assignable:
1604                 s.next()
1605                 rhs = p_simple_expr(s)
1606         else:
1607             if nonempty:
1608                 error(s.position(), "Empty declarator")
1609             name = ""
1610             cname = None
1611         result = Nodes.CNameDeclaratorNode(pos,
1612             name = name, cname = cname, rhs = rhs)
1613     result.calling_convention = calling_convention
1614     return result
1615
1616 def p_nogil(s):
1617     if s.sy == 'IDENT' and s.systring == 'nogil':
1618         s.next()
1619         return 1
1620     else:
1621         return 0
1622
1623 def p_with_gil(s):
1624     if s.sy == 'with':
1625         s.next()
1626         s.expect_keyword('gil')
1627         return 1
1628     else:
1629         return 0
1630
1631 def p_exception_value_clause(s):
1632     exc_val = None
1633     exc_check = 0
1634     if s.sy == 'except':
1635         s.next()
1636         if s.sy == '*':
1637             exc_check = 1
1638             s.next()
1639         else:
1640             if s.sy == '?':
1641                 exc_check = 1
1642                 s.next()
1643             exc_val = p_simple_expr(s)
1644     return exc_val, exc_check
1645
1646 c_arg_list_terminators = ('*', '**', '.', ')')
1647
1648 #def p_c_arg_list(s, in_pyfunc, cmethod_flag = 0, nonempty_declarators = 0,
1649 #               kw_only = 0):
1650 #       args = []
1651 #       if s.sy not in c_arg_list_terminators:
1652 #               args.append(p_c_arg_decl(s, in_pyfunc, cmethod_flag,
1653 #                       nonempty = nonempty_declarators, kw_only = kw_only))
1654 #               while s.sy == ',':
1655 #                       s.next()
1656 #                       if s.sy in c_arg_list_terminators:
1657 #                               break
1658 #                       args.append(p_c_arg_decl(s, in_pyfunc), nonempty = nonempty_declarators,
1659 #                               kw_only = kw_only)
1660 #       return args
1661
1662 def p_c_arg_list(s, in_pyfunc, cmethod_flag = 0, nonempty_declarators = 0,
1663         kw_only = 0):
1664     #  Comma-separated list of C argument declarations, possibly empty.
1665     #  May have a trailing comma.
1666     args = []
1667     is_self_arg = cmethod_flag
1668     while s.sy not in c_arg_list_terminators:
1669         args.append(p_c_arg_decl(s, in_pyfunc, is_self_arg,
1670             nonempty = nonempty_declarators, kw_only = kw_only))
1671         if s.sy != ',':
1672             break
1673         s.next()
1674         is_self_arg = 0
1675     return args
1676
1677 def p_optional_ellipsis(s):
1678     if s.sy == '.':
1679         expect_ellipsis(s)
1680         return 1
1681     else:
1682         return 0
1683
1684 def p_c_arg_decl(s, in_pyfunc, cmethod_flag = 0, nonempty = 0, kw_only = 0):
1685     pos = s.position()
1686     not_none = 0
1687     default = None
1688     base_type = p_c_base_type(s, cmethod_flag)
1689     declarator = p_c_declarator(s, nonempty = nonempty)
1690     if s.sy == 'not':
1691         s.next()
1692         if s.sy == 'IDENT' and s.systring == 'None':
1693             s.next()
1694         else:
1695             s.error("Expected 'None'")
1696         if not in_pyfunc:
1697             error(pos, "'not None' only allowed in Python functions")
1698         not_none = 1
1699     if s.sy == '=':
1700         s.next()
1701         if 'pxd' in s.level:
1702             if s.sy not in ['*', '?']:
1703                 error(pos, "default values cannot be specified in pxd files, use ? or *")
1704             default = 1
1705             s.next()
1706         else:
1707             default = p_simple_expr(s)
1708     return Nodes.CArgDeclNode(pos,
1709         base_type = base_type,
1710         declarator = declarator,
1711         not_none = not_none,
1712         default = default,
1713         kw_only = kw_only)
1714
1715 def p_api(s):
1716     if s.sy == 'IDENT' and s.systring == 'api':
1717         s.next()
1718         return 1
1719     else:
1720         return 0
1721
1722 def p_cdef_statement(s, level, visibility = 'private', api = 0,
1723                      overridable = False):
1724     pos = s.position()
1725     if overridable and level not in ('c_class', 'c_class_pxd'):
1726             error(pos, "Overridable cdef function not allowed here")
1727     visibility = p_visibility(s, visibility)
1728     api = api or p_api(s)
1729     if api:
1730         if visibility not in ('private', 'public'):
1731             error(pos, "Cannot combine 'api' with '%s'" % visibility)
1732     if visibility == 'extern' and s.sy == 'from':
1733             return p_cdef_extern_block(s, level, pos)
1734     elif s.sy == ':':
1735         return p_cdef_block(s, level, visibility, api)
1736     elif s.sy == 'class':
1737         if level not in ('module', 'module_pxd'):
1738             error(pos, "Extension type definition not allowed here")
1739         #if api:
1740         #    error(pos, "'api' not allowed with extension class")
1741         return p_c_class_definition(s, level, pos, visibility = visibility, api = api)
1742     elif s.sy == 'IDENT' and s.systring in struct_union_or_enum:
1743         if level not in ('module', 'module_pxd'):
1744             error(pos, "C struct/union/enum definition not allowed here")
1745         #if visibility == 'public':
1746         #    error(pos, "Public struct/union/enum definition not implemented")
1747         #if api:
1748         #    error(pos, "'api' not allowed with '%s'" % s.systring)
1749         if s.systring == "enum":
1750             return p_c_enum_definition(s, pos, level, visibility)
1751         else:
1752             return p_c_struct_or_union_definition(s, pos, level, visibility)
1753     elif s.sy == 'pass':
1754         node = p_pass_statement(s)
1755         s.expect_newline('Expected a newline')
1756         return node
1757     else:
1758         return p_c_func_or_var_declaration(s, level, pos, visibility, api,
1759                                            overridable)
1760
1761 def p_cdef_block(s, level, visibility, api):
1762     return p_suite(s, level, cdef_flag = 1, visibility = visibility, api = api)
1763
1764 def p_cdef_extern_block(s, level, pos):
1765     include_file = None
1766     s.expect('from')
1767     if s.sy == '*':
1768         s.next()
1769     else:
1770         _, include_file = p_string_literal(s)
1771     body = p_suite(s, level, cdef_flag = 1, visibility = 'extern')
1772     return Nodes.CDefExternNode(pos,
1773         include_file = include_file,
1774         body = body)
1775
1776 struct_union_or_enum = (
1777     "struct", "union", "enum"
1778 )
1779
1780 def p_c_enum_definition(s, pos, level, visibility, typedef_flag = 0):
1781     # s.sy == ident 'enum'
1782     s.next()
1783     if s.sy == 'IDENT':
1784         name = s.systring
1785         s.next()
1786         s.add_type_name(name)
1787         cname = p_opt_cname(s)
1788     else:
1789         name = None
1790         cname = None
1791     items = None
1792     s.expect(':')
1793     items = []
1794     if s.sy <> 'NEWLINE':
1795         p_c_enum_line(s, items)
1796     else:
1797         s.next() # 'NEWLINE'
1798         s.expect_indent()
1799         while s.sy not in ('DEDENT', 'EOF'):
1800             p_c_enum_line(s, items)
1801         s.expect_dedent()
1802     return Nodes.CEnumDefNode(pos, name = name, cname = cname,
1803         items = items, typedef_flag = typedef_flag, visibility = visibility,
1804         in_pxd = level == 'module_pxd')
1805
1806 def p_c_enum_line(s, items):
1807     if s.sy <> 'pass':
1808         p_c_enum_item(s, items)
1809         while s.sy == ',':
1810             s.next()
1811             if s.sy in ('NEWLINE', 'EOF'):
1812                 break
1813             p_c_enum_item(s, items)
1814     else:
1815         s.next()
1816     s.expect_newline("Syntax error in enum item list")
1817
1818 def p_c_enum_item(s, items):
1819     pos = s.position()
1820     name = p_ident(s)
1821     cname = p_opt_cname(s)
1822     value = None
1823     if s.sy == '=':
1824         s.next()
1825         value = p_simple_expr(s)
1826     items.append(Nodes.CEnumDefItemNode(pos, 
1827         name = name, cname = cname, value = value))
1828
1829 def p_c_struct_or_union_definition(s, pos, level, visibility, typedef_flag = 0):
1830     # s.sy == ident 'struct' or 'union'
1831     kind = s.systring
1832     s.next()
1833     name = p_ident(s)
1834     cname = p_opt_cname(s)
1835     s.add_type_name(name)
1836     attributes = None
1837     if s.sy == ':':
1838         s.next()
1839         s.expect('NEWLINE')
1840         s.expect_indent()
1841         attributes = []
1842         while s.sy <> 'DEDENT':
1843             if s.sy <> 'pass':
1844                 attributes.append(
1845                     p_c_func_or_var_declaration(s, level = 'other', pos = s.position()))
1846             else:
1847                 s.next()
1848                 s.expect_newline("Expected a newline")
1849         s.expect_dedent()
1850     else:
1851         s.expect_newline("Syntax error in struct or union definition")
1852     return Nodes.CStructOrUnionDefNode(pos, 
1853         name = name, cname = cname, kind = kind, attributes = attributes,
1854         typedef_flag = typedef_flag, visibility = visibility,
1855         in_pxd = level == 'module_pxd')
1856
1857 def p_visibility(s, prev_visibility):
1858     pos = s.position()
1859     visibility = prev_visibility
1860     if s.sy == 'IDENT' and s.systring in ('extern', 'public', 'readonly'):
1861         visibility = s.systring
1862         if prev_visibility <> 'private' and visibility <> prev_visibility:
1863             s.error("Conflicting visibility options '%s' and '%s'"
1864                 % (prev_visibility, visibility))
1865         s.next()
1866     return visibility
1867     
1868 def p_c_modifiers(s):
1869     if s.sy == 'IDENT' and s.systring in ('inline',):
1870         modifier = s.systring
1871         s.next()
1872         return [modifier] + p_c_modifiers(s)
1873     return []
1874
1875 def p_c_func_or_var_declaration(s, level, pos, visibility = 'private', api = 0,
1876                                 overridable = False):
1877     cmethod_flag = level in ('c_class', 'c_class_pxd')
1878     modifiers = p_c_modifiers(s)
1879     base_type = p_c_base_type(s)
1880     declarator = p_c_declarator(s, cmethod_flag = cmethod_flag, assignable = 1, nonempty = 1)
1881     declarator.overridable = overridable
1882     if s.sy == ':':
1883         if level not in ('module', 'c_class'):
1884             s.error("C function definition not allowed here")
1885         doc, suite = p_suite(s, 'function', with_doc = 1)
1886         result = Nodes.CFuncDefNode(pos,
1887             visibility = visibility,
1888             base_type = base_type,
1889             declarator = declarator, 
1890             body = suite,
1891             doc = doc,
1892             modifiers = modifiers,
1893             api = api,
1894             overridable = overridable)
1895     else:
1896         #if api:
1897         #    error(s.pos, "'api' not allowed with variable declaration")
1898         declarators = [declarator]
1899         while s.sy == ',':
1900             s.next()
1901             if s.sy == 'NEWLINE':
1902                 break
1903             declarator = p_c_declarator(s, cmethod_flag = cmethod_flag, assignable = 1, nonempty = 1)
1904             declarators.append(declarator)
1905         s.expect_newline("Syntax error in C variable declaration")
1906         result = Nodes.CVarDefNode(pos, 
1907             visibility = visibility,
1908             base_type = base_type, 
1909             declarators = declarators,
1910             in_pxd = level == 'module_pxd',
1911             api = api,
1912             overridable = overridable)
1913     return result
1914
1915 def p_ctypedef_statement(s, level, visibility = 'private', api = 0):
1916     # s.sy == 'ctypedef'
1917     pos = s.position()
1918     s.next()
1919     visibility = p_visibility(s, visibility)
1920     if s.sy == 'class':
1921         return p_c_class_definition(s, level, pos,
1922             visibility = visibility, typedef_flag = 1, api = api)
1923     elif s.sy == 'IDENT' and s.systring in ('struct', 'union', 'enum'):
1924         if s.systring == 'enum':
1925             return p_c_enum_definition(s, pos, level, visibility, typedef_flag = 1)
1926         else:
1927             return p_c_struct_or_union_definition(s, pos, level, visibility,
1928                 typedef_flag = 1)
1929     else:
1930         base_type = p_c_base_type(s)
1931         declarator = p_c_declarator(s, is_type = 1, nonempty = 1)
1932         s.expect_newline("Syntax error in ctypedef statement")
1933         return Nodes.CTypeDefNode(pos,
1934             base_type = base_type, declarator = declarator, visibility = visibility,
1935             in_pxd = level == 'module_pxd')
1936
1937 def p_def_statement(s):
1938     # s.sy == 'def'
1939     pos = s.position()
1940     s.next()
1941     name = p_ident(s)
1942     #args = []
1943     s.expect('(');
1944     args = p_c_arg_list(s, in_pyfunc = 1, nonempty_declarators = 1)
1945     star_arg = None
1946     starstar_arg = None
1947     if s.sy == '*':
1948         s.next()
1949         if s.sy == 'IDENT':
1950             star_arg = p_py_arg_decl(s)
1951         if s.sy == ',':
1952             s.next()
1953             args.extend(p_c_arg_list(s, in_pyfunc = 1,
1954                 nonempty_declarators = 1, kw_only = 1))
1955         elif s.sy != ')':
1956             s.error("Syntax error in Python function argument list")
1957     if s.sy == '**':
1958         s.next()
1959         starstar_arg = p_py_arg_decl(s)
1960     s.expect(')')
1961     if p_nogil(s):
1962         error(s.pos, "Python function cannot be declared nogil")
1963     doc, body = p_suite(s, 'function', with_doc = 1)
1964     return Nodes.DefNode(pos, name = name, args = args, 
1965         star_arg = star_arg, starstar_arg = starstar_arg,
1966         doc = doc, body = body)
1967
1968 def p_py_arg_decl(s):
1969     pos = s.position()
1970     name = p_ident(s)
1971     return Nodes.PyArgDeclNode(pos, name = name)
1972
1973 def p_class_statement(s):
1974     # s.sy == 'class'
1975     pos = s.position()
1976     s.next()
1977     class_name = p_ident(s)
1978     if s.sy == '(':
1979         s.next()
1980         base_list = p_simple_expr_list(s)
1981         s.expect(')')
1982     else:
1983         base_list = []
1984     doc, body = p_suite(s, 'class', with_doc = 1)
1985     return Nodes.PyClassDefNode(pos,
1986         name = class_name,
1987         bases = ExprNodes.TupleNode(pos, args = base_list),
1988         doc = doc, body = body)
1989
1990 def p_c_class_definition(s, level, pos, 
1991         visibility = 'private', typedef_flag = 0, api = 0):
1992     # s.sy == 'class'
1993     s.next()
1994     module_path = []
1995     class_name = p_ident(s)
1996     while s.sy == '.':
1997         s.next()
1998         module_path.append(class_name)
1999         class_name = p_ident(s)
2000     if module_path and visibility <> 'extern':
2001         error(pos, "Qualified class name only allowed for 'extern' C class")
2002     if module_path and s.sy == 'IDENT' and s.systring == 'as':
2003         s.next()
2004         as_name = p_ident(s)
2005     else:
2006         as_name = class_name
2007     s.add_type_name(as_name)
2008     objstruct_name = None
2009     typeobj_name = None
2010     base_class_module = None
2011     base_class_name = None
2012     if s.sy == '(':
2013         s.next()
2014         base_class_path = [p_ident(s)]
2015         while s.sy == '.':
2016             s.next()
2017             base_class_path.append(p_ident(s))
2018         if s.sy == ',':
2019             s.error("C class may only have one base class")
2020         s.expect(')')
2021         base_class_module = ".".join(base_class_path[:-1])
2022         base_class_name = base_class_path[-1]
2023     if s.sy == '[':
2024         if visibility not in ('public', 'extern'):
2025             error(s.position(), "Name options only allowed for 'public' or 'extern' C class")
2026         objstruct_name, typeobj_name = p_c_class_options(s)
2027     if s.sy == ':':
2028         if level == 'module_pxd':
2029             body_level = 'c_class_pxd'
2030         else:
2031             body_level = 'c_class'
2032         doc, body = p_suite(s, body_level, with_doc = 1)
2033     else:
2034         s.expect_newline("Syntax error in C class definition")
2035         doc = None
2036         body = None
2037     if visibility == 'extern':
2038         if not module_path:
2039             error(pos, "Module name required for 'extern' C class")
2040         if typeobj_name:
2041             error(pos, "Type object name specification not allowed for 'extern' C class")
2042     elif visibility == 'public':
2043         if not objstruct_name:
2044             error(pos, "Object struct name specification required for 'public' C class")
2045         if not typeobj_name:
2046             error(pos, "Type object name specification required for 'public' C class")
2047     elif visibility == 'private':
2048         if api:
2049             error(pos, "Only 'public' C class can be declared 'api'")
2050     else:
2051         error(pos, "Invalid class visibility '%s'" % visibility)
2052     return Nodes.CClassDefNode(pos,
2053         visibility = visibility,
2054         typedef_flag = typedef_flag,
2055         api = api,
2056         module_name = ".".join(module_path),
2057         class_name = class_name,
2058         as_name = as_name,
2059         base_class_module = base_class_module,
2060         base_class_name = base_class_name,
2061         objstruct_name = objstruct_name,
2062         typeobj_name = typeobj_name,
2063         in_pxd = level == 'module_pxd',
2064         doc = doc,
2065         body = body)
2066
2067 def p_c_class_options(s):
2068     objstruct_name = None
2069     typeobj_name = None
2070     s.expect('[')
2071     while 1:
2072         if s.sy <> 'IDENT':
2073             break
2074         if s.systring == 'object':
2075             s.next()
2076             objstruct_name = p_ident(s)
2077         elif s.systring == 'type':
2078             s.next()
2079             typeobj_name = p_ident(s)
2080         if s.sy <> ',':
2081             break
2082         s.next()
2083     s.expect(']', "Expected 'object' or 'type'")
2084     return objstruct_name, typeobj_name
2085
2086 def p_property_decl(s):
2087     pos = s.position()
2088     s.next() # 'property'
2089     name = p_ident(s)
2090     doc, body = p_suite(s, 'property', with_doc = 1)
2091     return Nodes.PropertyNode(pos, name = name, doc = doc, body = body)
2092
2093 def p_doc_string(s):
2094     if s.sy == 'STRING' or s.sy == 'BEGIN_STRING':
2095         _, result = p_cat_string_literal(s)
2096         if s.sy <> 'EOF':
2097             s.expect_newline("Syntax error in doc string")
2098         return result
2099     else:
2100         return None
2101
2102 def p_module(s, pxd, full_module_name):
2103     s.add_type_name("object")
2104     pos = s.position()
2105     doc = p_doc_string(s)
2106     if pxd:
2107         level = 'module_pxd'
2108     else:
2109         level = 'module'
2110     body = p_statement_list(s, level)
2111     if s.sy <> 'EOF':
2112         s.error("Syntax error in statement [%s,%s]" % (
2113             repr(s.sy), repr(s.systring)))
2114     return ModuleNode(pos, doc = doc, body = body, full_module_name = full_module_name)
2115
2116 #----------------------------------------------
2117 #
2118 #   Debugging
2119 #
2120 #----------------------------------------------
2121
2122 def print_parse_tree(f, node, level, key = None):       
2123     from Nodes import Node
2124     ind = "  " * level
2125     if node:
2126         f.write(ind)
2127         if key:
2128             f.write("%s: " % key)
2129         t = type(node)
2130         if t == TupleType:
2131             f.write("(%s @ %s\n" % (node[0], node[1]))
2132             for i in xrange(2, len(node)):
2133                 print_parse_tree(f, node[i], level+1)
2134             f.write("%s)\n" % ind)
2135             return
2136         elif isinstance(node, Node):
2137             try:
2138                 tag = node.tag
2139             except AttributeError:
2140                 tag = node.__class__.__name__
2141             f.write("%s @ %s\n" % (tag, node.pos))
2142             for name, value in node.__dict__.items():
2143                 if name <> 'tag' and name <> 'pos':
2144                     print_parse_tree(f, value, level+1, name)
2145             return
2146         elif t == ListType:
2147             f.write("[\n")
2148             for i in xrange(len(node)):
2149                 print_parse_tree(f, node[i], level+1)
2150             f.write("%s]\n" % ind)
2151             return
2152     f.write("%s%s\n" % (ind, node))
2153