diff options
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.py | 2142 |
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)) - |