summaryrefslogtreecommitdiffstats
path: root/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Parsing.py
diff options
context:
space:
mode:
Diffstat (limited to 'debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Parsing.py')
-rw-r--r--debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Parsing.py2142
1 files changed, 0 insertions, 2142 deletions
diff --git a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Parsing.py b/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Parsing.py
deleted file mode 100644
index b7b9e4b5..00000000
--- a/debian/pyrex/pyrex-0.9.9/Pyrex/Compiler/Parsing.py
+++ /dev/null
@@ -1,2142 +0,0 @@
-#
-# Pyrex Parser
-#
-
-import os, re
-from string import join, replace
-from types import ListType, TupleType
-from Scanning import PyrexScanner
-import Nodes
-import ExprNodes
-from ModuleNode import ModuleNode
-from Errors import warning, error, InternalError
-
-
-class Ctx(object):
- # Parsing context
- level = 'other'
- visibility = 'private'
- extern_from = False
- cdef_flag = 0
- cplus_flag = 0
- typedef_flag = 0
- api = 0
- nogil = 0
-
- def __init__(self, **kwds):
- self.__dict__.update(kwds)
-
- def __call__(self, **kwds):
- ctx = Ctx()
- d = ctx.__dict__
- d.update(self.__dict__)
- d.update(kwds)
- return ctx
-
- def cplus_check(self, pos):
- #if self.visibility <> 'extern':
- # error(pos, "C++ declarations must be 'extern'")
- if self.cplus_flag and not self.extern_from:
- error(pos, "C++ declarations must be in an 'extern from' block")
-
-
-def p_ident(s, message = "Expected an identifier"):
- if s.sy == 'IDENT':
- name = s.systring
- s.next()
- return name
- else:
- s.error(message)
-
-def p_ident_list(s):
- names = []
- while s.sy == 'IDENT':
- names.append(s.systring)
- s.next()
- if s.sy <> ',':
- break
- s.next()
- return names
-
-#------------------------------------------
-#
-# Expressions
-#
-#------------------------------------------
-
-def p_binop_expr(s, ops, p_sub_expr):
- n1 = p_sub_expr(s)
- while s.sy in ops:
- op = s.sy
- pos = s.position()
- s.next()
- n2 = p_sub_expr(s)
- n1 = ExprNodes.binop_node(pos, op, n1, n2)
- return n1
-
-#test: and_test ('or' and_test)* | lambdef
-
-def p_simple_expr(s):
- return p_rassoc_binop_expr(s, ('or',), p_and_test)
-
-def p_rassoc_binop_expr(s, ops, p_subexpr):
- n1 = p_subexpr(s)
- if s.sy in ops:
- pos = s.position()
- op = s.sy
- s.next()
- n2 = p_rassoc_binop_expr(s, ops, p_subexpr)
- n1 = ExprNodes.binop_node(pos, op, n1, n2)
- return n1
-
-#and_test: not_test ('and' not_test)*
-
-def p_and_test(s):
- #return p_binop_expr(s, ('and',), p_not_test)
- return p_rassoc_binop_expr(s, ('and',), p_not_test)
-
-#not_test: 'not' not_test | comparison
-
-def p_not_test(s):
- if s.sy == 'not':
- pos = s.position()
- s.next()
- return ExprNodes.NotNode(pos, operand = p_not_test(s))
- else:
- return p_comparison(s)
-
-#comparison: expr (comp_op expr)*
-#comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
-
-def p_comparison(s):
- n1 = p_bit_expr(s)
- if s.sy in comparison_ops:
- pos = s.position()
- op = p_cmp_op(s)
- n2 = p_bit_expr(s)
- n1 = ExprNodes.PrimaryCmpNode(pos,
- operator = op, operand1 = n1, operand2 = n2)
- if s.sy in comparison_ops:
- n1.cascade = p_cascaded_cmp(s)
- return n1
-
-def p_cascaded_cmp(s):
- pos = s.position()
- op = p_cmp_op(s)
- n2 = p_bit_expr(s)
- result = ExprNodes.CascadedCmpNode(pos,
- operator = op, operand2 = n2)
- if s.sy in comparison_ops:
- result.cascade = p_cascaded_cmp(s)
- return result
-
-def p_cmp_op(s):
- if s.sy == 'not':
- s.next()
- s.expect('in')
- op = 'not_in'
- elif s.sy == 'is':
- s.next()
- if s.sy == 'not':
- s.next()
- op = 'is_not'
- else:
- op = 'is'
- else:
- op = s.sy
- s.next()
- if op == '<>':
- op = '!='
- return op
-
-comparison_ops = (
- '<', '>', '==', '>=', '<=', '<>', '!=',
- 'in', 'is', 'not'
-)
-
-#expr: xor_expr ('|' xor_expr)*
-
-def p_bit_expr(s):
- return p_binop_expr(s, ('|',), p_xor_expr)
-
-#xor_expr: and_expr ('^' and_expr)*
-
-def p_xor_expr(s):
- return p_binop_expr(s, ('^',), p_and_expr)
-
-#and_expr: shift_expr ('&' shift_expr)*
-
-def p_and_expr(s):
- return p_binop_expr(s, ('&',), p_shift_expr)
-
-#shift_expr: arith_expr (('<<'|'>>') arith_expr)*
-
-def p_shift_expr(s):
- return p_binop_expr(s, ('<<', '>>'), p_arith_expr)
-
-#arith_expr: term (('+'|'-') term)*
-
-def p_arith_expr(s):
- return p_binop_expr(s, ('+', '-'), p_term)
-
-#term: factor (('*'|'/'|'%') factor)*
-
-def p_term(s):
- return p_binop_expr(s, ('*', '/', '%'), p_factor)
-
-#factor: ('+'|'-'|'~'|'&'|typecast|sizeof) factor | power
-
-def p_factor(s):
- sy = s.sy
- if sy in ('+', '-', '~'):
- op = s.sy
- pos = s.position()
- s.next()
- return ExprNodes.unop_node(pos, op, p_factor(s))
- elif sy == '&':
- pos = s.position()
- s.next()
- arg = p_factor(s)
- return ExprNodes.AmpersandNode(pos, operand = arg)
- elif sy == "<":
- return p_typecast(s)
- elif sy == 'IDENT' and s.systring == "sizeof":
- return p_sizeof(s)
- else:
- return p_power(s)
-
-def p_typecast(s):
- # s.sy == "<"
- pos = s.position()
- s.next()
- base_type = p_c_base_type(s)
- declarator = p_c_declarator(s, empty = 1)
- s.expect(">")
- operand = p_factor(s)
- return ExprNodes.TypecastNode(pos,
- base_type = base_type,
- declarator = declarator,
- operand = operand)
-
-def p_sizeof(s):
- # s.sy == ident "sizeof"
- pos = s.position()
- s.next()
- s.expect('(')
- if looking_at_type(s):
- base_type = p_c_base_type(s)
- declarator = p_c_declarator(s, empty = 1)
- node = ExprNodes.SizeofTypeNode(pos,
- base_type = base_type, declarator = declarator)
- else:
- operand = p_simple_expr(s)
- node = ExprNodes.SizeofVarNode(pos, operand = operand)
- s.expect(')')
- return node
-
-#power: atom trailer* ('**' factor)*
-
-def p_power(s):
- n1 = p_primitive(s)
- if s.sy == '**':
- pos = s.position()
- s.next()
- n2 = p_factor(s)
- n1 = ExprNodes.binop_node(pos, '**', n1, n2)
- return n1
-
-def p_primitive(s):
- n = p_atom(s)
- while s.sy in ('(', '[', '.'):
- n = p_trailer(s, n)
- return n
-
-#trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
-
-def p_trailer(s, node1):
- pos = s.position()
- if s.sy == '(':
- return p_call(s, node1)
- elif s.sy == '[':
- return p_index(s, node1)
- else: # s.sy == '.'
- s.next()
- name = p_ident(s)
- return ExprNodes.AttributeNode(pos,
- obj = node1, attribute = name)
-
-# arglist: argument (',' argument)* [',']
-# argument: [test '='] test # Really [keyword '='] test
-
-def p_call(s, function):
- # s.sy == '('
- pos = s.position()
- s.next()
- positional_args = []
- keyword_args = []
- star_arg = None
- starstar_arg = None
- while s.sy not in ('*', '**', ')'):
- arg = p_simple_expr(s)
- if s.sy == '=':
- s.next()
- if not arg.is_name:
- s.error("Expected an identifier before '='",
- pos = arg.pos)
- keyword = ExprNodes.StringNode(arg.pos,
- value = arg.name)
- arg = p_simple_expr(s)
- keyword_args.append((keyword, arg))
- else:
- if keyword_args:
- s.error("Non-keyword arg following keyword arg",
- pos = arg.pos)
- positional_args.append(arg)
- if s.sy <> ',':
- break
- s.next()
- if s.sy == '*':
- s.next()
- star_arg = p_simple_expr(s)
- if s.sy == ',':
- s.next()
- if s.sy == '**':
- s.next()
- starstar_arg = p_simple_expr(s)
- if s.sy == ',':
- s.next()
- s.expect(')')
- if not (keyword_args or star_arg or starstar_arg):
- return ExprNodes.SimpleCallNode(pos,
- function = function,
- args = positional_args)
- else:
- arg_tuple = None
- keyword_dict = None
- if positional_args or not star_arg:
- arg_tuple = ExprNodes.TupleNode(pos,
- args = positional_args)
- if star_arg:
- star_arg_tuple = ExprNodes.AsTupleNode(pos, arg = star_arg)
- if arg_tuple:
- arg_tuple = ExprNodes.binop_node(pos,
- operator = '+', operand1 = arg_tuple,
- operand2 = star_arg_tuple)
- else:
- arg_tuple = star_arg_tuple
- if keyword_args:
- keyword_dict = ExprNodes.DictNode(pos,
- key_value_pairs = keyword_args)
- return ExprNodes.GeneralCallNode(pos,
- function = function,
- positional_args = arg_tuple,
- keyword_args = keyword_dict,
- starstar_arg = starstar_arg)
-
-#lambdef: 'lambda' [varargslist] ':' test
-
-#subscriptlist: subscript (',' subscript)* [',']
-
-def p_index(s, base):
- # s.sy == '['
- pos = s.position()
- s.next()
- subscripts = p_subscript_list(s)
- if len(subscripts) == 1 and len(subscripts[0]) == 2:
- start, stop = subscripts[0]
- result = ExprNodes.SliceIndexNode(pos,
- base = base, start = start, stop = stop)
- else:
- indexes = make_slice_nodes(pos, subscripts)
- if len(indexes) == 1:
- index = indexes[0]
- else:
- index = ExprNodes.TupleNode(pos, args = indexes)
- result = ExprNodes.IndexNode(pos,
- base = base, index = index)
- s.expect(']')
- return result
-
-def p_subscript_list(s):
- items = [p_subscript(s)]
- while s.sy == ',':
- s.next()
- if s.sy == ']':
- break
- items.append(p_subscript(s))
- return items
-
-#subscript: '.' '.' '.' | test | [test] ':' [test] [':' [test]]
-
-def p_subscript(s):
- # Parse a subscript and return a list of
- # 1, 2 or 3 ExprNodes, depending on how
- # many slice elements were encountered.
- pos = s.position()
- if s.sy == '.':
- expect_ellipsis(s)
- return [ExprNodes.EllipsisNode(pos)]
- else:
- start = p_slice_element(s, (':',))
- if s.sy <> ':':
- return [start]
- s.next()
- stop = p_slice_element(s, (':', ',', ']'))
- if s.sy <> ':':
- return [start, stop]
- s.next()
- step = p_slice_element(s, (':', ',', ']'))
- return [start, stop, step]
-
-def p_slice_element(s, follow_set):
- # Simple expression which may be missing iff
- # it is followed by something in follow_set.
- if s.sy not in follow_set:
- return p_simple_expr(s)
- else:
- return None
-
-def expect_ellipsis(s):
- s.expect('.')
- s.expect('.')
- s.expect('.')
-
-def make_slice_nodes(pos, subscripts):
- # Convert a list of subscripts as returned
- # by p_subscript_list into a list of ExprNodes,
- # creating SliceNodes for elements with 2 or
- # more components.
- result = []
- for subscript in subscripts:
- if len(subscript) == 1:
- result.append(subscript[0])
- else:
- result.append(make_slice_node(pos, *subscript))
- return result
-
-def make_slice_node(pos, start, stop = None, step = None):
- if not start:
- start = ExprNodes.NoneNode(pos)
- if not stop:
- stop = ExprNodes.NoneNode(pos)
- if not step:
- step = ExprNodes.NoneNode(pos)
- return ExprNodes.SliceNode(pos,
- start = start, stop = stop, step = step)
-
-#atom: '(' [testlist] ')' | '[' [listmaker] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+
-
-def p_atom(s):
- pos = s.position()
- sy = s.sy
- if sy == '(':
- s.next()
- if s.sy == ')':
- result = ExprNodes.TupleNode(pos, args = [])
- else:
- result = p_expr(s)
- s.expect(')')
- return result
- elif sy == '[':
- return p_list_maker(s)
- elif sy == '{':
- return p_dict_maker(s)
- elif sy == '`':
- return p_backquote_expr(s)
- elif sy == 'INT':
- value = s.systring
- s.next()
- return ExprNodes.IntNode(pos, value = value)
- elif sy == 'LONG':
- value = s.systring
- s.next()
- return ExprNodes.LongNode(pos, value = value)
- elif sy == 'FLOAT':
- value = s.systring
- s.next()
- return ExprNodes.FloatNode(pos, value = value)
- elif sy == 'IMAG':
- value = s.systring[:-1]
- s.next()
- return ExprNodes.ImagNode(pos, value = value)
- elif sy == 'STRING' or sy == 'BEGIN_STRING':
- kind, value = p_cat_string_literal(s)
- if kind == 'c':
- return ExprNodes.CharNode(pos, value = value)
- else:
- return ExprNodes.StringNode(pos, value = value)
- elif sy == 'IDENT':
- name = s.systring
- s.next()
- if name == "None":
- return ExprNodes.NoneNode(pos)
- elif name == "new" and s.sy == 'IDENT':
- return p_new_call(s)
- else:
- return p_name_atom(s, name)
- elif sy == 'NULL':
- s.next()
- return ExprNodes.NullNode(pos)
- else:
- s.error("Expected an identifier or literal")
-
-def p_new_call(s):
- node = p_primitive(s)
- if isinstance(node, ExprNodes.SimpleCallNode):
- node.is_new = 1
- else:
- error(s.position(), "'new' must be followed by a C++ constructor call")
- return node
-
-def p_name(s):
- if s.sy == 'IDENT':
- pos = s.position()
- name = s.systring
- s.next()
- return ExprNodes.NameNode(pos, name = name)
- else:
- s.error("Expected a variable name")
-
-def p_name_atom(s, name):
- pos = s.position()
- if not s.compile_time_expr:
- try:
- value = s.compile_time_env.lookup_here(name)
- except KeyError:
- pass
- else:
- rep = repr(value)
- if isinstance(value, int):
- return ExprNodes.IntNode(pos, value = rep)
- elif isinstance(value, long):
- return ExprNodes.LongNode(pos, value = rep)
- elif isinstance(value, float):
- return ExprNodes.FloatNode(pos, value = rep)
- elif isinstance(value, str):
- return ExprNodes.StringNode(pos, value = rep[1:-1])
- else:
- error(pos, "Invalid type for compile-time constant: %s"
- % value.__class__.__name__)
- return ExprNodes.NameNode(pos, name = name)
-
-def p_cat_string_literal(s):
- # A sequence of one or more adjacent string literals.
- # Returns (kind, value) where kind in ('', 'c', 'r')
- kind, value = p_string_literal(s)
- if kind <> 'c':
- strings = [value]
- while s.sy == 'STRING' or s.sy == 'BEGIN_STRING':
- next_kind, next_value = p_string_literal(s)
- if next_kind == 'c':
- self.error(
- "Cannot concatenate char literal with another string or char literal")
- strings.append(next_value)
- value = ''.join(strings)
- return kind, value
-
-def p_opt_string_literal(s):
- if s.sy == 'STRING' or s.sy == 'BEGIN_STRING':
- return p_string_literal(s)
- else:
- return None
-
-def p_string_literal(s):
- # A single string or char literal.
- # Returns (kind, value) where kind in ('', 'c', 'r')
- if s.sy == 'STRING':
- value = unquote(s.systring)
- s.next()
- return value
- # s.sy == 'BEGIN_STRING'
- pos = s.position()
- #is_raw = s.systring[:1].lower() == "r"
- kind = s.systring[:1].lower()
- if kind not in "cr":
- kind = ''
- chars = []
- while 1:
- s.next()
- sy = s.sy
- #print "p_string_literal: sy =", sy, repr(s.systring) ###
- if sy == 'CHARS':
- systr = s.systring
- if len(systr) == 1 and systr in "'\"\n":
- chars.append('\\')
- chars.append(systr)
- elif sy == 'ESCAPE':
- systr = s.systring
- if kind == 'r':
- if systr == '\\\n':
- chars.append(r'\\\n')
- elif systr == r'\"':
- chars.append(r'\\\"')
- elif systr == r'\\':
- chars.append(r'\\\\')
- else:
- chars.append('\\' + systr)
- else:
- c = systr[1]
- if c in "'\"\\abfnrtv01234567":
- chars.append(systr)
- elif c == 'x':
- chars.append('\\x0' + systr[2:])
- elif c == '\n':
- pass
- else:
- chars.append(r'\\' + systr[1:])
- elif sy == 'NEWLINE':
- chars.append(r'\n')
- elif sy == 'END_STRING':
- break
- elif sy == 'EOF':
- s.error("Unclosed string literal", pos = pos)
- else:
- s.error(
- "Unexpected token %r:%r in string literal" %
- (sy, s.systring))
- s.next()
- value = join(chars, '')
- #print "p_string_literal: value =", repr(value) ###
- return kind, value
-
-def unquote(s):
- is_raw = 0
- if s[:1].lower() == "r":
- is_raw = 1
- s = s[1:]
- q = s[:3]
- if q == '"""' or q == "'''":
- s = s[3:-3]
- else:
- s = s[1:-1]
- if is_raw:
- s = s.replace('\\', '\\\\')
- s = s.replace('\n', '\\\n')
- else:
- # Split into double quotes, newlines, escape sequences
- # and spans of regular chars
- l1 = re.split(r'((?:\\[0-7]{1,3})|(?:\\x[0-9A-Fa-f]{2})|(?:\\.)|(?:\\\n)|(?:\n)|")', s)
- print "unquote: l1 =", l1 ###
- l2 = []
- for item in l1:
- if item == '"' or item == '\n':
- l2.append('\\' + item)
- elif item == '\\\n':
- pass
- elif item[:1] == '\\':
- if len(item) == 2:
- if item[1] in '"\\abfnrtv':
- l2.append(item)
- else:
- l2.append(item[1])
- elif item[1:2] == 'x':
- l2.append('\\x0' + item[2:])
- else:
- # octal escape
- l2.append(item)
- else:
- l2.append(item)
- s = "".join(l2)
- return s
-
-def p_list_maker(s):
- # s.sy == '['
- pos = s.position()
- s.next()
- exprs = p_simple_expr_list(s)
- s.expect(']')
- return ExprNodes.ListNode(pos, args = exprs)
-
-#dictmaker: test ':' test (',' test ':' test)* [',']
-
-def p_dict_maker(s):
- # s.sy == '{'
- pos = s.position()
- s.next()
- items = []
- while s.sy <> '}':
- key = p_simple_expr(s)
- s.expect(':')
- value = p_simple_expr(s)
- items.append((key, value))
- if s.sy <> ',':
- break
- s.next()
- s.expect('}')
- return ExprNodes.DictNode(pos, key_value_pairs = items)
-
-def p_backquote_expr(s):
- # s.sy == '`'
- pos = s.position()
- s.next()
- arg = p_expr(s)
- s.expect('`')
- return ExprNodes.BackquoteNode(pos, arg = arg)
-
-#testlist: test (',' test)* [',']
-
-def p_simple_expr_list(s):
- exprs = []
- while s.sy not in expr_terminators:
- exprs.append(p_simple_expr(s))
- if s.sy <> ',':
- break
- s.next()
- return exprs
-
-def p_expr(s):
- pos = s.position()
- expr = p_simple_expr(s)
- if s.sy == ',':
- s.next()
- exprs = [expr] + p_simple_expr_list(s)
- return ExprNodes.TupleNode(pos, args = exprs)
- else:
- return expr
-
-expr_terminators = (')', ']', '}', ':', '=', 'NEWLINE')
-
-#-------------------------------------------------------
-#
-# Statements
-#
-#-------------------------------------------------------
-
-def p_global_statement(s):
- # assume s.sy == 'global'
- pos = s.position()
- s.next()
- names = p_ident_list(s)
- return Nodes.GlobalNode(pos, names = names)
-
-inplace_operators = ('+=', '-=', '*=', '/=', '%=', '**=',
- '<<=', '>>=', '&=', '^=', '|=')
-
-def p_expression_or_assignment(s):
- pos = s.position()
- expr = p_expr(s)
- if s.sy in inplace_operators:
- return p_inplace_operation(s, expr)
- elif s.sy <> '=':
- if isinstance(expr, ExprNodes.StringNode):
- return Nodes.PassStatNode(expr.pos)
- else:
- return Nodes.ExprStatNode(expr.pos, expr = expr)
- else:
- expr_list = [expr]
- while s.sy == '=':
- s.next()
- expr_list.append(p_expr(s))
- expr_list_list = []
- flatten_parallel_assignments(expr_list, expr_list_list)
- nodes = []
- for expr_list in expr_list_list:
- lhs_list = expr_list[:-1]
- rhs = expr_list[-1]
- if len(lhs_list) == 1:
- node = Nodes.SingleAssignmentNode(rhs.pos,
- lhs = lhs_list[0], rhs = rhs)
- else:
- node = Nodes.CascadedAssignmentNode(rhs.pos,
- lhs_list = lhs_list, rhs = rhs)
- nodes.append(node)
- if len(nodes) == 1:
- return nodes[0]
- else:
- return Nodes.ParallelAssignmentNode(nodes[0].pos, stats = nodes)
-
-def p_inplace_operation(s, lhs):
- pos = s.position()
- op = s.sy
- s.next()
- rhs = p_expr(s)
- return Nodes.AugmentedAssignmentNode(pos, lhs = lhs, operator = op, rhs = rhs)
-
-def flatten_parallel_assignments(input, output):
- # The input is a list of expression nodes, representing
- # the LHSs and RHS of one (possibly cascaded) assignment
- # statement. If they are all sequence constructors with
- # the same number of arguments, rearranges them into a
- # list of equivalent assignments between the individual
- # elements. This transformation is applied recursively.
- size = find_parallel_assignment_size(input)
- if size >= 0:
- for i in range(size):
- new_exprs = [expr.args[i] for expr in input]
- flatten_parallel_assignments(new_exprs, output)
- else:
- output.append(input)
-
-def find_parallel_assignment_size(input):
- # The input is a list of expression nodes. If
- # they are all sequence constructors with the same number
- # of arguments, return that number, else return -1.
- # Produces an error message if they are all sequence
- # constructors but not all the same size.
- for expr in input:
- if not expr.is_sequence_constructor:
- return -1
- rhs = input[-1]
- rhs_size = len(rhs.args)
- for lhs in input[:-1]:
- lhs_size = len(lhs.args)
- if lhs_size <> rhs_size:
- error(lhs.pos, "Unpacking sequence of wrong size (expected %d, got %d)"
- % (lhs_size, rhs_size))
- return -1
- return rhs_size
-
-def p_print_statement(s):
- # s.sy == 'print'
- pos = s.position()
- s.next()
- if s.sy == '>>':
- s.error("'print >>' not yet implemented")
- args = []
- ewc = 0
- if s.sy not in ('NEWLINE', 'EOF'):
- args.append(p_simple_expr(s))
- while s.sy == ',':
- s.next()
- if s.sy in ('NEWLINE', 'EOF'):
- ewc = 1
- break
- args.append(p_simple_expr(s))
- return Nodes.PrintStatNode(pos,
- args = args, ends_with_comma = ewc)
-
-def p_del_statement(s):
- # s.sy == 'del'
- pos = s.position()
- s.next()
- args = p_simple_expr_list(s)
- return Nodes.DelStatNode(pos, args = args)
-
-def p_pass_statement(s, with_newline = 0):
- pos = s.position()
- s.expect('pass')
- if with_newline:
- s.expect_newline("Expected a newline")
- return Nodes.PassStatNode(pos)
-
-def p_break_statement(s):
- # s.sy == 'break'
- pos = s.position()
- s.next()
- return Nodes.BreakStatNode(pos)
-
-def p_continue_statement(s):
- # s.sy == 'continue'
- pos = s.position()
- s.next()
- return Nodes.ContinueStatNode(pos)
-
-def p_return_statement(s):
- # s.sy == 'return'
- pos = s.position()
- s.next()
- if s.sy not in statement_terminators:
- value = p_expr(s)
- else:
- value = None
- return Nodes.ReturnStatNode(pos, value = value)
-
-def p_raise_statement(s):
- # s.sy == 'raise'
- pos = s.position()
- s.next()
- exc_type = None
- exc_value = None
- exc_tb = None
- if s.sy not in statement_terminators:
- exc_type = p_simple_expr(s)
- if s.sy == ',':
- s.next()
- exc_value = p_simple_expr(s)
- if s.sy == ',':
- s.next()
- exc_tb = p_simple_expr(s)
- if exc_type or exc_value or exc_tb:
- return Nodes.RaiseStatNode(pos,
- exc_type = exc_type,
- exc_value = exc_value,
- exc_tb = exc_tb)
- else:
- return Nodes.ReraiseStatNode(pos)
-
-def p_import_statement(s):
- # s.sy in ('import', 'cimport')
- pos = s.position()
- kind = s.sy
- s.next()
- items = [p_dotted_name(s, as_allowed = 1)]
- while s.sy == ',':
- s.next()
- items.append(p_dotted_name(s, as_allowed = 1))
- stats = []
- for pos, target_name, dotted_name, as_name in items:
- if kind == 'cimport':
- stat = Nodes.CImportStatNode(pos,
- module_name = dotted_name,
- as_name = as_name)
- else:
- if as_name and "." in dotted_name:
- name_list = ExprNodes.ListNode(pos, args = [
- ExprNodes.StringNode(pos, value = "*")])
- else:
- name_list = None
- stat = Nodes.SingleAssignmentNode(pos,
- lhs = ExprNodes.NameNode(pos,
- name = as_name or target_name),
- rhs = ExprNodes.ImportNode(pos,
- module_name = ExprNodes.StringNode(pos,
- value = dotted_name),
- name_list = name_list))
- stats.append(stat)
- return Nodes.StatListNode(pos, stats = stats)
-
-def p_from_import_statement(s, ctx):
- # s.sy == 'from'
- pos = s.position()
- s.next()
- (dotted_name_pos, _, dotted_name, _) = \
- p_dotted_name(s, as_allowed = 0)
- if s.sy in ('import', 'cimport'):
- kind = s.sy
- s.next()
- else:
- s.error("Expected 'import' or 'cimport'")
- if kind == 'cimport' and ctx.level not in ('module', 'module_pxd'):
- s.error("cimport statement not allowed in this context")
- if s.sy == '*':
- s.error("'import *' not supported")
- is_cimport = kind == 'cimport'
- imported_names = [p_imported_name(s, is_cimport)]
- while s.sy == ',':
- s.next()
- imported_names.append(p_imported_name(s, is_cimport))
- if kind == 'cimport':
- for imp in imported_names:
- local_name = imp.as_name or imp.name
- s.add_type_name(local_name)
- return Nodes.FromCImportStatNode(pos,
- module_name = dotted_name,
- imported_names = imported_names)
- else:
- imported_name_strings = []
- items = []
- for imp in imported_names:
- imported_name_strings.append(
- ExprNodes.StringNode(imp.pos, value = imp.name))
- items.append(
- (imp.name,
- ExprNodes.NameNode(imp.pos,
- name = imp.as_name or imp.name)))
- import_list = ExprNodes.ListNode(
- imported_names[0].pos, args = imported_name_strings)
- return Nodes.FromImportStatNode(pos,
- module = ExprNodes.ImportNode(dotted_name_pos,
- module_name = ExprNodes.StringNode(dotted_name_pos,
- value = dotted_name),
- name_list = import_list),
- items = items)
-
-class ImportedName(object):
- # pos
- # name
- # as_name
- # kind 'class', 'struct', 'union', None
-
- def __init__(self, pos, name, as_name, kind):
- self.pos = pos
- self.name = name
- self.as_name = as_name
- self.kind = kind
-
-imported_name_kinds = ('class', 'struct', 'union')
-
-def p_imported_name(s, is_cimport):
- pos = s.position()
- kind = None
- if is_cimport and s.systring in imported_name_kinds:
- kind = s.systring
- s.next()
- name = p_ident(s)
- as_name = p_as_name(s)
- return ImportedName(pos, name, as_name, kind)
-
-def p_dotted_name(s, as_allowed):
- pos = s.position()
- target_name = p_ident(s)
- as_name = None
- names = [target_name]
- while s.sy == '.':
- s.next()
- names.append(p_ident(s))
- if as_allowed:
- as_name = p_as_name(s)
- return (pos, target_name, join(names, "."), as_name)
-
-def p_as_name(s):
- if s.sy == 'IDENT' and s.systring == 'as':
- s.next()
- return p_ident(s)
- else:
- return None
-
-def p_assert_statement(s):
- # s.sy == 'assert'
- pos = s.position()
- s.next()
- cond = p_simple_expr(s)
- if s.sy == ',':
- s.next()
- value = p_simple_expr(s)
- else:
- value = None
- return Nodes.AssertStatNode(pos, cond = cond, value = value)
-
-statement_terminators = (';', 'NEWLINE', 'EOF')
-
-def p_if_statement(s):
- # s.sy == 'if'
- pos = s.position()
- s.next()
- if_clauses = [p_if_clause(s)]
- while s.sy == 'elif':
- s.next()
- if_clauses.append(p_if_clause(s))
- else_clause = p_else_clause(s)
- return Nodes.IfStatNode(pos,
- if_clauses = if_clauses, else_clause = else_clause)
-
-def p_if_clause(s):
- pos = s.position()
- test = p_simple_expr(s)
- body = p_suite(s)
- return Nodes.IfClauseNode(pos,
- condition = test, body = body)
-
-def p_else_clause(s):
- if s.sy == 'else':
- s.next()
- return p_suite(s)
- else:
- return None
-
-def p_while_statement(s):
- # s.sy == 'while'
- pos = s.position()
- s.next()
- test = p_simple_expr(s)
- body = p_suite(s)
- else_clause = p_else_clause(s)
- return Nodes.WhileStatNode(pos,
- condition = test, body = body,
- else_clause = else_clause)
-
-def p_for_statement(s):
- # s.sy == 'for'
- pos = s.position()
- s.next()
- expr = p_for_expr(s)
- if s.sy == 'in':
- return p_standard_for_statement(s, expr)
- elif s.sy in inequality_relations:
- return p_integer_for_statement(s, expr)
- elif s.sy == 'from':
- #warning(pos, "Old-style integer for-loop is deprecated, use 'for x < i < y' instead")
- return p_old_style_integer_for_statement(s, expr)
- else:
- s.error("Expected 'in' or an inequality relation")
-
-def p_standard_for_statement(s, target):
- # s.sy == 'in'
- s.next()
- iterator = p_for_iterator(s)
- body = p_suite(s)
- else_clause = p_else_clause(s)
- return Nodes.ForInStatNode(target.pos,
- target = target,
- iterator = iterator,
- body = body,
- else_clause = else_clause)
-
-def p_integer_for_statement(s, bound1):
- rel1 = s.sy
- s.next()
- name_pos = s.position()
- target = p_name(s)
- rel2_pos = s.position()
- rel2 = p_inequality_relation(s)
- bound2 = p_bit_expr(s)
- if rel1[0] <> rel2[0]:
- error(rel2_pos,
- "Relation directions in integer for-loop do not match")
- body = p_suite(s)
- else_clause = p_else_clause(s)
- return Nodes.IntegerForStatNode(bound1.pos,
- bound1 = bound1,
- relation1 = rel1,
- target = target,
- relation2 = rel2,
- bound2 = bound2,
- body = body,
- else_clause = else_clause)
-
-def p_old_style_integer_for_statement(s, target):
- # s.sy == 'for'
- s.next()
- bound1 = p_bit_expr(s)
- rel1 = p_inequality_relation(s)
- name2_pos = s.position()
- name2 = p_ident(s)
- rel2_pos = s.position()
- rel2 = p_inequality_relation(s)
- bound2 = p_bit_expr(s)
- if not target.is_name:
- error(target.pos,
- "Target of for-from statement must be a variable name")
- elif name2 <> target.name:
- error(name2_pos,
- "Variable name in for-from range does not match target")
- if rel1[0] <> rel2[0]:
- error(rel2_pos,
- "Relation directions in for-from do not match")
- body = p_suite(s)
- else_clause = p_else_clause(s)
- return Nodes.IntegerForStatNode(bound1.pos,
- bound1 = bound1,
- relation1 = rel1,
- target = target,
- relation2 = rel2,
- bound2 = bound2,
- body = body,
- else_clause = else_clause)
-
-def p_inequality_relation(s):
- if s.sy in inequality_relations:
- op = s.sy
- s.next()
- return op
- else:
- s.error("Expected one of '<', '<=', '>' '>='")
-
-inequality_relations = ('<', '<=', '>', '>=')
-
-def p_for_expr(s):
- # Target of standard for-statement or first bound of integer for-statement
- pos = s.position()
- expr = p_bit_expr(s)
- if s.sy == ',':
- s.next()
- exprs = [expr]
- while s.sy <> 'in':
- exprs.append(p_bit_expr(s))
- if s.sy <> ',':
- break
- s.next()
- return ExprNodes.TupleNode(pos, args = exprs)
- else:
- return expr
-
-def p_for_iterator(s):
- pos = s.position()
- expr = p_expr(s)
- return ExprNodes.IteratorNode(pos, sequence = expr)
-
-def p_try_statement(s):
- # s.sy == 'try'
- pos = s.position()
- s.next()
- body = p_suite(s)
- except_clauses = []
- else_clause = None
- if s.sy in ('except', 'else'):
- while s.sy == 'except':
- except_clauses.append(p_except_clause(s))
- if s.sy == 'else':
- s.next()
- else_clause = p_suite(s)
- return Nodes.TryExceptStatNode(pos,
- body = body, except_clauses = except_clauses,
- else_clause = else_clause)
- elif s.sy == 'finally':
- s.next()
- finally_clause = p_suite(s)
- return Nodes.TryFinallyStatNode(pos,
- body = body, finally_clause = finally_clause)
- else:
- s.error("Expected 'except' or 'finally'")
-
-def p_except_clause(s):
- # s.sy == 'except'
- pos = s.position()
- s.next()
- exc_type = None
- exc_value = None
- tb_value = None
- if s.sy <> ':':
- exc_type = p_simple_expr(s)
- if s.sy == ',':
- s.next()
- exc_value = p_simple_expr(s)
- if s.sy == ',':
- s.next()
- tb_value = p_simple_expr(s)
- body = p_suite(s)
- return Nodes.ExceptClauseNode(pos,
- pattern = exc_type, exc_target = exc_value, tb_target = tb_value, body = body)
-
-def p_include_statement(s, ctx):
- pos = s.position()
- s.next() # 'include'
- _, include_file_name = p_string_literal(s)
- s.expect_newline("Syntax error in include statement")
- if s.compile_time_eval:
- include_file_path = s.context.find_include_file(include_file_name, pos)
- if include_file_path:
- s.included_files.append(include_file_name)
- f = open(include_file_path, "rU")
- s2 = PyrexScanner(f, include_file_path, parent_scanner = s)
- try:
- tree = p_statement_list(s2, ctx)
- finally:
- f.close()
- return tree
- else:
- return None
- else:
- return Nodes.PassStatNode(pos)
-
-def p_with_statement(s):
- pos = s.position()
- s.next() # 'with'
-# if s.sy == 'IDENT' and s.systring in ('gil', 'nogil'):
- if s.sy == 'IDENT' and s.systring == 'nogil':
- state = s.systring
- s.next()
- body = p_suite(s)
- return Nodes.GILStatNode(pos, state = state, body = body)
- else:
- s.error("Only 'with nogil' implemented")
-
-def p_simple_statement(s, ctx):
- if s.sy == 'global':
- node = p_global_statement(s)
- elif s.sy == 'print':
- node = p_print_statement(s)
- elif s.sy == 'del':
- node = p_del_statement(s)
- elif s.sy == 'break':
- node = p_break_statement(s)
- elif s.sy == 'continue':
- node = p_continue_statement(s)
- elif s.sy == 'return':
- node = p_return_statement(s)
- elif s.sy == 'raise':
- node = p_raise_statement(s)
- elif s.sy == 'cimport':
- if ctx.level not in ('module', 'module_pxd'):
- s.error("cimport statement not allowed in this context")
- node = p_import_statement(s)
- elif s.sy == 'import':
- node = p_import_statement(s)
- elif s.sy == 'from':
- node = p_from_import_statement(s, ctx)
- elif s.sy == 'assert':
- node = p_assert_statement(s)
- elif s.sy == 'pass':
- node = p_pass_statement(s)
- else:
- node = p_expression_or_assignment(s)
- return node
-
-def p_simple_statement_list(s, ctx):
- # Parse a series of simple statements on one line
- # separated by semicolons.
- stat = p_simple_statement(s, ctx)
- if s.sy == ';':
- stats = [stat]
- while s.sy == ';':
- s.next()
- if s.sy in ('NEWLINE', 'EOF'):
- break
- stats.append(p_simple_statement(s, ctx))
- stat = Nodes.StatListNode(stats[0].pos, stats = stats)
- s.expect_newline("Syntax error in simple statement list")
- return stat
-
-def p_compile_time_expr(s):
- old = s.compile_time_expr
- s.compile_time_expr = 1
- expr = p_expr(s)
- s.compile_time_expr = old
- return expr
-
-def p_DEF_statement(s):
- pos = s.position()
- denv = s.compile_time_env
- s.next() # 'DEF'
- name = p_ident(s)
- s.expect('=')
- expr = p_compile_time_expr(s)
- value = expr.compile_time_value(denv)
- #print "p_DEF_statement: %s = %r" % (name, value) ###
- denv.declare(name, value)
- s.expect_newline()
- return Nodes.PassStatNode(pos)
-
-def p_IF_statement(s, ctx):
- pos = s.position()
- saved_eval = s.compile_time_eval
- current_eval = saved_eval
- denv = s.compile_time_env
- result = None
- while 1:
- s.next() # 'IF' or 'ELIF'
- expr = p_compile_time_expr(s)
- s.compile_time_eval = current_eval and bool(expr.compile_time_value(denv))
- body = p_suite(s, ctx)
- if s.compile_time_eval:
- result = body
- current_eval = 0
- if s.sy <> 'ELIF':
- break
- if s.sy == 'ELSE':
- s.next()
- s.compile_time_eval = current_eval
- body = p_suite(s, ctx)
- if current_eval:
- result = body
- if not result:
- result = Nodes.PassStatNode(pos)
- s.compile_time_eval = saved_eval
- return result
-
-def p_statement(s, ctx):
- pos = s.position()
- cdef_flag = ctx.cdef_flag
- if s.sy == 'ctypedef':
- if ctx.level not in ('module', 'module_pxd'):
- s.error("ctypedef statement not allowed here")
- #if ctx.api:
- # error(s.pos, "'api' not allowed with 'ctypedef'")
- return p_ctypedef_statement(s, ctx)
- elif s.sy == 'DEF':
- return p_DEF_statement(s)
- elif s.sy == 'IF':
- return p_IF_statement(s, ctx)
- else:
- if s.sy == 'cdef':
- cdef_flag = 1
- s.next()
- if s.sy == '+':
- ctx = ctx(cplus_flag = 1)
- s.next()
- if cdef_flag:
- if ctx.level not in ('module', 'module_pxd', 'function', 'c_class', 'c_class_pxd'):
- s.error('cdef statement not allowed here')
- return p_cdef_statement(s, ctx)
- else:
- if ctx.api:
- error(s.pos, "'api' not allowed with this statement")
- if s.sy == 'def':
- if ctx.level not in ('module', 'class', 'c_class', 'property'):
- s.error('def statement not allowed here')
- return p_def_statement(s)
- elif s.sy == 'class':
- if ctx.level <> 'module':
- s.error("class definition not allowed here")
- return p_class_statement(s)
- elif s.sy == 'include':
- #if ctx.level not in ('module', 'module_pxd'):
- # s.error("include statement not allowed here")
- return p_include_statement(s, ctx)
- elif ctx.level == 'c_class' and s.sy == 'IDENT' and s.systring == 'property':
- return p_property_decl(s)
- elif s.sy == 'pass' and ctx.level <> 'property':
- return p_pass_statement(s, with_newline = 1)
- else:
- if ctx.level in ('c_class', 'c_class_pxd', 'property'):
- s.error("Executable statement not allowed here")
- if s.sy == 'if':
- return p_if_statement(s)
- elif s.sy == 'while':
- return p_while_statement(s)
- elif s.sy == 'for':
- return p_for_statement(s)
- elif s.sy == 'try':
- return p_try_statement(s)
- elif s.sy == 'with':
- return p_with_statement(s)
- else:
- return p_simple_statement_list(s, ctx)
-
-def p_statement_list(s, ctx):
- # Parse a series of statements separated by newlines.
- pos = s.position()
- stats = []
- while s.sy not in ('DEDENT', 'EOF'):
- stats.append(p_statement(s, ctx))
- if len(stats) == 1:
- return stats[0]
- else:
- return Nodes.StatListNode(pos, stats = stats)
-
-def p_suite(s, ctx = Ctx(), with_doc = 0, with_pseudo_doc = 0):
- pos = s.position()
- s.expect(':')
- doc = None
- stmts = []
- if s.sy == 'NEWLINE':
- s.next()
- s.expect_indent()
- if with_doc or with_pseudo_doc:
- doc = p_doc_string(s)
- body = p_statement_list(s, ctx)
- s.expect_dedent()
- else:
- if ctx.api:
- error(s.pos, "'api' not allowed with this statement")
- if ctx.level in ('module', 'class', 'function', 'other'):
- body = p_simple_statement_list(s, ctx)
- else:
- body = p_pass_statement(s)
- s.expect_newline("Syntax error in declarations")
- if with_doc:
- return doc, body
- else:
- return body
-
-def p_c_base_type(s, self_flag = 0):
- # If self_flag is true, this is the base type for the
- # self argument of a C method of an extension type.
- if s.sy == '(':
- return p_c_complex_base_type(s)
- else:
- return p_c_simple_base_type(s, self_flag)
-
-def p_calling_convention(s):
- if s.sy == 'IDENT' and s.systring in calling_convention_words:
- result = s.systring
- s.next()
- return result
- else:
- return ""
-
-calling_convention_words = ("__stdcall", "__cdecl", "__fastcall")
-
-def p_c_complex_base_type(s):
- # s.sy == '('
- pos = s.position()
- s.next()
- base_type = p_c_base_type(s)
- declarator = p_c_declarator(s, empty = 1)
- s.expect(')')
- return Nodes.CComplexBaseTypeNode(pos,
- base_type = base_type, declarator = declarator)
-
-def p_c_simple_base_type(s, self_flag):
- #print "p_c_simple_base_type: self_flag =", self_flag
- is_basic = 0
- signed = 1
- longness = 0
- module_path = []
- pos = s.position()
- if looking_at_base_type(s):
- #print "p_c_simple_base_type: looking_at_base_type at", s.position()
- is_basic = 1
- signed, longness = p_sign_and_longness(s)
- if s.sy == 'IDENT' and s.systring in basic_c_type_names:
- name = s.systring
- s.next()
- else:
- name = 'int'
- elif s.looking_at_type_name() or looking_at_dotted_name(s):
- #print "p_c_simple_base_type: looking_at_type_name at", s.position()
- name = s.systring
- s.next()
- while s.sy == '.':
- module_path.append(name)
- s.next()
- name = p_ident(s)
- else:
- #print "p_c_simple_base_type: not looking at type at", s.position()
- name = None
- return Nodes.CSimpleBaseTypeNode(pos,
- name = name, module_path = module_path,
- is_basic_c_type = is_basic, signed = signed,
- longness = longness, is_self_arg = self_flag)
-
-def looking_at_type(s):
- return looking_at_base_type(s) or s.looking_at_type_name()
-
-def looking_at_base_type(s):
- #print "looking_at_base_type?", s.sy, s.systring, s.position()
- return s.sy == 'IDENT' and s.systring in base_type_start_words
-
-def looking_at_dotted_name(s):
- if s.sy == 'IDENT':
- name = s.systring
- s.next()
- result = s.sy == '.'
- s.put_back('IDENT', name)
- return result
- else:
- return 0
-
-basic_c_type_names = ("void", "char", "int", "float", "double") #,
- #"size_t", "Py_ssize_t")
-
-sign_and_longness_words = ("short", "long", "signed", "unsigned")
-
-base_type_start_words = \
- basic_c_type_names + sign_and_longness_words
-
-def p_sign_and_longness(s):
- signed = 1
- longness = 0
- while s.sy == 'IDENT' and s.systring in sign_and_longness_words:
- if s.systring == 'unsigned':
- signed = 0
- elif s.systring == 'signed':
- signed = 2
- elif s.systring == 'short':
- longness = -1
- elif s.systring == 'long':
- longness += 1
- s.next()
- return signed, longness
-
-def p_opt_cname(s):
- literal = p_opt_string_literal(s)
- if literal:
- _, cname = literal
- else:
- cname = None
- return cname
-
-def p_c_declarator(s, ctx = Ctx(), empty = 0, is_type = 0, cmethod_flag = 0, nonempty = 0,
- calling_convention_allowed = 0):
- # If empty is true, the declarator must be empty. If nonempty is true,
- # the declarator must be nonempty. Otherwise we don't care.
- # If cmethod_flag is true, then if this declarator declares
- # a function, it's a C method of an extension type.
- pos = s.position()
- if s.sy == '(':
- s.next()
- if s.sy == ')' or looking_at_type(s):
- base = Nodes.CNameDeclaratorNode(pos, name = "", cname = None)
- result = p_c_func_declarator(s, pos, ctx, base, cmethod_flag)
- else:
- result = p_c_declarator(s, ctx, empty = empty, is_type = is_type,
- cmethod_flag = cmethod_flag, nonempty = nonempty,
- calling_convention_allowed = 1)
- s.expect(')')
- else:
- result = p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag, nonempty)
- if not calling_convention_allowed and result.calling_convention and s.sy <> '(':
- error(s.position(), "%s on something that is not a function"
- % result.calling_convention)
- while s.sy in ('[', '('):
- pos = s.position()
- if s.sy == '[':
- result = p_c_array_declarator(s, result)
- else: # sy == '('
- s.next()
- result = p_c_func_declarator(s, pos, ctx, result, cmethod_flag)
- cmethod_flag = 0
- return result
-
-def p_c_array_declarator(s, base):
- pos = s.position()
- s.next() # '['
- if s.sy <> ']':
- dim = p_expr(s)
- else:
- dim = None
- s.expect(']')
- return Nodes.CArrayDeclaratorNode(pos, base = base, dimension = dim)
-
-def p_c_func_declarator(s, pos, ctx, base, cmethod_flag):
- # Opening paren has already been skipped
- args = p_c_arg_list(s, ctx, cmethod_flag = cmethod_flag,
- nonempty_declarators = 0)
- ellipsis = p_optional_ellipsis(s)
- s.expect(')')
- nogil = p_nogil(s)
- exc_val, exc_check = p_exception_value_clause(s)
- with_gil = p_with_gil(s)
- return Nodes.CFuncDeclaratorNode(pos,
- base = base, args = args, has_varargs = ellipsis,
- exception_value = exc_val, exception_check = exc_check,
- nogil = nogil or ctx.nogil or with_gil, with_gil = with_gil)
-
-def p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag, nonempty):
- pos = s.position()
- calling_convention = p_calling_convention(s)
- if s.sy == '*':
- s.next()
- base = p_c_declarator(s, ctx, empty = empty, is_type = is_type,
- cmethod_flag = cmethod_flag, nonempty = nonempty)
- result = Nodes.CPtrDeclaratorNode(pos,
- base = base)
- elif s.sy == '**': # scanner returns this as a single token
- s.next()
- base = p_c_declarator(s, ctx, empty = empty, is_type = is_type,
- cmethod_flag = cmethod_flag, nonempty = nonempty)
- result = Nodes.CPtrDeclaratorNode(pos,
- base = Nodes.CPtrDeclaratorNode(pos,
- base = base))
- else:
- if s.sy == 'IDENT':
- name = s.systring
- if is_type:
- s.add_type_name(name)
- if empty:
- error(s.position(), "Declarator should be empty")
- s.next()
- cname = p_opt_cname(s)
- else:
- if nonempty:
- error(s.position(), "Empty declarator")
- name = ""
- cname = None
- result = Nodes.CNameDeclaratorNode(pos,
- name = name, cname = cname)
- result.calling_convention = calling_convention
- return result
-
-def p_nogil(s):
- if s.sy == 'IDENT' and s.systring == 'nogil':
- s.next()
- return 1
- else:
- return 0
-
-def p_with_gil(s):
- if s.sy == 'with':
- s.next()
- s.expect_keyword('gil')
- return 1
- else:
- return 0
-
-def p_exception_value_clause(s):
- exc_val = None
- exc_check = 0
- if s.sy == 'except':
- s.next()
- if s.sy == '*':
- exc_check = 1
- s.next()
- else:
- if s.sy == '?':
- exc_check = 1
- s.next()
- exc_val = p_simple_expr(s)
- return exc_val, exc_check
-
-c_arg_list_terminators = ('*', '**', '.', ')')
-
-def p_c_arg_list(s, ctx = Ctx(), in_pyfunc = 0, cmethod_flag = 0, nonempty_declarators = 0,
- kw_only = 0):
- # Comma-separated list of C argument declarations, possibly empty.
- # May have a trailing comma.
- args = []
- is_self_arg = cmethod_flag
- while s.sy not in c_arg_list_terminators:
- args.append(p_c_arg_decl(s, ctx, in_pyfunc, is_self_arg,
- nonempty = nonempty_declarators, kw_only = kw_only))
- if s.sy <> ',':
- break
- s.next()
- is_self_arg = 0
- return args
-
-def p_optional_ellipsis(s):
- if s.sy == '.':
- expect_ellipsis(s)
- return 1
- else:
- return 0
-
-def p_c_arg_decl(s, ctx, in_pyfunc, cmethod_flag = 0, nonempty = 0, kw_only = 0):
- pos = s.position()
- allow_none = None
- #not_none = 0
- default = None
- base_type = p_c_base_type(s, cmethod_flag)
- declarator = p_c_declarator(s, ctx, nonempty = nonempty)
- if s.sy in ('or', 'not'):
- or_not = s.sy
- s.next()
- if s.sy == 'IDENT' and s.systring == 'None':
- s.next()
- else:
- s.error("Expected 'None'")
- if not in_pyfunc:
- error(pos, "'%s None' only allowed in Python functions" % or_not)
- allow_none = or_not == 'or'
- if s.sy == '=':
- s.next()
- default = p_simple_expr(s)
- return Nodes.CArgDeclNode(pos,
- base_type = base_type,
- declarator = declarator,
- allow_none = allow_none,
- default = default,
- kw_only = kw_only)
-
-def p_api(s):
- if s.sy == 'IDENT' and s.systring == 'api':
- s.next()
- return 1
- else:
- return 0
-
-def p_cdef_statement(s, ctx):
- ctx = ctx(cdef_flag = 1)
- pos = s.position()
- ctx.visibility = p_visibility(s, ctx.visibility)
- ctx.api = ctx.api or p_api(s)
- if ctx.api:
- if ctx.visibility not in ('private', 'public'):
- error(pos, "Cannot combine 'api' with '%s'" % visibility)
- if ctx.visibility == 'extern' and s.sy == 'from':
- return p_cdef_extern_block(s, pos, ctx)
- if p_nogil(s):
- ctx.nogil = 1
- if s.sy == ':':
- return p_cdef_block(s, ctx)
- elif s.sy == 'class':
- if ctx.level not in ('module', 'module_pxd'):
- error(pos, "Extension type definition not allowed here")
- #if api:
- # error(pos, "'api' not allowed with extension class")
- return p_c_class_definition(s, pos, ctx)
- elif s.sy == 'IDENT' and s.systring in struct_union_or_enum:
- if ctx.level not in ('module', 'module_pxd'):
- error(pos, "C struct/union/enum definition not allowed here")
- #if ctx.visibility == 'public':
- # error(pos, "Public struct/union/enum definition not implemented")
- #if ctx.api:
- # error(pos, "'api' not allowed with '%s'" % s.systring)
- if s.systring == "enum":
- return p_c_enum_definition(s, pos, ctx)
- else:
- return p_c_struct_or_union_definition(s, pos, ctx)
- elif s.sy == 'pass':
- node = p_pass_statement(s)
- s.expect_newline('Expected a newline')
- return node
- else:
- return p_c_func_or_var_declaration(s, pos, ctx)
-
-def p_cdef_block(s, ctx):
- return p_suite(s, ctx(cdef_flag = 1))
-
-def p_cdef_extern_block(s, pos, ctx):
- include_file = None
- s.expect('from')
- if s.sy == '*':
- s.next()
- else:
- _, include_file = p_string_literal(s)
- ctx = ctx(cdef_flag = 1, visibility = 'extern', extern_from = True)
- if p_nogil(s):
- ctx.nogil = 1
- body = p_suite(s, ctx)
- return Nodes.CDefExternNode(pos,
- include_file = include_file,
- body = body)
-
-struct_union_or_enum = (
- "struct", "union", "enum"
-)
-
-def p_c_enum_definition(s, pos, ctx):
- # s.sy == ident 'enum'
- s.next()
- if s.sy == 'IDENT':
- name = s.systring
- s.next()
- s.add_type_name(name)
- cname = p_opt_cname(s)
- else:
- name = None
- cname = None
- items = None
- s.expect(':')
- items = []
- if s.sy <> 'NEWLINE':
- p_c_enum_line(s, items)
- else:
- s.next() # 'NEWLINE'
- s.expect_indent()
- while s.sy not in ('DEDENT', 'EOF'):
- p_c_enum_line(s, items)
- s.expect_dedent()
- return Nodes.CEnumDefNode(pos, name = name, cname = cname, items = items,
- typedef_flag = ctx.typedef_flag,
- visibility = ctx.visibility,
- in_pxd = ctx.level == 'module_pxd')
-
-def p_c_enum_line(s, items):
- if s.sy <> 'pass':
- p_c_enum_item(s, items)
- while s.sy == ',':
- s.next()
- if s.sy in ('NEWLINE', 'EOF'):
- break
- p_c_enum_item(s, items)
- else:
- s.next()
- s.expect_newline("Syntax error in enum item list")
-
-def p_c_enum_item(s, items):
- pos = s.position()
- name = p_ident(s)
- cname = p_opt_cname(s)
- value = None
- if s.sy == '=':
- s.next()
- value = p_simple_expr(s)
- items.append(Nodes.CEnumDefItemNode(pos,
- name = name, cname = cname, value = value))
-
-def p_c_struct_or_union_definition(s, pos, ctx):
- # s.sy == ident 'struct' or 'union'
- ctx.cplus_check(pos)
- kind = s.systring
- s.next()
- module_path, name = p_qualified_name(s)
- bases = []
- if s.sy == '(':
- s.next()
- while s.sy == 'IDENT':
- bases.append(p_qualified_name(s))
- if s.sy <> ',':
- break
- s.next()
- s.expect(')')
- if bases and not ctx.cplus_flag:
- error(s, "Only C++ struct may have bases")
- cname = p_opt_cname(s)
- s.add_type_name(name)
- attributes = None
- if s.sy == ':':
- s.next()
- s.expect('NEWLINE')
- s.expect_indent()
- attributes = []
- body_ctx = Ctx()
- while s.sy <> 'DEDENT':
- if s.sy <> 'pass':
- attributes.append(p_c_func_or_var_declaration(s,
- s.position(), body_ctx))
- else:
- s.next()
- s.expect_newline("Expected a newline")
- s.expect_dedent()
- else:
- s.expect_newline("Syntax error in struct or union definition")
- return Nodes.CStructOrUnionDefNode(pos,
- name = name, cname = cname, module_path = module_path,
- kind = kind, attributes = attributes,
- typedef_flag = ctx.typedef_flag,
- visibility = ctx.visibility,
- in_pxd = ctx.level == 'module_pxd',
- cplus_flag = ctx.cplus_flag,
- bases = bases)
-
-def p_visibility(s, prev_visibility):
- pos = s.position()
- visibility = prev_visibility
- if s.sy == 'IDENT' and s.systring in ('extern', 'public', 'readonly'):
- visibility = s.systring
- if prev_visibility <> 'private' and visibility <> prev_visibility:
- s.error("Conflicting visibility options '%s' and '%s'"
- % (prev_visibility, visibility))
- s.next()
- return visibility
-
-def p_c_func_or_var_declaration(s, pos, ctx):
- cmethod_flag = ctx.level in ('c_class', 'c_class_pxd')
- base_type = p_c_base_type(s)
- declarator = p_c_declarator(s, ctx, cmethod_flag = cmethod_flag, nonempty = 1)
- if s.sy == ':':
- if ctx.level not in ('module', 'c_class'):
- s.error("C function definition not allowed here")
- suite = p_suite(s, Ctx(level = 'function'), with_pseudo_doc = 1)
- result = Nodes.CFuncDefNode(pos,
- visibility = ctx.visibility,
- base_type = base_type,
- declarator = declarator,
- body = suite,
- api = ctx.api)
- else:
- #if api:
- # error(pos, "'api' not allowed with variable declaration")
- declarators = [declarator]
- while s.sy == ',':
- s.next()
- if s.sy == 'NEWLINE':
- break
- declarator = p_c_declarator(s, ctx, cmethod_flag = cmethod_flag, nonempty = 1)
- declarators.append(declarator)
- s.expect_newline("Syntax error in C variable declaration")
- result = Nodes.CVarDefNode(pos,
- visibility = ctx.visibility,
- base_type = base_type,
- declarators = declarators,
- in_pxd = ctx.level == 'module_pxd',
- api = ctx.api)
- return result
-
-def p_ctypedef_statement(s, ctx):
- # s.sy == 'ctypedef'
- pos = s.position()
- s.next()
- visibility = p_visibility(s, ctx.visibility)
- api = p_api(s)
- ctx = ctx(typedef_flag = 1, visibility = visibility)
- if api:
- ctx.api = 1
- if s.sy == 'class':
- return p_c_class_definition(s, pos, ctx)
- elif s.sy == 'IDENT' and s.systring in ('struct', 'union', 'enum'):
- if s.systring == 'enum':
- return p_c_enum_definition(s, pos, ctx)
- else:
- return p_c_struct_or_union_definition(s, pos, ctx)
- else:
- base_type = p_c_base_type(s)
- declarator = p_c_declarator(s, ctx, is_type = 1, nonempty = 1)
- s.expect_newline("Syntax error in ctypedef statement")
- return Nodes.CTypeDefNode(pos,
- base_type = base_type, declarator = declarator,
- visibility = ctx.visibility,
- in_pxd = ctx.level == 'module_pxd')
-
-def p_def_statement(s):
- # s.sy == 'def'
- pos = s.position()
- s.next()
- name = p_ident(s)
- #args = []
- s.expect('(');
- args = p_c_arg_list(s, in_pyfunc = 1, nonempty_declarators = 1)
- star_arg = None
- starstar_arg = None
- if s.sy == '*':
- s.next()
- if s.sy == 'IDENT':
- star_arg = p_py_arg_decl(s)
- if s.sy == ',':
- s.next()
- args.extend(p_c_arg_list(s, in_pyfunc = 1,
- nonempty_declarators = 1, kw_only = 1))
- elif s.sy <>')':
- s.error("Syntax error in Python function argument list")
- if s.sy == '**':
- s.next()
- starstar_arg = p_py_arg_decl(s)
- s.expect(')')
- if p_nogil(s):
- error(s.pos, "Python function cannot be declared nogil")
- doc, body = p_suite(s, Ctx(level = 'function'), with_doc = 1)
- return Nodes.DefNode(pos, name = name, args = args,
- star_arg = star_arg, starstar_arg = starstar_arg,
- doc = doc, body = body)
-
-def p_py_arg_decl(s):
- pos = s.position()
- name = p_ident(s)
- return Nodes.PyArgDeclNode(pos, name = name)
-
-def p_class_statement(s):
- # s.sy == 'class'
- pos = s.position()
- s.next()
- class_name = p_ident(s)
- if s.sy == '(':
- s.next()
- base_list = p_simple_expr_list(s)
- s.expect(')')
- else:
- base_list = []
- doc, body = p_suite(s, Ctx(level = 'class'), with_doc = 1)
- return Nodes.PyClassDefNode(pos,
- name = class_name,
- bases = ExprNodes.TupleNode(pos, args = base_list),
- doc = doc, body = body)
-
-def p_qualified_name(s):
- path = []
- name = p_ident(s)
- while s.sy == '.':
- s.next()
- path.append(name)
- name = p_ident(s)
- return path, name
-
-class CClassOptions:
-
- objstruct_cname = None
- typeobj_cname = None
- no_gc = 0
-
-
-def p_c_class_definition(s, pos, ctx):
- # s.sy == 'class'
- s.next()
- module_path, class_name = p_qualified_name(s)
- if module_path and s.sy == 'IDENT' and s.systring == 'as':
- s.next()
- as_name = p_ident(s)
- else:
- as_name = class_name
- s.add_type_name(as_name)
- options = CClassOptions()
- base_class_module = None
- base_class_name = None
- if s.sy == '(':
- s.next()
- base_class_path, base_class_name = p_qualified_name(s)
- if s.sy == ',':
- s.error("C class may only have one base class")
- s.expect(')')
- base_class_module = ".".join(base_class_path)
- if s.sy == '[':
- p_c_class_options(s, ctx, options)
- if s.sy == ':':
- if ctx.level == 'module_pxd':
- body_level = 'c_class_pxd'
- else:
- body_level = 'c_class'
- doc, body = p_suite(s, Ctx(level = body_level), with_doc = 1)
- else:
- s.expect_newline("Syntax error in C class definition")
- doc = None
- body = None
- if ctx.visibility == 'extern':
- if not module_path:
- error(pos, "Module name required for 'extern' C class")
- if options.typeobj_cname:
- error(pos, "Type object name specification not allowed for 'extern' C class")
- elif ctx.visibility == 'public':
- if not options.objstruct_cname:
- error(pos, "Object struct name specification required for 'public' C class")
- if not options.typeobj_cname:
- error(pos, "Type object name specification required for 'public' C class")
- else:
- if ctx.api:
- error(pos, "Only 'public' C class can be declared 'api'")
- return Nodes.CClassDefNode(pos,
- visibility = ctx.visibility,
- typedef_flag = ctx.typedef_flag,
- api = ctx.api,
- module_name = ".".join(module_path),
- class_name = class_name,
- as_name = as_name,
- base_class_module = base_class_module,
- base_class_name = base_class_name,
- options = options,
- in_pxd = ctx.level == 'module_pxd',
- doc = doc,
- body = body)
-
-def p_c_class_options(s, ctx, options):
- s.expect('[')
- while 1:
- if s.sy <> 'IDENT':
- break
- if s.systring == 'object':
- if ctx.visibility not in ('public', 'extern'):
- error(s.position(), "Object name option only allowed for 'public' or 'extern' C class")
- s.next()
- options.objstruct_cname = p_ident(s)
- elif s.systring == 'type':
- if ctx.visibility not in ('public', 'extern'):
- error(s.position(), "Type name option only allowed for 'public' or 'extern' C class")
- s.next()
- options.typeobj_cname = p_ident(s)
- elif s.systring == 'nogc':
- s.next()
- options.no_gc = 1
- else:
- s.error("Unrecognised C class option '%s'" % s.systring)
- if s.sy <> ',':
- break
- s.next()
- s.expect(']', "Expected a C class option")
-
-def p_property_decl(s):
- pos = s.position()
- s.next() # 'property'
- name = p_ident(s)
- doc, body = p_suite(s, Ctx(level = 'property'), with_doc = 1)
- return Nodes.PropertyNode(pos, name = name, doc = doc, body = body)
-
-def p_doc_string(s):
- if s.sy == 'STRING' or s.sy == 'BEGIN_STRING':
- _, result = p_cat_string_literal(s)
- if s.sy <> 'EOF':
- s.expect_newline("Syntax error in doc string")
- return result
- else:
- return None
-
-def p_module(s, pxd):
- s.add_type_name("object")
- pos = s.position()
- doc = p_doc_string(s)
- if pxd:
- level = 'module_pxd'
- else:
- level = 'module'
- body = p_statement_list(s, Ctx(level = level))
- if s.sy <> 'EOF':
- s.error("Syntax error in statement [%s,%s]" % (
- repr(s.sy), repr(s.systring)))
- return ModuleNode(pos, doc = doc, body = body)
-
-#----------------------------------------------
-#
-# Debugging
-#
-#----------------------------------------------
-
-def print_parse_tree(f, node, level, key = None):
- ind = " " * level
- if node:
- f.write(ind)
- if key:
- f.write("%s: " % key)
- t = type(node)
- if t == TupleType:
- f.write("(%s @ %s\n" % (node[0], node[1]))
- for i in xrange(2, len(node)):
- print_parse_tree(f, node[i], level+1)
- f.write("%s)\n" % ind)
- return
- elif isinstance(node, Node):
- try:
- tag = node.tag
- except AttributeError:
- tag = node.__class__.__name__
- f.write("%s @ %s\n" % (tag, node.pos))
- for name, value in node.__dict__.items():
- if name <> 'tag' and name <> 'pos':
- print_parse_tree(f, value, level+1, name)
- return
- elif t == ListType:
- f.write("[\n")
- for i in xrange(len(node)):
- print_parse_tree(f, node[i], level+1)
- f.write("%s]\n" % ind)
- return
- f.write("%s%s\n" % (ind, node))
-