-# cython: auto_cpdef=True, infer_types=True
+# cython: auto_cpdef=True, infer_types=True, language_level=3, py2_import=True
#
# Pyrex Parser
#
pos = s.position()
op = p_cmp_op(s)
n2 = p_starred_expr(s)
- n1 = ExprNodes.PrimaryCmpNode(pos,
+ n1 = ExprNodes.PrimaryCmpNode(pos,
operator = op, operand1 = n1, operand2 = n2)
if s.sy in comparison_ops:
n1.cascade = p_cascaded_cmp(s)
pos = s.position()
op = p_cmp_op(s)
n2 = p_starred_expr(s)
- result = ExprNodes.CascadedCmpNode(pos,
+ result = ExprNodes.CascadedCmpNode(pos,
operator = op, operand2 = n2)
if s.sy in comparison_ops:
result.cascade = p_cascaded_cmp(s)
if op == '<>':
op = '!='
return op
-
+
comparison_ops = (
- '<', '>', '==', '>=', '<=', '<>', '!=',
+ '<', '>', '==', '>=', '<=', '<>', '!=',
'in', 'is', 'not'
)
#factor: ('+'|'-'|'~'|'&'|typecast|sizeof) factor | power
def p_factor(s):
+ # little indirection for C-ification purposes
+ return _p_factor(s)
+
+def _p_factor(s):
sy = s.sy
if sy in ('+', '-', '~'):
op = s.sy
typecheck = 0
s.expect(">")
operand = p_factor(s)
- return ExprNodes.TypecastNode(pos,
- base_type = base_type,
+ return ExprNodes.TypecastNode(pos,
+ base_type = base_type,
declarator = declarator,
operand = operand,
typecheck = typecheck)
s.next()
s.expect('(')
# Here we decide if we are looking at an expression or type
- # If it is actually a type, but parsable as an expression,
- # we treat it as an expression here.
+ # If it is actually a type, but parsable as an expression,
+ # we treat it as an expression here.
if looking_at_expr(s):
operand = p_test(s)
node = ExprNodes.SizeofVarNode(pos, operand = operand)
else:
base_type = p_c_base_type(s)
declarator = p_c_declarator(s, empty = 1)
- node = ExprNodes.SizeofTypeNode(pos,
+ node = ExprNodes.SizeofTypeNode(pos,
base_type = base_type, declarator = declarator)
s.expect(')')
return node
else: # s.sy == '.'
s.next()
name = EncodedString( p_ident(s) )
- return ExprNodes.AttributeNode(pos,
+ return ExprNodes.AttributeNode(pos,
obj = node1, attribute = name)
# arglist: argument (',' argument)* [',']
else:
arg_tuple, keyword_dict = p_call_build_packed_args(
pos, positional_args, keyword_args, star_arg)
- return ExprNodes.GeneralCallNode(pos,
+ return ExprNodes.GeneralCallNode(pos,
function = function,
positional_args = arg_tuple,
keyword_args = keyword_dict,
subscripts = p_subscript_list(s)
if len(subscripts) == 1 and len(subscripts[0]) == 2:
start, stop = subscripts[0]
- result = ExprNodes.SliceIndexNode(pos,
+ result = ExprNodes.SliceIndexNode(pos,
base = base, start = start, stop = stop)
else:
indexes = make_slice_nodes(pos, subscripts)
return ExprNodes.BoolNode(pos, value=True)
elif name == "False":
return ExprNodes.BoolNode(pos, value=False)
- elif name == "NULL":
+ elif name == "NULL" and not s.in_python_file:
return ExprNodes.NullNode(pos)
else:
return p_name(s, name)
has_non_ASCII_literal_characters = True
elif sy == 'ESCAPE':
if is_raw:
- if systr == u'\\\n':
- chars.append(u'\\\n')
- elif systr == u'\\\"':
- chars.append(u'"')
- elif systr == u'\\\'':
- chars.append(u"'")
- else:
- chars.append(systr)
- if is_python3_source and not has_non_ASCII_literal_characters \
- and check_for_non_ascii_characters(systr):
- has_non_ASCII_literal_characters = True
+ chars.append(systr)
+ if is_python3_source and not has_non_ASCII_literal_characters \
+ and check_for_non_ascii_characters(systr):
+ has_non_ASCII_literal_characters = True
else:
c = systr[1]
if c in u"01234567":
elif c == u'\n':
pass
elif c == u'x':
- chars.append_charval( int(systr[2:], 16) )
+ if len(systr) == 4:
+ chars.append_charval( int(systr[2:], 16) )
+ else:
+ s.error("Invalid hex escape '%s'" % systr)
elif c in u'Uu':
if kind in ('u', ''):
- chrval = int(systr[2:], 16)
- if chrval > 1114111: # sys.maxunicode:
- s.error("Invalid unicode escape '%s'" % systr,
- pos = pos)
+ if len(systr) in (6,10):
+ chrval = int(systr[2:], 16)
+ if chrval > 1114111: # sys.maxunicode:
+ s.error("Invalid unicode escape '%s'" % systr)
+ else:
+ s.error("Invalid unicode escape '%s'" % systr)
else:
- # unicode escapes in plain byte strings are not unescaped
+ # unicode escapes in byte strings are not unescaped
chrval = None
chars.append_uescape(chrval, systr)
else:
# comp_iter ::= comp_for | comp_if
# comp_for ::= "for" expression_list "in" testlist [comp_iter]
# comp_if ::= "if" test [comp_iter]
-
+
def p_list_maker(s):
# s.sy == '['
pos = s.position()
exprs = [expr]
s.expect(']')
return ExprNodes.ListNode(pos, args = exprs)
-
+
def p_comp_iter(s, body):
if s.sy == 'for':
return p_comp_for(s, body)
pos = s.position()
s.next()
kw = p_for_bounds(s, allow_testlist=False)
- kw['else_clause'] = None
- kw['body'] = p_comp_iter(s, body)
+ kw.update(dict(else_clause = None, body = p_comp_iter(s, body)))
return Nodes.ForStatNode(pos, **kw)
-
+
def p_comp_if(s, body):
# s.sy == 'if'
pos = s.position()
s.next()
test = p_test_nocond(s)
- return Nodes.IfStatNode(pos,
+ return Nodes.IfStatNode(pos,
if_clauses = [Nodes.IfClauseNode(pos, condition = test,
body = p_comp_iter(s, body))],
else_clause = None )
break
s.next()
return exprs
-
+
#testlist: test (',' test)* [',']
names = p_ident_list(s)
return Nodes.GlobalNode(pos, names = names)
+def p_nonlocal_statement(s):
+ pos = s.position()
+ s.next()
+ names = p_ident_list(s)
+ return Nodes.NonlocalNode(pos, names = names)
+
def p_expression_or_assignment(s):
expr_list = [p_testlist_star_expr(s)]
while s.sy == '=':
rhs = expr_list[-1]
if len(expr_list) == 2:
- return Nodes.SingleAssignmentNode(rhs.pos,
+ return Nodes.SingleAssignmentNode(rhs.pos,
lhs = expr_list[0], rhs = rhs)
else:
return Nodes.CascadedAssignmentNode(rhs.pos,
s.next()
exc_tb = p_test(s)
if exc_type or exc_value or exc_tb:
- return Nodes.RaiseStatNode(pos,
+ return Nodes.RaiseStatNode(pos,
exc_type = exc_type,
exc_value = exc_value,
exc_tb = exc_tb)
for pos, target_name, dotted_name, as_name in items:
dotted_name = EncodedString(dotted_name)
if kind == 'cimport':
- stat = Nodes.CImportStatNode(pos,
+ stat = Nodes.CImportStatNode(pos,
module_name = dotted_name,
as_name = as_name)
else:
else:
name_list = None
stat = Nodes.SingleAssignmentNode(pos,
- lhs = ExprNodes.NameNode(pos,
+ lhs = ExprNodes.NameNode(pos,
name = as_name or target_name),
- rhs = ExprNodes.ImportNode(pos,
+ rhs = ExprNodes.ImportNode(pos,
module_name = ExprNodes.IdentifierStringNode(
pos, value = dotted_name),
+ level = None,
name_list = name_list))
stats.append(stat)
return Nodes.StatListNode(pos, stats = stats)
# s.sy == 'from'
pos = s.position()
s.next()
- (dotted_name_pos, _, dotted_name, _) = \
- p_dotted_name(s, as_allowed = 0)
+ if s.sy == '.':
+ # count relative import level
+ level = 0
+ while s.sy == '.':
+ level += 1
+ s.next()
+ if s.sy == 'cimport':
+ s.error("Relative cimport is not supported yet")
+ else:
+ level = None
+ if level is not None and s.sy == 'import':
+ # we are dealing with "from .. import foo, bar"
+ dotted_name_pos, dotted_name = s.position(), ''
+ elif level is not None and s.sy == 'cimport':
+ # "from .. cimport"
+ s.error("Relative cimport is not supported yet")
+ else:
+ (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'")
+
is_cimport = kind == 'cimport'
is_parenthesized = False
if s.sy == '*':
if dotted_name == '__future__':
if not first_statement:
s.error("from __future__ imports must occur at the beginning of the file")
+ elif level is not None:
+ s.error("invalid syntax")
else:
for (name_pos, name, as_name, kind) in imported_names:
if name == "braces":
ExprNodes.IdentifierStringNode(name_pos, value = encoded_name))
items.append(
(name,
- ExprNodes.NameNode(name_pos,
+ ExprNodes.NameNode(name_pos,
name = as_name or name)))
import_list = ExprNodes.ListNode(
imported_names[0][0], args = imported_name_strings)
return Nodes.FromImportStatNode(pos,
module = ExprNodes.ImportNode(dotted_name_pos,
module_name = ExprNodes.IdentifierStringNode(pos, value = dotted_name),
+ level = level,
name_list = import_list),
items = items)
test = p_test(s)
body = p_suite(s)
else_clause = p_else_clause(s)
- return Nodes.WhileStatNode(pos,
- condition = test, body = body,
+ return Nodes.WhileStatNode(pos,
+ condition = test, body = body,
else_clause = else_clause)
def p_for_statement(s):
pos = s.position()
s.next()
kw = p_for_bounds(s, allow_testlist=True)
- kw['body'] = p_suite(s)
- kw['else_clause'] = p_else_clause(s)
+ body = p_suite(s)
+ else_clause = p_else_clause(s)
+ kw.update(dict(body = body, else_clause = else_clause))
return Nodes.ForStatNode(pos, **kw)
-
+
def p_for_bounds(s, allow_testlist=True):
target = p_for_target(s)
if s.sy == 'in':
s.next()
iterator = p_for_iterator(s, allow_testlist)
- return { 'target': target, 'iterator': iterator }
+ return dict( target = target, iterator = iterator )
elif not s.in_python_file:
if s.sy == 'from':
s.next()
target = ExprNodes.NameNode(name2_pos, name = name2)
else:
if not target.is_name:
- error(target.pos,
+ error(target.pos,
"Target of for-from statement must be a variable name")
elif name2 != target.name:
error(name2_pos,
if rel1[0] != rel2[0]:
error(rel2_pos,
"Relation directions in for-from do not match")
- return {'target': target,
- 'bound1': bound1,
- 'relation1': rel1,
- 'relation2': rel2,
- 'bound2': bound2,
- 'step': step }
+ return dict(target = target,
+ bound1 = bound1,
+ relation1 = rel1,
+ relation2 = rel2,
+ bound2 = bound2,
+ step = step,
+ )
else:
s.expect('in')
return {}
s.error("Expected one of '<', '<=', '>' '>='")
def p_for_from_step(s):
- if s.sy == 'by':
+ if s.sy == 'IDENT' and s.systring == 'by':
s.next()
step = p_bit_expr(s)
return step
body = p_with_items(s)
else:
body = p_suite(s)
- return Nodes.WithStatNode(pos, manager = manager,
+ return Nodes.WithStatNode(pos, manager = manager,
target = target, body = body)
def p_with_template(s):
#print "p_simple_statement:", s.sy, s.systring ###
if s.sy == 'global':
node = p_global_statement(s)
+ elif s.sy == 'nonlocal':
+ node = p_nonlocal_statement(s)
elif s.sy == 'print':
node = p_print_statement(s)
elif s.sy == 'exec':
# Parse a series of simple statements on one line
# separated by semicolons.
stat = p_simple_statement(s, first_statement = first_statement)
- if s.sy == ';':
- stats = [stat]
- while s.sy == ';':
- #print "p_simple_statement_list: maybe more to follow" ###
- s.next()
- if s.sy in ('NEWLINE', 'EOF'):
- break
- stats.append(p_simple_statement(s))
- stat = Nodes.StatListNode(stats[0].pos, stats = stats)
+ pos = stat.pos
+ stats = []
+ if not isinstance(stat, Nodes.PassStatNode):
+ stats.append(stat)
+ while s.sy == ';':
+ #print "p_simple_statement_list: maybe more to follow" ###
+ s.next()
+ if s.sy in ('NEWLINE', 'EOF'):
+ break
+ stat = p_simple_statement(s, first_statement = first_statement)
+ if isinstance(stat, Nodes.PassStatNode):
+ continue
+ stats.append(stat)
+ first_statement = False
+
+ if not stats:
+ stat = Nodes.PassStatNode(pos)
+ elif len(stats) == 1:
+ stat = stats[0]
+ else:
+ stat = Nodes.StatListNode(pos, stats = stats)
s.expect_newline("Syntax error in simple statement list")
return stat
return p_IF_statement(s, ctx)
elif s.sy == 'DECORATOR':
if ctx.level not in ('module', 'class', 'c_class', 'function', 'property', 'module_pxd', 'c_class_pxd'):
- print ctx.level
s.error('decorator not allowed here')
s.level = ctx.level
decorators = p_decorators(s)
pos = s.position()
stats = []
while s.sy not in ('DEDENT', 'EOF'):
- stats.append(p_statement(s, ctx, first_statement = first_statement))
- first_statement = 0
- if len(stats) == 1:
+ stat = p_statement(s, ctx, first_statement = first_statement)
+ if isinstance(stat, Nodes.PassStatNode):
+ continue
+ stats.append(stat)
+ first_statement = False
+ if not stats:
+ return Nodes.PassStatNode(pos)
+ elif len(stats) == 1:
return stats[0]
else:
return Nodes.StatListNode(pos, stats = stats)
else:
base_type = p_c_base_type(s, templates = templates)
declarator = p_c_declarator(s, empty = 1)
- arg = Nodes.CComplexBaseTypeNode(base_type.pos,
+ arg = Nodes.CComplexBaseTypeNode(base_type.pos,
base_type = base_type, declarator = declarator)
parsed_type = True
keyword_node = ExprNodes.IdentifierStringNode(
arg.pos, value = EncodedString(ident))
keyword_args.append((keyword_node, arg))
was_keyword = True
-
+
else:
if looking_at_expr(s):
arg = p_test(s)
else:
base_type = p_c_base_type(s, templates = templates)
declarator = p_c_declarator(s, empty = 1)
- arg = Nodes.CComplexBaseTypeNode(base_type.pos,
+ arg = Nodes.CComplexBaseTypeNode(base_type.pos,
base_type = base_type, declarator = declarator)
parsed_type = True
positional_args.append(arg)
base_type = p_c_base_type(s)
declarator = p_c_declarator(s, empty = 1)
s.expect(')')
- return Nodes.CComplexBaseTypeNode(pos,
+ return Nodes.CComplexBaseTypeNode(pos,
base_type = base_type, declarator = declarator)
def p_c_simple_base_type(s, self_flag, nonempty, templates = None):
name = s.systring
s.next()
else:
- name = 'int'
+ name = 'int' # long [int], short [int], long [int] complex, etc.
if s.sy == 'IDENT' and s.systring == 'complex':
complex = 1
s.next()
name = s.systring
s.next()
if nonempty and s.sy != 'IDENT':
- # Make sure this is not a declaration of a variable or function.
+ # Make sure this is not a declaration of a variable or function.
if s.sy == '(':
s.next()
if s.sy == '*' or s.sy == '**' or s.sy == '&':
s.put_back('IDENT', name)
name = None
- type_node = Nodes.CSimpleBaseTypeNode(pos,
+ type_node = Nodes.CSimpleBaseTypeNode(pos,
name = name, module_path = module_path,
is_basic_c_type = is_basic, signed = signed,
- complex = complex, longness = longness,
+ complex = complex, longness = longness,
is_self_arg = self_flag, templates = templates)
if s.sy == '[':
type_node = p_buffer_or_template(s, type_node, templates)
-
+
if s.sy == '.':
s.next()
name = p_ident(s)
type_node = Nodes.CNestedBaseTypeNode(pos, base_type = type_node, name = name)
-
+
return type_node
def p_buffer_or_template(s, base_type_node, templates):
# s.sy == '['
pos = s.position()
s.next()
- # Note that buffer_positional_options_count=1, so the only positional argument is dtype.
- # For templated types, all parameters are types.
+ # Note that buffer_positional_options_count=1, so the only positional argument is dtype.
+ # For templated types, all parameters are types.
positional_args, keyword_args = (
p_positional_and_keyword_args(s, (']',), templates)
)
keyword_args = keyword_dict,
base_type_node = base_type_node)
return result
-
+
def looking_at_name(s):
return s.sy == 'IDENT' and not s.systring in calling_convention_words
is_type = True
elif s.sy == '*' or s.sy == '**':
s.next()
- is_type = s.sy == ')'
+ is_type = s.sy in (')', ']')
s.put_back(*saved)
elif s.sy == '(':
s.next()
special_basic_c_types = {
# name : (signed, longness)
"Py_UNICODE" : (0, 0),
+ "Py_UCS4" : (0, 0),
"Py_ssize_t" : (2, 0),
"ssize_t" : (2, 0),
"size_t" : (0, 0),
nogil = p_nogil(s)
exc_val, exc_check = p_exception_value_clause(s)
with_gil = p_with_gil(s)
- return Nodes.CFuncDeclaratorNode(pos,
+ 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)
supported_overloaded_operators = cython.set([
- '+', '-', '*', '/', '%',
+ '+', '-', '*', '/', '%',
'++', '--', '~', '|', '&', '^', '<<', '>>', ',',
'==', '!=', '>=', '>', '<=', '<',
'[]', '()',
base = p_c_declarator(s, ctx, empty = empty, is_type = is_type,
cmethod_flag = cmethod_flag,
assignable = assignable, nonempty = nonempty)
- result = Nodes.CPtrDeclaratorNode(pos,
+ result = Nodes.CPtrDeclaratorNode(pos,
base = base)
elif s.sy == '**': # scanner returns this as a single token
s.next()
return Nodes.CEnumDefNode(
pos, name = name, cname = cname, items = items,
typedef_flag = ctx.typedef_flag, visibility = ctx.visibility,
- in_pxd = ctx.level == 'module_pxd')
+ api = ctx.api, in_pxd = ctx.level == 'module_pxd')
def p_c_enum_line(s, ctx, items):
if s.sy != 'pass':
if s.sy == '=':
s.next()
value = p_test(s)
- items.append(Nodes.CEnumDefItemNode(pos,
+ items.append(Nodes.CEnumDefItemNode(pos,
name = name, cname = cname, value = value))
def p_c_struct_or_union_definition(s, pos, ctx):
s.expect_dedent()
else:
s.expect_newline("Syntax error in struct or union definition")
- return Nodes.CStructOrUnionDefNode(pos,
+ return Nodes.CStructOrUnionDefNode(pos,
name = name, cname = cname, kind = kind, attributes = attributes,
typedef_flag = ctx.typedef_flag, visibility = ctx.visibility,
- in_pxd = ctx.level == 'module_pxd', packed = packed)
+ api = ctx.api, in_pxd = ctx.level == 'module_pxd', packed = packed)
def p_visibility(s, prev_visibility):
pos = s.position()
% (prev_visibility, visibility))
s.next()
return visibility
-
+
def p_c_modifiers(s):
if s.sy == 'IDENT' and s.systring in ('inline',):
modifier = s.systring
result = Nodes.CFuncDefNode(pos,
visibility = ctx.visibility,
base_type = base_type,
- declarator = declarator,
+ declarator = declarator,
body = suite,
doc = doc,
modifiers = modifiers,
assignable = 1, nonempty = 1)
declarators.append(declarator)
s.expect_newline("Syntax error in C variable declaration")
- result = Nodes.CVarDefNode(pos,
+ result = Nodes.CVarDefNode(pos,
visibility = ctx.visibility,
base_type = base_type,
declarators = declarators,
s.expect_newline("Syntax error in ctypedef statement")
return Nodes.CTypeDefNode(
pos, base_type = base_type,
- declarator = declarator, visibility = visibility,
+ declarator = declarator,
+ visibility = visibility, api = api,
in_pxd = ctx.level == 'module_pxd')
def p_decorators(s):
s.next()
return_type_annotation = p_test(s)
doc, body = p_suite(s, Ctx(level = 'function'), with_doc = 1)
- return Nodes.DefNode(pos, name = name, args = args,
+ return Nodes.DefNode(pos, name = name, args = args,
star_arg = star_arg, starstar_arg = starstar_arg,
doc = doc, body = body, decorators = decorators,
return_type_annotation = return_type_annotation)
base_class_module = ".".join(base_class_path[:-1])
base_class_name = base_class_path[-1]
if s.sy == '[':
- if ctx.visibility not in ('public', 'extern'):
- error(s.position(), "Name options only allowed for 'public' or 'extern' C class")
+ if ctx.visibility not in ('public', 'extern') and not ctx.api:
+ error(s.position(), "Name options only allowed for 'public', 'api', or 'extern' C class")
objstruct_name, typeobj_name = p_c_class_options(s)
if s.sy == ':':
if ctx.level == 'module_pxd':
error(pos, "Type object name specification required for 'public' C class")
elif ctx.visibility == 'private':
if ctx.api:
- error(pos, "Only 'public' C class can be declared 'api'")
+ if not objstruct_name:
+ error(pos, "Object struct name specification required for 'api' C class")
+ if not typeobj_name:
+ error(pos, "Type object name specification required for 'api' C class")
else:
error(pos, "Invalid class visibility '%s'" % ctx.visibility)
return Nodes.CClassDefNode(pos,
repr(s.sy), repr(s.systring)))
return body
-COMPILER_DIRECTIVE_COMMENT_RE = re.compile(r"^#\s*cython:\s*((\w|[.])+\s*=.*)$")
+COMPILER_DIRECTIVE_COMMENT_RE = re.compile(r"^#\s*cython\s*:\s*((\w|[.])+\s*=.*)$")
def p_compiler_directive_comments(s):
result = {}