-# cython: auto_cpdef=True, infer_types=True, language_level=3
+# cython: auto_cpdef=True, infer_types=True, language_level=3, py2_import=True
#
# Pyrex Parser
#
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)
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 = 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":
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)
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
#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
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)
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':
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()
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):
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 = {}