base.py 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306
  1. # Copyright (c) 2016-2017, 2019-2024 Rocky Bernstein
  2. # This program is free software: you can redistribute it and/or modify
  3. # it under the terms of the GNU General Public License as published by
  4. # the Free Software Foundation, either version 3 of the License, or
  5. # (at your option) any later version.
  6. #
  7. # This program is distributed in the hope that it will be useful,
  8. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. # GNU General Public License for more details.
  11. #
  12. # You should have received a copy of the GNU General Public License
  13. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. """
  15. Python 3.7 base code. We keep non-custom-generated grammar rules out of this file.
  16. """
  17. from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
  18. from spark_parser.spark import rule2str
  19. from decompyle3.parsers.parse_heads import ParserError, PythonBaseParser, nop_func
  20. from decompyle3.parsers.reduce_check import (
  21. and_cond_check,
  22. and_invalid,
  23. and_not_check,
  24. c_tryelsestmt,
  25. if_and_elsestmt,
  26. if_and_stmt,
  27. ifelsestmt,
  28. iflaststmt,
  29. ifstmt,
  30. ifstmts_jump_invalid,
  31. lastc_stmt,
  32. list_if_not,
  33. not_or_check,
  34. or_check37_invalid,
  35. or_cond_check_invalid,
  36. testtrue,
  37. tryexcept,
  38. while1elsestmt,
  39. while1stmt,
  40. whilestmt,
  41. )
  42. from decompyle3.parsers.treenode import SyntaxTree
  43. class Python37BaseParser(PythonBaseParser):
  44. def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
  45. self.added_rules = set()
  46. super(Python37BaseParser, self).__init__(SyntaxTree, debug=debug_parser)
  47. self.new_rules = set()
  48. @staticmethod
  49. def call_fn_name(token):
  50. """Customize CALL_FUNCTION to add the number of positional arguments"""
  51. if token.attr is not None:
  52. return "%s_%i" % (token.kind, token.attr)
  53. else:
  54. return "%s_0" % (token.kind)
  55. def add_make_function_rule(self, rule, opname, attr, customize):
  56. """Python 3.3 added a an additional LOAD_STR before MAKE_FUNCTION and
  57. this has an effect on many rules.
  58. """
  59. new_rule = rule % "LOAD_STR "
  60. self.add_unique_rule(new_rule, opname, attr, customize)
  61. def custom_build_class_rule(self, opname, i, token, tokens, customize):
  62. """
  63. # Should the first rule be somehow folded into the 2nd one?
  64. build_class ::= LOAD_BUILD_CLASS mkfunc
  65. LOAD_CLASSNAME {expr}^n-1 CALL_FUNCTION_n
  66. LOAD_CONST CALL_FUNCTION_n
  67. build_class ::= LOAD_BUILD_CLASS mkfunc
  68. expr
  69. call
  70. CALL_FUNCTION_3
  71. """
  72. # FIXME: I bet this can be simplified
  73. # look for next MAKE_FUNCTION
  74. for i in range(i + 1, len(tokens)):
  75. if tokens[i].kind.startswith("MAKE_FUNCTION"):
  76. break
  77. elif tokens[i].kind.startswith("MAKE_CLOSURE"):
  78. break
  79. pass
  80. assert i < len(
  81. tokens
  82. ), "build_class needs to find MAKE_FUNCTION or MAKE_CLOSURE"
  83. assert (
  84. tokens[i + 1].kind == "LOAD_STR"
  85. ), "build_class expecting CONST after MAKE_FUNCTION/MAKE_CLOSURE"
  86. call_fn_tok = None
  87. for i in range(i, len(tokens)):
  88. if tokens[i].kind.startswith("CALL_FUNCTION"):
  89. call_fn_tok = tokens[i]
  90. break
  91. if not call_fn_tok:
  92. raise RuntimeError(
  93. "build_class custom rule for %s needs to find CALL_FUNCTION" % opname
  94. )
  95. # customize build_class rule
  96. # FIXME: What's the deal with the two rules? Different Python versions?
  97. # Different situations? Note that the above rule is based on the CALL_FUNCTION
  98. # token found, while this one doesn't.
  99. # 3.6+ handling
  100. call_function = call_fn_tok.kind
  101. if call_function.startswith("CALL_FUNCTION_KW"):
  102. self.addRule("classdef ::= build_class_kw store", nop_func)
  103. rule = "build_class_kw ::= LOAD_BUILD_CLASS mkfunc %sLOAD_CONST %s" % (
  104. "expr " * (call_fn_tok.attr - 1),
  105. call_function,
  106. )
  107. else:
  108. call_function = self.call_fn_name(call_fn_tok)
  109. rule = "build_class ::= LOAD_BUILD_CLASS mkfunc %s%s" % (
  110. "expr " * (call_fn_tok.attr - 1),
  111. call_function,
  112. )
  113. self.addRule(rule, nop_func)
  114. return
  115. # FIXME FIXME FIXME: The below is an utter mess. Come up with a better
  116. # organization for this. For example, arrange organize by opcode base?
  117. def customize_grammar_rules37(self, tokens, customize):
  118. is_pypy = False
  119. # For a rough break out on the first word. This may
  120. # include instructions that don't need customization,
  121. # but we'll do a finer check after the rough breakout.
  122. customize_instruction_basenames = frozenset(
  123. (
  124. "BEFORE",
  125. "BUILD",
  126. "CALL",
  127. "CONTINUE",
  128. "DELETE",
  129. "FORMAT",
  130. "GET",
  131. "JUMP",
  132. "LOAD",
  133. "LOOKUP",
  134. "MAKE",
  135. "RETURN",
  136. "RAISE",
  137. "SETUP",
  138. "UNPACK",
  139. "WITH",
  140. )
  141. )
  142. # Opcode names in the custom_ops_processed set have rules that get added
  143. # unconditionally and the rules are constant. So they need to be done
  144. # only once and if we see the opcode a second we don't have to consider
  145. # adding more rules.
  146. #
  147. # Note: BUILD_TUPLE_UNPACK_WITH_CALL gets considered by
  148. # default because it starts with BUILD. So we'll set to ignore it from
  149. # the start.
  150. custom_ops_processed = {"BUILD_TUPLE_UNPACK_WITH_CALL"}
  151. # A set of instruction operation names that exist in the token stream.
  152. # We use this customize the grammar that we create.
  153. # 2.6-compatible set comprehensions
  154. self.seen_ops = frozenset([t.kind for t in tokens])
  155. self.seen_op_basenames = frozenset(
  156. [opname[: opname.rfind("_")] for opname in self.seen_ops]
  157. )
  158. # Loop over instructions adding custom grammar rules based on
  159. # a specific instruction seen.
  160. if "PyPy" in customize:
  161. is_pypy = True
  162. self.addRule(
  163. """
  164. stmt ::= assign3_pypy
  165. stmt ::= assign2_pypy
  166. assign3_pypy ::= expr expr expr store store store
  167. assign2_pypy ::= expr expr store store
  168. """,
  169. nop_func,
  170. )
  171. n = len(tokens)
  172. # Determine if we have an iteration CALL_FUNCTION_1.
  173. has_get_iter_call_function1 = False
  174. for i, token in enumerate(tokens):
  175. if (
  176. token == "GET_ITER"
  177. and i < n - 2
  178. and self.call_fn_name(tokens[i + 1]) == "CALL_FUNCTION_1"
  179. ):
  180. has_get_iter_call_function1 = True
  181. for i, token in enumerate(tokens):
  182. opname = token.kind
  183. # Do a quick breakout before testing potentially
  184. # each of the dozen or so instruction in if elif.
  185. if (
  186. opname[: opname.find("_")] not in customize_instruction_basenames
  187. or opname in custom_ops_processed
  188. ):
  189. continue
  190. opname_base = opname[: opname.rfind("_")]
  191. # The order of opname listed is roughly sorted below
  192. if opname == "LOAD_ASSERT" and "PyPy" in customize:
  193. rules_str = """
  194. stmt ::= JUMP_IF_NOT_DEBUG stmts COME_FROM
  195. """
  196. self.add_unique_doc_rules(rules_str, customize)
  197. elif opname == "BEFORE_ASYNC_WITH":
  198. rules_str = """
  199. stmt ::= async_with_stmt
  200. stmt ::= async_with_as_stmt
  201. c_stmt ::= c_async_with_stmt
  202. """
  203. if self.version < (3, 8):
  204. rules_str += """
  205. stmt ::= async_with_stmt SETUP_ASYNC_WITH
  206. c_stmt ::= c_async_with_stmt SETUP_ASYNC_WITH
  207. async_with_stmt ::= expr
  208. async_with_pre
  209. POP_TOP
  210. suite_stmts_opt
  211. POP_BLOCK LOAD_CONST
  212. async_with_post
  213. c_async_with_stmt ::= expr
  214. async_with_pre
  215. POP_TOP
  216. c_suite_stmts_opt
  217. POP_BLOCK LOAD_CONST
  218. async_with_post
  219. async_with_stmt ::= expr
  220. async_with_pre
  221. POP_TOP
  222. suite_stmts_opt
  223. async_with_post
  224. c_async_with_stmt ::= expr
  225. async_with_pre
  226. POP_TOP
  227. c_suite_stmts_opt
  228. async_with_post
  229. async_with_as_stmt ::= expr
  230. async_with_pre
  231. store
  232. suite_stmts_opt
  233. POP_BLOCK LOAD_CONST
  234. async_with_post
  235. c_async_with_as_stmt ::= expr
  236. async_with_pre
  237. store
  238. c_suite_stmts_opt
  239. POP_BLOCK LOAD_CONST
  240. async_with_post
  241. async_with_as_stmt ::= expr
  242. async_with_pre
  243. store
  244. suite_stmts_opt
  245. async_with_post
  246. c_async_with_as_stmt ::= expr
  247. async_with_pre
  248. store
  249. suite_stmts_opt
  250. async_with_post
  251. """
  252. else:
  253. rules_str += """
  254. async_with_pre ::= BEFORE_ASYNC_WITH GET_AWAITABLE LOAD_CONST YIELD_FROM SETUP_ASYNC_WITH
  255. async_with_post ::= BEGIN_FINALLY COME_FROM_ASYNC_WITH
  256. WITH_CLEANUP_START GET_AWAITABLE LOAD_CONST YIELD_FROM
  257. WITH_CLEANUP_FINISH END_FINALLY
  258. async_with_stmt ::= expr
  259. async_with_pre
  260. POP_TOP
  261. suite_stmts
  262. POP_TOP POP_BLOCK
  263. async_with_post
  264. c_async_with_stmt ::= expr
  265. async_with_pre
  266. POP_TOP
  267. c_suite_stmts
  268. POP_TOP POP_BLOCK
  269. async_with_post
  270. async_with_stmt ::= expr
  271. async_with_pre
  272. POP_TOP
  273. suite_stmts
  274. POP_BLOCK
  275. BEGIN_FINALLY
  276. WITH_CLEANUP_START GET_AWAITABLE LOAD_CONST YIELD_FROM
  277. WITH_CLEANUP_FINISH POP_FINALLY LOAD_CONST RETURN_VALUE
  278. COME_FROM_ASYNC_WITH
  279. WITH_CLEANUP_START GET_AWAITABLE LOAD_CONST YIELD_FROM
  280. WITH_CLEANUP_FINISH END_FINALLY
  281. c_async_with_stmt ::= async_with_stmt
  282. async_with_as_stmt ::= expr
  283. async_with_pre
  284. store suite_stmts
  285. POP_TOP POP_BLOCK
  286. async_with_post
  287. c_async_with_as_stmt ::= expr
  288. async_with_pre
  289. store suite_stmts
  290. POP_TOP POP_BLOCK
  291. async_with_post
  292. async_with_as_stmt ::= expr
  293. async_with_pre
  294. store suite_stmts
  295. POP_BLOCK async_with_post
  296. c_async_with_as_stmt ::= expr
  297. async_with_pre
  298. store suite_stmts
  299. POP_BLOCK async_with_post
  300. """
  301. self.addRule(rules_str, nop_func)
  302. elif opname_base == "BUILD_CONST_KEY_MAP":
  303. kvlist_n = "expr " * (token.attr)
  304. rule = """
  305. expr ::= dict
  306. dict ::= %sLOAD_CONST %s
  307. """ % (
  308. kvlist_n,
  309. opname,
  310. )
  311. self.addRule(rule, nop_func)
  312. elif opname.startswith("BUILD_LIST_UNPACK"):
  313. v = token.attr
  314. rule = "build_list_unpack ::= %s%s" % ("expr " * v, opname)
  315. self.addRule(rule, nop_func)
  316. rule = "expr ::= build_list_unpack"
  317. self.addRule(rule, nop_func)
  318. elif opname_base in ("BUILD_MAP", "BUILD_MAP_UNPACK"):
  319. if opname == "BUILD_MAP_UNPACK":
  320. self.addRule(
  321. """
  322. expr ::= dict_unpack
  323. dict_unpack ::= expr BUILD_MAP_UNPACK
  324. """,
  325. nop_func,
  326. )
  327. pass
  328. elif opname.startswith("BUILD_MAP_UNPACK_WITH_CALL"):
  329. v = token.attr
  330. rule = "build_map_unpack_with_call ::= %s%s" % ("expr " * v, opname)
  331. self.addRule(rule, nop_func)
  332. kvlist_n = "kvlist_%s" % token.attr
  333. if opname == "BUILD_MAP_n":
  334. # PyPy sometimes has no count. Sigh.
  335. rule = (
  336. "dict_comp_func ::= BUILD_MAP_n LOAD_ARG for_iter store "
  337. "comp_iter JUMP_LOOP RETURN_VALUE RETURN_LAST"
  338. )
  339. self.add_unique_rule(rule, "dict_comp_func", 1, customize)
  340. kvlist_n = "kvlist_n"
  341. rule = "kvlist_n ::= kvlist_n kv3"
  342. self.add_unique_rule(rule, "kvlist_n", 0, customize)
  343. rule = "kvlist_n ::="
  344. self.add_unique_rule(rule, "kvlist_n", 1, customize)
  345. rule = """
  346. expr ::= dict
  347. dict ::= BUILD_MAP_n kvlist_n
  348. """
  349. if not opname.startswith("BUILD_MAP_WITH_CALL"):
  350. # FIXME: Use the attr
  351. # so this doesn't run into exponential parsing time.
  352. if opname.startswith("BUILD_MAP_UNPACK"):
  353. # FIXME: start here. The LHS should be dict_unpack, not dict.
  354. # FIXME: really we need a combination of dict_entry-like things.
  355. # It just so happens the most common case is not to mix
  356. # dictionary comphensions with dictionary, elements
  357. if "LOAD_DICTCOMP" in self.seen_ops:
  358. rule = """
  359. expr ::= dict_comp
  360. expr ::= dict
  361. dict ::= %s%s
  362. """ % (
  363. "dict_comp " * token.attr,
  364. opname,
  365. )
  366. self.addRule(rule, nop_func)
  367. rule = """
  368. expr ::= dict_unpack
  369. dict_unpack ::= %s%s
  370. """ % (
  371. "expr " * token.attr,
  372. opname,
  373. )
  374. else:
  375. rule = "%s ::= %s %s" % (
  376. kvlist_n,
  377. "expr " * (token.attr * 2),
  378. opname,
  379. )
  380. self.add_unique_rule(rule, opname, token.attr, customize)
  381. rule = (
  382. """
  383. expr ::= dict
  384. dict ::= %s
  385. """
  386. % kvlist_n
  387. )
  388. self.add_unique_rule(rule, opname, token.attr, customize)
  389. elif opname.startswith("BUILD_MAP_UNPACK_WITH_CALL"):
  390. v = token.attr
  391. rule = "build_map_unpack_with_call ::= %s%s" % ("expr " * v, opname)
  392. self.addRule(rule, nop_func)
  393. elif opname.startswith("BUILD_TUPLE_UNPACK_WITH_CALL"):
  394. v = token.attr
  395. rule = (
  396. "build_tuple_unpack_with_call ::= "
  397. + "expr1024 " * int(v // 1024)
  398. + "expr32 " * int((v // 32) % 32)
  399. + "expr " * (v % 32)
  400. + opname
  401. )
  402. self.addRule(rule, nop_func)
  403. rule = "starred ::= %s %s" % ("expr " * v, opname)
  404. self.addRule(rule, nop_func)
  405. elif opname_base in (
  406. "BUILD_LIST",
  407. "BUILD_SET",
  408. "BUILD_TUPLE",
  409. "BUILD_TUPLE_UNPACK",
  410. ):
  411. collection_size = token.attr
  412. is_LOAD_CLOSURE = False
  413. if opname_base == "BUILD_TUPLE":
  414. # If is part of a "load_closure", then it is not part of a
  415. # "list".
  416. is_LOAD_CLOSURE = True
  417. for j in range(collection_size):
  418. if tokens[i - j - 1].kind != "LOAD_CLOSURE":
  419. is_LOAD_CLOSURE = False
  420. break
  421. if is_LOAD_CLOSURE:
  422. rule = "load_closure ::= %s%s" % (
  423. ("LOAD_CLOSURE " * collection_size),
  424. opname,
  425. )
  426. self.add_unique_rule(rule, opname, token.attr, customize)
  427. if not is_LOAD_CLOSURE or collection_size == 0:
  428. # We do this complicated test to speed up parsing of
  429. # pathelogically long literals, especially those over 1024.
  430. thousands = collection_size // 1024
  431. thirty32s = (collection_size // 32) % 32
  432. if thirty32s > 0:
  433. rule = "expr32 ::=%s" % (" expr" * 32)
  434. self.add_unique_rule(
  435. rule, opname_base, collection_size, customize
  436. )
  437. pass
  438. if thousands > 0:
  439. self.add_unique_rule(
  440. "expr1024 ::=%s" % (" expr32" * 32),
  441. opname_base,
  442. collection_size,
  443. customize,
  444. )
  445. pass
  446. collection = opname_base[opname_base.find("_") + 1 :].lower()
  447. rule = (
  448. ("%s ::= " % collection)
  449. + "expr1024 " * thousands
  450. + "expr32 " * thirty32s
  451. + "expr " * (collection_size % 32)
  452. + opname
  453. )
  454. self.add_unique_rules(["expr ::= %s" % collection, rule], customize)
  455. continue
  456. continue
  457. elif opname_base == "BUILD_SLICE":
  458. if token.attr == 2:
  459. self.add_unique_rules(
  460. [
  461. "expr ::= slice2",
  462. "slice2 ::= expr expr BUILD_SLICE_2",
  463. ],
  464. customize,
  465. )
  466. else:
  467. assert token.attr == 3, (
  468. "BUILD_SLICE value must be 2 or 3; is %s" % token.attr
  469. )
  470. self.add_unique_rules(
  471. [
  472. "expr ::= slice3",
  473. "slice3 ::= expr expr expr BUILD_SLICE_3",
  474. ],
  475. customize,
  476. )
  477. elif opname.startswith("BUILD_STRING"):
  478. v = token.attr
  479. rules_str = """
  480. expr ::= joined_str
  481. joined_str ::= %sBUILD_STRING_%d
  482. """ % (
  483. "expr " * v,
  484. v,
  485. )
  486. self.add_unique_doc_rules(rules_str, customize)
  487. if "FORMAT_VALUE_ATTR" in self.seen_ops:
  488. rules_str = """
  489. formatted_value_attr ::= expr expr FORMAT_VALUE_ATTR expr BUILD_STRING
  490. expr ::= formatted_value_attr
  491. """
  492. self.add_unique_doc_rules(rules_str, customize)
  493. elif opname in frozenset(
  494. (
  495. "CALL_FUNCTION",
  496. "CALL_FUNCTION_EX",
  497. "CALL_FUNCTION_EX_KW",
  498. "CALL_FUNCTION_VAR",
  499. "CALL_FUNCTION_VAR_KW",
  500. )
  501. ) or opname.startswith("CALL_FUNCTION_KW"):
  502. if opname == "CALL_FUNCTION" and token.attr == 1:
  503. rule = """
  504. expr ::= dict_comp
  505. dict_comp ::= LOAD_DICTCOMP LOAD_STR MAKE_FUNCTION_0 expr
  506. GET_ITER CALL_FUNCTION_1
  507. classdefdeco1 ::= expr classdefdeco2 CALL_FUNCTION_1
  508. classdefdeco1 ::= expr classdefdeco1 CALL_FUNCTION_1
  509. """
  510. self.addRule(rule, nop_func)
  511. self.custom_classfunc_rule(opname, token, customize, tokens[i + 1])
  512. # Note: don't add to custom_ops_processed.
  513. elif opname_base == "CALL_METHOD":
  514. # PyPy and Python 3.7+ only - DRY with parse2
  515. if opname == "CALL_METHOD_KW":
  516. args_kw = token.attr
  517. rules_str = """
  518. expr ::= call_kw_pypy37
  519. pypy_kw_keys ::= LOAD_CONST
  520. """
  521. self.add_unique_doc_rules(rules_str, customize)
  522. rule = (
  523. "call_kw_pypy37 ::= expr "
  524. + ("expr " * args_kw)
  525. + " pypy_kw_keys "
  526. + opname
  527. )
  528. else:
  529. args_pos, args_kw = self.get_pos_kw(token)
  530. # number of apply equiv arguments:
  531. nak = (len(opname_base) - len("CALL_METHOD")) // 3
  532. rule = (
  533. "call ::= expr "
  534. + ("expr " * args_pos)
  535. + ("kwarg " * args_kw)
  536. + "expr " * nak
  537. + opname
  538. )
  539. self.add_unique_rule(rule, opname, token.attr, customize)
  540. elif opname == "CONTINUE":
  541. self.addRule("continue ::= CONTINUE", nop_func)
  542. custom_ops_processed.add(opname)
  543. elif opname == "CONTINUE_LOOP":
  544. self.addRule("continue ::= CONTINUE_LOOP", nop_func)
  545. custom_ops_processed.add(opname)
  546. elif opname == "DELETE_ATTR":
  547. self.addRule("delete ::= expr DELETE_ATTR", nop_func)
  548. custom_ops_processed.add(opname)
  549. elif opname == "DELETE_DEREF":
  550. self.addRule(
  551. """
  552. stmt ::= del_deref_stmt
  553. del_deref_stmt ::= DELETE_DEREF
  554. """,
  555. nop_func,
  556. )
  557. custom_ops_processed.add(opname)
  558. elif opname == "DELETE_SUBSCR":
  559. self.addRule(
  560. """
  561. delete ::= delete_subscript
  562. delete_subscript ::= expr expr DELETE_SUBSCR
  563. """,
  564. nop_func,
  565. )
  566. custom_ops_processed.add(opname)
  567. elif opname == "FORMAT_VALUE":
  568. rules_str = """
  569. expr ::= formatted_value1
  570. formatted_value1 ::= expr FORMAT_VALUE
  571. """
  572. self.add_unique_doc_rules(rules_str, customize)
  573. elif opname == "FORMAT_VALUE_ATTR":
  574. rules_str = """
  575. expr ::= formatted_value2
  576. formatted_value2 ::= expr expr FORMAT_VALUE_ATTR
  577. """
  578. self.add_unique_doc_rules(rules_str, customize)
  579. elif opname == "GET_AITER":
  580. self.addRule(
  581. """
  582. stmt ::= genexpr_func_async
  583. """,
  584. nop_func,
  585. )
  586. custom_ops_processed.add(opname)
  587. elif opname == "JUMP_IF_NOT_DEBUG":
  588. v = token.attr
  589. self.addRule(
  590. """
  591. stmt ::= assert_pypy
  592. stmt ::= assert2_pypy", nop_func)
  593. assert_pypy ::= JUMP_IF_NOT_DEBUG expr POP_JUMP_IF_TRUE
  594. LOAD_ASSERT RAISE_VARARGS_1 COME_FROM
  595. assert2_pypy ::= JUMP_IF_NOT_DEBUG assert_expr POP_JUMP_IF_TRUE
  596. LOAD_ASSERT expr CALL_FUNCTION_1
  597. RAISE_VARARGS_1 COME_FROM
  598. assert2_pypy ::= JUMP_IF_NOT_DEBUG expr POP_JUMP_IF_TRUE
  599. LOAD_ASSERT expr CALL_FUNCTION_1
  600. RAISE_VARARGS_1 COME_FROM,
  601. """,
  602. nop_func,
  603. )
  604. custom_ops_processed.add(opname)
  605. elif opname == "LOAD_BUILD_CLASS":
  606. self.custom_build_class_rule(opname, i, token, tokens, customize)
  607. # Note: don't add to custom_ops_processed.
  608. elif opname == "LOAD_CLASSDEREF":
  609. # Python 3.4+
  610. self.addRule("expr ::= LOAD_CLASSDEREF", nop_func)
  611. custom_ops_processed.add(opname)
  612. elif opname == "LOAD_CLASSNAME":
  613. self.addRule("expr ::= LOAD_CLASSNAME", nop_func)
  614. custom_ops_processed.add(opname)
  615. elif opname == "LOAD_DICTCOMP":
  616. if has_get_iter_call_function1:
  617. rule_pat = (
  618. "dict_comp ::= LOAD_DICTCOMP %sMAKE_FUNCTION_0 expr "
  619. "GET_ITER CALL_FUNCTION_1"
  620. )
  621. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  622. pass
  623. custom_ops_processed.add(opname)
  624. elif opname == "LOAD_LISTCOMP":
  625. self.add_unique_rule(
  626. "expr ::= list_comp", opname, token.attr, customize
  627. )
  628. custom_ops_processed.add(opname)
  629. elif opname == "LOAD_NAME":
  630. if (
  631. token.attr == "__annotations__"
  632. and "SETUP_ANNOTATIONS" in self.seen_ops
  633. ):
  634. token.kind = "LOAD_ANNOTATION"
  635. self.addRule(
  636. """
  637. stmt ::= SETUP_ANNOTATIONS
  638. stmt ::= ann_assign
  639. ann_assign ::= expr LOAD_ANNOTATION LOAD_STR STORE_SUBSCR
  640. """,
  641. nop_func,
  642. )
  643. pass
  644. elif opname == "LOAD_SETCOMP":
  645. # Should this be generalized and put under MAKE_FUNCTION?
  646. if has_get_iter_call_function1:
  647. self.addRule("expr ::= set_comp", nop_func)
  648. rule_pat = (
  649. "set_comp ::= LOAD_SETCOMP %sMAKE_FUNCTION_0 expr "
  650. "GET_ITER CALL_FUNCTION_1"
  651. )
  652. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  653. pass
  654. custom_ops_processed.add(opname)
  655. elif opname == "LOOKUP_METHOD":
  656. # A PyPy speciality - DRY with parse3
  657. self.addRule(
  658. """
  659. expr ::= attribute
  660. attribute ::= expr LOOKUP_METHOD
  661. """,
  662. nop_func,
  663. )
  664. custom_ops_processed.add(opname)
  665. elif opname.startswith("MAKE_CLOSURE"):
  666. # DRY with MAKE_FUNCTION
  667. # Note: this probably doesn't handle kwargs proprerly
  668. if opname == "MAKE_CLOSURE_0" and "LOAD_DICTCOMP" in self.seen_ops:
  669. # Is there something general going on here?
  670. # Note that 3.6+ doesn't do this, but we'll remove
  671. # this rule in parse36.py
  672. rule = """
  673. dict_comp ::= load_closure LOAD_DICTCOMP LOAD_STR
  674. MAKE_CLOSURE_0 expr
  675. GET_ITER CALL_FUNCTION_1
  676. """
  677. self.addRule(rule, nop_func)
  678. args_pos, args_kw, annotate_args = token.attr
  679. # FIXME: Fold test into add_make_function_rule
  680. j = 2
  681. if is_pypy or (i >= j and tokens[i - j] == "LOAD_LAMBDA"):
  682. rule_pat = """
  683. expr ::= lambda_body
  684. lambda_body ::= %sload_closure LOAD_LAMBDA %%s%s
  685. """ % (
  686. "expr " * args_pos,
  687. opname,
  688. )
  689. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  690. if has_get_iter_call_function1:
  691. rule_pat = (
  692. "generator_exp ::= %sload_closure load_genexpr %%s%s expr "
  693. "GET_ITER CALL_FUNCTION_1" % ("expr " * args_pos, opname)
  694. )
  695. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  696. if has_get_iter_call_function1:
  697. if is_pypy or (i >= j and tokens[i - j] == "LOAD_LISTCOMP"):
  698. # In the tokens we saw:
  699. # LOAD_LISTCOMP LOAD_CONST MAKE_FUNCTION (>= 3.3) or
  700. # LOAD_LISTCOMP MAKE_FUNCTION (< 3.3) or
  701. # and have GET_ITER CALL_FUNCTION_1
  702. # Todo: For Pypy we need to modify this slightly
  703. rule_pat = (
  704. "list_comp ::= %sload_closure LOAD_LISTCOMP %%s%s expr "
  705. "GET_ITER CALL_FUNCTION_1"
  706. % ("expr " * args_pos, opname)
  707. )
  708. self.add_make_function_rule(
  709. rule_pat, opname, token.attr, customize
  710. )
  711. if is_pypy or (i >= j and tokens[i - j] == "LOAD_SETCOMP"):
  712. rule_pat = (
  713. "set_comp ::= %sload_closure LOAD_SETCOMP %%s%s expr "
  714. "GET_ITER CALL_FUNCTION_1"
  715. % ("expr " * args_pos, opname)
  716. )
  717. self.add_make_function_rule(
  718. rule_pat, opname, token.attr, customize
  719. )
  720. if is_pypy or (i >= j and tokens[i - j] == "LOAD_DICTCOMP"):
  721. self.add_unique_rule(
  722. "dict_comp ::= %sload_closure LOAD_DICTCOMP %s "
  723. "expr GET_ITER CALL_FUNCTION_1"
  724. % ("expr " * args_pos, opname),
  725. opname,
  726. token.attr,
  727. customize,
  728. )
  729. if args_kw > 0:
  730. kwargs_str = "kwargs "
  731. else:
  732. kwargs_str = ""
  733. rule = "mkfunc ::= %s%s%s load_closure LOAD_CODE LOAD_STR %s" % (
  734. "expr " * args_pos,
  735. kwargs_str,
  736. "expr " * annotate_args,
  737. opname,
  738. )
  739. self.add_unique_rule(rule, opname, token.attr, customize)
  740. if args_kw == 0:
  741. rule = "mkfunc ::= %sload_closure load_genexpr %s" % (
  742. "expr " * args_pos,
  743. opname,
  744. )
  745. self.add_unique_rule(rule, opname, token.attr, customize)
  746. pass
  747. elif opname_base.startswith("MAKE_FUNCTION"):
  748. args_pos, args_kw, annotate_args, closure = token.attr
  749. stack_count = args_pos + args_kw + annotate_args
  750. if closure:
  751. if args_pos:
  752. rule = """
  753. expr ::= lambda_body
  754. lambda_body ::= %s%s%s%s
  755. """ % (
  756. "expr " * stack_count,
  757. "load_closure " * closure,
  758. "BUILD_TUPLE_1 LOAD_LAMBDA LOAD_STR ",
  759. opname,
  760. )
  761. else:
  762. rule = """
  763. expr ::= lambda_body
  764. lambda_body ::= %s%s%s""" % (
  765. "load_closure " * closure,
  766. "LOAD_LAMBDA LOAD_STR ",
  767. opname,
  768. )
  769. self.add_unique_rule(rule, opname, token.attr, customize)
  770. else:
  771. rule = """
  772. expr ::= lambda_body
  773. lambda_body ::= %sLOAD_LAMBDA LOAD_STR %s""" % (
  774. ("expr " * stack_count),
  775. opname,
  776. )
  777. self.add_unique_rule(rule, opname, token.attr, customize)
  778. rule = "mkfunc ::= %s%s%s%s" % (
  779. "expr " * stack_count,
  780. "load_closure " * closure,
  781. "LOAD_CODE LOAD_STR ",
  782. opname,
  783. )
  784. self.add_unique_rule(rule, opname, token.attr, customize)
  785. if has_get_iter_call_function1:
  786. rule_pat = (
  787. "generator_exp ::= %sload_genexpr %%s%s expr "
  788. "GET_ITER CALL_FUNCTION_1"
  789. ) % ("expr " * args_pos, opname)
  790. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  791. rule_pat = """
  792. expr ::= generator_exp
  793. generator_exp ::= %sload_closure load_genexpr %%s%s expr
  794. GET_ITER CALL_FUNCTION_1""" % (
  795. "expr " * args_pos,
  796. opname,
  797. )
  798. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  799. if is_pypy or (i >= 2 and tokens[i - 2] == "LOAD_LISTCOMP"):
  800. # 3.6+ sometimes bundles all of the
  801. # 'exprs' in the rule above into a
  802. # tuple.
  803. rule_pat = (
  804. "list_comp ::= load_closure LOAD_LISTCOMP %%s%s "
  805. "expr GET_ITER CALL_FUNCTION_1" % (opname,)
  806. )
  807. self.add_make_function_rule(
  808. rule_pat, opname, token.attr, customize
  809. )
  810. rule_pat = (
  811. "list_comp ::= %sLOAD_LISTCOMP %%s%s expr "
  812. "GET_ITER CALL_FUNCTION_1" % ("expr " * args_pos, opname)
  813. )
  814. self.add_make_function_rule(
  815. rule_pat, opname, token.attr, customize
  816. )
  817. if is_pypy or (i >= 2 and tokens[i - 2] == "LOAD_LAMBDA"):
  818. rule_pat = """
  819. expr ::= lambda_body
  820. lambda_body ::= %s%sLOAD_LAMBDA %%s%s
  821. """ % (
  822. ("expr " * args_pos),
  823. ("kwarg " * args_kw),
  824. opname,
  825. )
  826. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  827. continue
  828. args_pos, args_kw, annotate_args, closure = token.attr
  829. j = 2
  830. if has_get_iter_call_function1:
  831. rule_pat = (
  832. "generator_exp ::= %sload_genexpr %%s%s expr "
  833. "GET_ITER CALL_FUNCTION_1" % ("expr " * args_pos, opname)
  834. )
  835. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  836. if is_pypy or (i >= j and tokens[i - j] == "LOAD_LISTCOMP"):
  837. # In the tokens we saw:
  838. # LOAD_LISTCOMP LOAD_CONST MAKE_FUNCTION (>= 3.3) or
  839. # LOAD_LISTCOMP MAKE_FUNCTION (< 3.3) or
  840. # and have GET_ITER CALL_FUNCTION_1
  841. # Todo: For Pypy we need to modify this slightly
  842. rule_pat = (
  843. "list_comp ::= %sLOAD_LISTCOMP %%s%s expr "
  844. "GET_ITER CALL_FUNCTION_1" % ("expr " * args_pos, opname)
  845. )
  846. self.add_make_function_rule(
  847. rule_pat, opname, token.attr, customize
  848. )
  849. # FIXME: Fold test into add_make_function_rule
  850. if is_pypy or (i >= j and tokens[i - j] == "LOAD_LAMBDA"):
  851. rule_pat = """
  852. expr ::= lambda_body
  853. lambda_body ::= %s%sLOAD_LAMBDA %%s%s
  854. """ % (
  855. ("expr " * args_pos),
  856. ("kwarg " * args_kw),
  857. opname,
  858. )
  859. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  860. if args_kw == 0:
  861. kwargs = "no_kwargs"
  862. self.add_unique_rule("no_kwargs ::=", opname, token.attr, customize)
  863. else:
  864. kwargs = "kwargs"
  865. # positional args before keyword args
  866. rule = "mkfunc ::= %s%s %s%s" % (
  867. "expr " * args_pos,
  868. kwargs,
  869. "LOAD_CODE LOAD_STR ",
  870. opname,
  871. )
  872. self.add_unique_rule(rule, opname, token.attr, customize)
  873. elif opname == "RETURN_VALUE_LAMBDA":
  874. self.addRule(
  875. """
  876. return_expr_lambda ::= return_expr RETURN_VALUE_LAMBDA
  877. """,
  878. nop_func,
  879. )
  880. custom_ops_processed.add(opname)
  881. elif opname == "RAISE_VARARGS_0":
  882. self.addRule(
  883. """
  884. stmt ::= raise_stmt0
  885. last_stmt ::= raise_stmt0
  886. raise_stmt0 ::= RAISE_VARARGS_0
  887. """,
  888. nop_func,
  889. )
  890. custom_ops_processed.add(opname)
  891. elif opname == "RAISE_VARARGS_1":
  892. self.addRule(
  893. """
  894. stmt ::= raise_stmt1
  895. last_stmt ::= raise_stmt1
  896. raise_stmt1 ::= expr RAISE_VARARGS_1
  897. """,
  898. nop_func,
  899. )
  900. custom_ops_processed.add(opname)
  901. elif opname == "RAISE_VARARGS_2":
  902. self.addRule(
  903. """
  904. stmt ::= raise_stmt2
  905. last_stmt ::= raise_stmt2
  906. raise_stmt2 ::= expr expr RAISE_VARARGS_2
  907. """,
  908. nop_func,
  909. )
  910. custom_ops_processed.add(opname)
  911. elif opname == "SETUP_EXCEPT":
  912. self.addRule(
  913. """
  914. try_except ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
  915. except_handler opt_come_from_except
  916. c_try_except ::= SETUP_EXCEPT c_suite_stmts POP_BLOCK
  917. c_except_handler opt_come_from_except
  918. stmt ::= tryelsestmt3
  919. tryelsestmt3 ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
  920. except_handler COME_FROM else_suite
  921. opt_come_from_except
  922. tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
  923. except_handler else_suite come_from_except_clauses
  924. tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
  925. except_handler else_suite come_froms
  926. c_stmt ::= c_tryelsestmt
  927. c_tryelsestmt ::= SETUP_EXCEPT c_suite_stmts POP_BLOCK
  928. c_except_handler
  929. come_any_froms else_suitec
  930. come_from_except_clauses
  931. """,
  932. nop_func,
  933. )
  934. custom_ops_processed.add(opname)
  935. elif opname == "WITH_CLEANUP_START":
  936. rules_str = """
  937. stmt ::= with_null
  938. with_null ::= with_suffix
  939. with_suffix ::= WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
  940. """
  941. self.addRule(rules_str, nop_func)
  942. elif opname == "SETUP_WITH":
  943. rules_str = """
  944. stmt ::= with
  945. stmt ::= with_as_pass
  946. stmt ::= with_as
  947. c_stmt ::= c_with
  948. c_with ::= expr SETUP_WITH POP_TOP
  949. c_suite_stmts_opt
  950. COME_FROM_WITH
  951. with_suffix
  952. c_with ::= expr SETUP_WITH POP_TOP
  953. c_suite_stmts_opt
  954. POP_BLOCK LOAD_CONST COME_FROM_WITH
  955. with_suffix
  956. with ::= expr SETUP_WITH POP_TOP
  957. suite_stmts_opt
  958. COME_FROM_WITH
  959. with_suffix
  960. with_as ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH
  961. with_suffix
  962. with ::= expr
  963. SETUP_WITH POP_TOP suite_stmts_opt
  964. POP_BLOCK LOAD_CONST COME_FROM_WITH
  965. with_suffix
  966. with_as ::= expr
  967. SETUP_WITH store suite_stmts_opt
  968. POP_BLOCK LOAD_CONST COME_FROM_WITH
  969. with_suffix
  970. with ::= expr
  971. SETUP_WITH POP_TOP suite_stmts_opt
  972. POP_BLOCK LOAD_CONST COME_FROM_WITH
  973. with_suffix
  974. with_as ::= expr
  975. SETUP_WITH store suite_stmts_opt
  976. POP_BLOCK LOAD_CONST COME_FROM_WITH
  977. with_suffix
  978. """
  979. if self.version < (3, 8):
  980. rules_str += """
  981. with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
  982. LOAD_CONST
  983. with_suffix
  984. """
  985. else:
  986. rules_str += """
  987. # A return at the end of a withas stmt can be this.
  988. # FIXME: should this be a different kind of return?
  989. return ::= return_expr POP_BLOCK
  990. ROT_TWO
  991. BEGIN_FINALLY
  992. WITH_CLEANUP_START
  993. WITH_CLEANUP_FINISH
  994. POP_FINALLY
  995. RETURN_VALUE
  996. with ::= expr
  997. SETUP_WITH POP_TOP suite_stmts_opt
  998. POP_BLOCK LOAD_CONST COME_FROM_WITH
  999. with_suffix
  1000. with_as ::= expr
  1001. SETUP_WITH store suite_stmts
  1002. POP_BLOCK LOAD_CONST COME_FROM_WITH
  1003. with_as ::= expr
  1004. SETUP_WITH store suite_stmts
  1005. POP_BLOCK BEGIN_FINALLY COME_FROM_WITH
  1006. with_suffix
  1007. # with_as ::= expr SETUP_WITH store suite_stmts
  1008. # COME_FROM expr COME_FROM POP_BLOCK ROT_TWO
  1009. # BEGIN_FINALLY WITH_CLEANUP_START WITH_CLEANUP_FINISH
  1010. # POP_FINALLY RETURN_VALUE COME_FROM_WITH
  1011. # WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
  1012. with ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
  1013. BEGIN_FINALLY COME_FROM_WITH
  1014. with_suffix
  1015. """
  1016. self.addRule(rules_str, nop_func)
  1017. elif opname_base in ("UNPACK_EX",):
  1018. before_count, after_count = token.attr
  1019. rule = (
  1020. """
  1021. store ::= unpack
  1022. unpack ::= """
  1023. + opname
  1024. + " store" * (before_count + after_count + 1)
  1025. )
  1026. self.addRule(rule, nop_func)
  1027. elif opname_base == "UNPACK_SEQUENCE":
  1028. rule = (
  1029. """
  1030. store ::= unpack
  1031. unpack ::= """
  1032. + opname
  1033. + " store" * token.attr
  1034. )
  1035. self.addRule(rule, nop_func)
  1036. pass
  1037. self.reduce_check_table = {
  1038. "ifstmts_jump": ifstmts_jump_invalid,
  1039. "and": and_invalid,
  1040. "and_cond": and_cond_check,
  1041. "and_not": and_not_check,
  1042. "if_and_stmt": if_and_stmt,
  1043. "if_and_elsestmtc": if_and_elsestmt,
  1044. "ifelsestmt": ifelsestmt,
  1045. "ifelsestmtc": ifelsestmt,
  1046. "iflaststmt": iflaststmt,
  1047. "iflaststmtc": iflaststmt,
  1048. "if_not_stmtc": ifstmt,
  1049. "ifstmt": ifstmt,
  1050. "ifstmtc": ifstmt,
  1051. "lastc_stmt": lastc_stmt,
  1052. "list_if_not": list_if_not,
  1053. "not_or": not_or_check,
  1054. "or": or_check37_invalid,
  1055. "or_cond": or_cond_check_invalid,
  1056. "testtrue": testtrue,
  1057. "testfalsec": testtrue,
  1058. "while1elsestmt": while1elsestmt,
  1059. "while1stmt": while1stmt,
  1060. "whilestmt": whilestmt,
  1061. "c_tryelsestmt": c_tryelsestmt,
  1062. "c_try_except": tryexcept,
  1063. }
  1064. self.check_reduce["and"] = "AST"
  1065. self.check_reduce["and_cond"] = "AST"
  1066. self.check_reduce["and_not"] = "AST"
  1067. self.check_reduce["annotate_tuple"] = "tokens"
  1068. self.check_reduce["aug_assign1"] = "AST"
  1069. self.check_reduce["aug_assign2"] = "AST"
  1070. self.check_reduce["c_try_except"] = "AST"
  1071. self.check_reduce["c_tryelsestmt"] = "AST"
  1072. self.check_reduce["if_and_stmt"] = "AST"
  1073. self.check_reduce["if_and_elsestmtc"] = "AST"
  1074. self.check_reduce["if_not_stmtc"] = "AST"
  1075. self.check_reduce["ifelsestmt"] = "AST"
  1076. self.check_reduce["ifelsestmtc"] = "AST"
  1077. self.check_reduce["iflaststmt"] = "AST"
  1078. self.check_reduce["iflaststmtc"] = "AST"
  1079. self.check_reduce["ifstmt"] = "AST"
  1080. self.check_reduce["ifstmtc"] = "AST"
  1081. self.check_reduce["ifstmts_jump"] = "AST"
  1082. self.check_reduce["ifstmts_jumpc"] = "AST"
  1083. self.check_reduce["import_as37"] = "tokens"
  1084. self.check_reduce["import_from37"] = "AST"
  1085. self.check_reduce["import_from_as37"] = "tokens"
  1086. self.check_reduce["lastc_stmt"] = "tokens"
  1087. self.check_reduce["list_if_not"] = "AST"
  1088. self.check_reduce["while1elsestmt"] = "tokens"
  1089. self.check_reduce["while1stmt"] = "tokens"
  1090. self.check_reduce["whilestmt"] = "tokens"
  1091. self.check_reduce["not_or"] = "AST"
  1092. self.check_reduce["or"] = "AST"
  1093. self.check_reduce["or_cond"] = "tokens"
  1094. self.check_reduce["testtrue"] = "tokens"
  1095. self.check_reduce["testfalsec"] = "tokens"
  1096. return
  1097. def custom_classfunc_rule(self, opname, token, customize, next_token):
  1098. """
  1099. call ::= expr {expr}^n CALL_FUNCTION_n
  1100. call ::= expr {expr}^n CALL_FUNCTION_VAR_n
  1101. call ::= expr {expr}^n CALL_FUNCTION_VAR_KW_n
  1102. call ::= expr {expr}^n CALL_FUNCTION_KW_n
  1103. classdefdeco2 ::= LOAD_BUILD_CLASS mkfunc {expr}^n-1 CALL_FUNCTION_n
  1104. """
  1105. args_pos, args_kw = self.get_pos_kw(token)
  1106. # Additional exprs for * and ** args:
  1107. # 0 if neither
  1108. # 1 for CALL_FUNCTION_VAR or CALL_FUNCTION_KW
  1109. # 2 for * and ** args (CALL_FUNCTION_VAR_KW).
  1110. # Yes, this computation based on instruction name is a little bit hoaky.
  1111. nak = (len(opname) - len("CALL_FUNCTION")) // 3
  1112. uniq_param = args_kw + args_pos
  1113. if frozenset(("GET_AWAITABLE", "YIELD_FROM")).issubset(self.seen_ops):
  1114. rule = (
  1115. "async_call ::= expr "
  1116. + ("expr " * args_pos)
  1117. + ("kwarg " * args_kw)
  1118. + "expr " * nak
  1119. + token.kind
  1120. + " GET_AWAITABLE LOAD_CONST YIELD_FROM"
  1121. )
  1122. self.add_unique_rule(rule, token.kind, uniq_param, customize)
  1123. self.add_unique_rule(
  1124. "expr ::= async_call", token.kind, uniq_param, customize
  1125. )
  1126. if opname.startswith("CALL_FUNCTION_VAR"):
  1127. token.kind = self.call_fn_name(token)
  1128. if opname.endswith("KW"):
  1129. kw = "expr "
  1130. else:
  1131. kw = ""
  1132. rule = (
  1133. "call ::= expr expr "
  1134. + ("expr " * args_pos)
  1135. + ("kwarg " * args_kw)
  1136. + kw
  1137. + token.kind
  1138. )
  1139. # Note: semantic actions make use of the fact of whether "args_pos"
  1140. # zero or not in creating a template rule.
  1141. self.add_unique_rule(rule, token.kind, args_pos, customize)
  1142. else:
  1143. token.kind = self.call_fn_name(token)
  1144. uniq_param = args_kw + args_pos
  1145. # Note: 3.5+ have subclassed this method; so we don't handle
  1146. # 'CALL_FUNCTION_VAR' or 'CALL_FUNCTION_EX' here.
  1147. rule = (
  1148. "call ::= expr "
  1149. + ("expr " * args_pos)
  1150. + ("kwarg " * args_kw)
  1151. + "expr " * nak
  1152. + token.kind
  1153. )
  1154. self.add_unique_rule(rule, token.kind, uniq_param, customize)
  1155. if "LOAD_BUILD_CLASS" in self.seen_ops:
  1156. if (
  1157. next_token == "CALL_FUNCTION"
  1158. and next_token.attr == 1
  1159. and args_pos > 1
  1160. ):
  1161. rule = "classdefdeco2 ::= LOAD_BUILD_CLASS mkfunc %s%s_%d" % (
  1162. ("expr " * (args_pos - 1)),
  1163. opname,
  1164. args_pos,
  1165. )
  1166. self.add_unique_rule(rule, token.kind, uniq_param, customize)
  1167. def reduce_is_invalid(self, rule, ast, tokens, first, last):
  1168. lhs = rule[0]
  1169. n = len(tokens)
  1170. last = min(last, n - 1)
  1171. fn = self.reduce_check_table.get(lhs, None)
  1172. try:
  1173. if fn:
  1174. return fn(self, lhs, n, rule, ast, tokens, first, last)
  1175. except Exception:
  1176. import sys
  1177. import traceback
  1178. print(
  1179. f"Exception in {fn.__name__} {sys.exc_info()[1]}\n"
  1180. + f"rule: {rule2str(rule)}\n"
  1181. + f"offsets {tokens[first].offset} .. {tokens[last].offset}"
  1182. )
  1183. print(traceback.print_tb(sys.exc_info()[2], -1))
  1184. raise ParserError(tokens[last], tokens[last].off2int(), self.debug["rules"])
  1185. if lhs in ("aug_assign1", "aug_assign2") and ast[0][0] == "and":
  1186. return True
  1187. elif lhs == "annotate_tuple":
  1188. return not isinstance(tokens[first].attr, tuple)
  1189. elif lhs == "import_from37":
  1190. importlist37 = ast[3]
  1191. alias37 = importlist37[0]
  1192. if importlist37 == "importlist37" and alias37 == "alias37":
  1193. store = alias37[1]
  1194. assert store == "store"
  1195. return alias37[0].attr != store[0].attr
  1196. return False
  1197. elif lhs == "import_as37":
  1198. return tokens[first + 1].pattr is not None
  1199. elif lhs == "import_from_as37":
  1200. return tokens[first + 1].pattr is None
  1201. return False