Commit ac32ea7a authored by Stefan Behnel's avatar Stefan Behnel

parse integer literals differently based on the type of source file: .pyx vs. .py, Py2 vs. Py3 mode

parent a22080cb
...@@ -800,9 +800,11 @@ class IntNode(ConstNode): ...@@ -800,9 +800,11 @@ class IntNode(ConstNode):
# unsigned "" or "U" # unsigned "" or "U"
# longness "" or "L" or "LL" # longness "" or "L" or "LL"
# is_c_literal True/False/None creator considers this a C integer literal
unsigned = "" unsigned = ""
longness = "" longness = ""
is_c_literal = None # unknown
def __init__(self, pos, **kwds): def __init__(self, pos, **kwds):
ExprNode.__init__(self, pos, **kwds) ExprNode.__init__(self, pos, **kwds)
...@@ -815,7 +817,10 @@ class IntNode(ConstNode): ...@@ -815,7 +817,10 @@ class IntNode(ConstNode):
self.calculate_constant_result() self.calculate_constant_result()
except ValueError: except ValueError:
pass pass
if self.constant_result in (constant_value_not_set, not_a_constant) or \ # we ignore 'is_c_literal = True' and instead map signed 32bit
# integers as C long values
if self.is_c_literal or \
self.constant_result in (constant_value_not_set, not_a_constant) or \
self.unsigned or self.longness == 'LL': self.unsigned or self.longness == 'LL':
# clearly a C literal # clearly a C literal
rank = (self.longness == 'LL') and 2 or 1 rank = (self.longness == 'LL') and 2 or 1
...@@ -844,17 +849,18 @@ class IntNode(ConstNode): ...@@ -844,17 +849,18 @@ class IntNode(ConstNode):
else: else:
return FloatNode(self.pos, value=self.value, type=dst_type, return FloatNode(self.pos, value=self.value, type=dst_type,
constant_result=not_a_constant) constant_result=not_a_constant)
node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
type = dst_type, unsigned=self.unsigned, longness=self.longness)
if dst_type.is_numeric and not dst_type.is_complex: if dst_type.is_numeric and not dst_type.is_complex:
node = IntNode(self.pos, value=self.value, constant_result=self.constant_result, node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
type = dst_type, unsigned=self.unsigned, longness=self.longness) type = dst_type, is_c_literal = True,
unsigned=self.unsigned, longness=self.longness)
return node return node
elif dst_type.is_pyobject: elif dst_type.is_pyobject:
node = IntNode(self.pos, value=self.value, constant_result=self.constant_result, node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
type = PyrexTypes.py_object_type, unsigned=self.unsigned, longness=self.longness) type = PyrexTypes.py_object_type, is_c_literal = False,
unsigned=self.unsigned, longness=self.longness)
else: else:
# not setting the type here! # FIXME: not setting the type here to keep it working with
# complex numbers. Should they be special cased?
node = IntNode(self.pos, value=self.value, constant_result=self.constant_result, node = IntNode(self.pos, value=self.value, constant_result=self.constant_result,
unsigned=self.unsigned, longness=self.longness) unsigned=self.unsigned, longness=self.longness)
# We still need to perform normal coerce_to processing on the # We still need to perform normal coerce_to processing on the
......
# We declare all of these here to type the first argument. # We declare all of these here to type the first argument.
cimport cython
from Cython.Compiler.Scanning cimport PyrexScanner from Cython.Compiler.Scanning cimport PyrexScanner
...@@ -46,6 +47,8 @@ cpdef expect_ellipsis(PyrexScanner s) ...@@ -46,6 +47,8 @@ cpdef expect_ellipsis(PyrexScanner s)
cpdef make_slice_nodes(pos, subscripts) cpdef make_slice_nodes(pos, subscripts)
cpdef make_slice_node(pos, start, stop = *, step = *) cpdef make_slice_node(pos, start, stop = *, step = *)
cpdef p_atom(PyrexScanner s) cpdef p_atom(PyrexScanner s)
@cython.locals(value=unicode)
cpdef p_int_literal(PyrexScanner s)
cpdef p_name(PyrexScanner s, name) cpdef p_name(PyrexScanner s, name)
cpdef p_cat_string_literal(PyrexScanner s) cpdef p_cat_string_literal(PyrexScanner s)
cpdef p_opt_string_literal(PyrexScanner s, required_type=*) cpdef p_opt_string_literal(PyrexScanner s, required_type=*)
......
...@@ -583,20 +583,7 @@ def p_atom(s): ...@@ -583,20 +583,7 @@ def p_atom(s):
expect_ellipsis(s) expect_ellipsis(s)
return ExprNodes.EllipsisNode(pos) return ExprNodes.EllipsisNode(pos)
elif sy == 'INT': elif sy == 'INT':
value = s.systring return p_int_literal(s)
s.next()
unsigned = ""
longness = ""
while value[-1] in "UuLl":
if value[-1] in "Ll":
longness += "L"
else:
unsigned += "U"
value = value[:-1]
return ExprNodes.IntNode(pos,
value = value,
unsigned = unsigned,
longness = longness)
elif sy == 'FLOAT': elif sy == 'FLOAT':
value = s.systring value = s.systring
s.next() s.next()
...@@ -631,6 +618,37 @@ def p_atom(s): ...@@ -631,6 +618,37 @@ def p_atom(s):
else: else:
s.error("Expected an identifier or literal") s.error("Expected an identifier or literal")
def p_int_literal(s):
pos = s.position()
value = s.systring
s.next()
unsigned = ""
longness = ""
while value[-1] in u"UuLl":
if value[-1] in u"Ll":
longness += "L"
else:
unsigned += "U"
value = value[:-1]
# '3L' is ambiguous in Py2 but not in Py3. '3U' and '3LL' are
# illegal in Py2 Python files. All suffixes are illegal in Py3
# Python files.
is_c_literal = None
if unsigned:
is_c_literal = True
elif longness:
if longness == 'LL' or s.context.language_level >= 3:
is_c_literal = True
if s.in_python_file:
if is_c_literal:
error(pos, "illegal integer literal syntax in Python source file")
is_c_literal = False
return ExprNodes.IntNode(pos,
is_c_literal = is_c_literal,
value = value,
unsigned = unsigned,
longness = longness)
def p_name(s, name): def p_name(s, name):
pos = s.position() pos = s.position()
if not s.compile_time_expr and name in s.compile_time_env: if not s.compile_time_expr and name in s.compile_time_env:
......
# cython: language_level=2
def int_literals():
a = 1L # ok
b = 10000000000000L # ok
c = 1UL
d = 10000000000000UL
e = 10000000000000LL
_ERRORS = """
6:8: illegal integer literal syntax in Python source file
7:8: illegal integer literal syntax in Python source file
8:8: illegal integer literal syntax in Python source file
"""
# cython: language_level=3
def int_literals():
a = 1L
b = 10000000000000L
c = 1UL
d = 10000000000000UL
e = 10000000000000LL
_ERRORS = """
4:8: illegal integer literal syntax in Python source file
5:8: illegal integer literal syntax in Python source file
6:8: illegal integer literal syntax in Python source file
7:8: illegal integer literal syntax in Python source file
8:8: illegal integer literal syntax in Python source file
"""
...@@ -106,3 +106,16 @@ def dict_iter(dict d): ...@@ -106,3 +106,16 @@ def dict_iter(dict d):
values = [ value for value in d.values() ] values = [ value for value in d.values() ]
items = [ item for item in d.items() ] items = [ item for item in d.items() ]
return keys, values, items return keys, values, items
def int_literals():
"""
>>> int_literals()
long
long
unsigned long
unsigned long
"""
print(cython.typeof(1L))
print(cython.typeof(10000000000000L))
print(cython.typeof(1UL))
print(cython.typeof(10000000000000UL))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment