-# 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)
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:
exc_type = None
exc_value = None
exc_tb = None
+ cause = None
if s.sy not in statement_terminators:
exc_type = p_test(s)
if s.sy == ',':
if s.sy == ',':
s.next()
exc_tb = p_test(s)
+ elif s.sy == 'from':
+ s.next()
+ cause = p_test(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)
+ exc_tb = exc_tb,
+ cause = cause)
else:
return Nodes.ReraiseStatNode(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":
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
# 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)
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),
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 = {}