TestGrammar.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. # mode: run
  2. # tag: syntax
  3. """
  4. Uses TreeFragment to test invalid syntax.
  5. """
  6. from __future__ import absolute_import
  7. from ...TestUtils import CythonTest
  8. from ..Errors import CompileError
  9. from .. import ExprNodes
  10. # Copied from CPython's test_grammar.py
  11. VALID_UNDERSCORE_LITERALS = [
  12. '0_0_0',
  13. '4_2',
  14. '1_0000_0000',
  15. '0b1001_0100',
  16. '0xffff_ffff',
  17. '0o5_7_7',
  18. '1_00_00.5',
  19. '1_00_00.5j',
  20. '1_00_00.5e5',
  21. '1_00_00j',
  22. '1_00_00e5_1',
  23. '1e1_0',
  24. '.1_4',
  25. '.1_4e1',
  26. '.1_4j',
  27. ]
  28. # Copied from CPython's test_grammar.py
  29. INVALID_UNDERSCORE_LITERALS = [
  30. # Trailing underscores:
  31. '0_',
  32. '42_',
  33. '1.4j_',
  34. '0b1_',
  35. '0xf_',
  36. '0o5_',
  37. # Underscores in the base selector:
  38. '0_b0',
  39. '0_xf',
  40. '0_o5',
  41. # Underscore right after the base selector:
  42. '0b_0',
  43. '0x_f',
  44. '0o_5',
  45. # Old-style octal, still disallowed:
  46. #'0_7',
  47. #'09_99',
  48. # Special case with exponent:
  49. '0 if 1_Else 1',
  50. # Underscore right before a dot:
  51. '1_.4',
  52. '1_.4j',
  53. # Underscore right after a dot:
  54. '1._4',
  55. '1._4j',
  56. '._5',
  57. # Underscore right after a sign:
  58. '1.0e+_1',
  59. # Multiple consecutive underscores:
  60. '4_______2',
  61. '0.1__4',
  62. '0b1001__0100',
  63. '0xffff__ffff',
  64. '0o5__77',
  65. '1e1__0',
  66. # Underscore right before j:
  67. '1.4_j',
  68. '1.4e5_j',
  69. # Underscore right before e:
  70. '1_e1',
  71. '1.4_e1',
  72. # Underscore right after e:
  73. '1e_1',
  74. '1.4e_1',
  75. # Whitespace in literals
  76. '1_ 2',
  77. '1 _2',
  78. '1_2.2_ 1',
  79. '1_2.2 _1',
  80. '1_2e _1',
  81. '1_2e2 _1',
  82. '1_2e 2_1',
  83. ]
  84. class TestGrammar(CythonTest):
  85. def test_invalid_number_literals(self):
  86. for literal in INVALID_UNDERSCORE_LITERALS:
  87. for expression in ['%s', '1 + %s', '%s + 1', '2 * %s', '%s * 2']:
  88. code = 'x = ' + expression % literal
  89. try:
  90. self.fragment(u'''\
  91. # cython: language_level=3
  92. ''' + code)
  93. except CompileError as exc:
  94. assert code in [s.strip() for s in str(exc).splitlines()], str(exc)
  95. else:
  96. assert False, "Invalid Cython code '%s' failed to raise an exception" % code
  97. def test_valid_number_literals(self):
  98. for literal in VALID_UNDERSCORE_LITERALS:
  99. for i, expression in enumerate(['%s', '1 + %s', '%s + 1', '2 * %s', '%s * 2']):
  100. code = 'x = ' + expression % literal
  101. node = self.fragment(u'''\
  102. # cython: language_level=3
  103. ''' + code).root
  104. assert node is not None
  105. literal_node = node.stats[0].rhs # StatListNode([SingleAssignmentNode('x', expr)])
  106. if i > 0:
  107. # Add/MulNode() -> literal is first or second operand
  108. literal_node = literal_node.operand2 if i % 2 else literal_node.operand1
  109. if 'j' in literal or 'J' in literal:
  110. assert isinstance(literal_node, ExprNodes.ImagNode)
  111. elif '.' in literal or 'e' in literal or 'E' in literal and not ('0x' in literal or '0X' in literal):
  112. assert isinstance(literal_node, ExprNodes.FloatNode)
  113. else:
  114. assert isinstance(literal_node, ExprNodes.IntNode)
  115. if __name__ == "__main__":
  116. import unittest
  117. unittest.main()