parse3.py 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816
  1. # Copyright (c) 2015-2024 Rocky Bernstein
  2. # Copyright (c) 2005 by Dan Pascu <dan@windowmaker.org>
  3. # Copyright (c) 2000-2002 by hartmut Goebel <h.goebel@crazy-compilers.com>
  4. # Copyright (c) 1999 John Aycock
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. """
  19. A spark grammar for Python 3.x.
  20. However instead of terminal symbols being the usual ASCII text,
  21. e.g. 5, myvariable, "for", etc. they are CPython Bytecode tokens,
  22. e.g. "LOAD_CONST 5", "STORE NAME myvariable", "SETUP_LOOP", etc.
  23. If we succeed in creating a parse tree, then we have a Python program
  24. that a later phase can turn into a sequence of ASCII text.
  25. """
  26. import re
  27. from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
  28. from uncompyle6.parser import PythonParser, PythonParserSingle, nop_func
  29. from uncompyle6.parsers.reducecheck import (
  30. and_invalid,
  31. except_handler_else,
  32. ifelsestmt,
  33. iflaststmt,
  34. ifstmt,
  35. or_check,
  36. testtrue,
  37. tryelsestmtl3,
  38. tryexcept,
  39. while1stmt,
  40. )
  41. from uncompyle6.parsers.treenode import SyntaxTree
  42. from uncompyle6.scanners.tok import Token
  43. class Python3Parser(PythonParser):
  44. def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
  45. self.added_rules = set()
  46. super(Python3Parser, self).__init__(SyntaxTree, "stmts", debug=debug_parser)
  47. self.new_rules = set()
  48. def p_comprehension3(self, args):
  49. """
  50. # Python3 scanner adds LOAD_LISTCOMP. Python3 does list comprehension like
  51. # other comprehensions (set, dictionary).
  52. # Our "continue" heuristic - in two successive JUMP_BACKS, the first
  53. # one may be a continue - sometimes classifies a JUMP_BACK
  54. # as a CONTINUE. The two are kind of the same in a comprehension.
  55. comp_for ::= expr for_iter store comp_iter CONTINUE
  56. comp_for ::= expr for_iter store comp_iter JUMP_BACK
  57. list_comp ::= BUILD_LIST_0 list_iter
  58. lc_body ::= expr LIST_APPEND
  59. list_for ::= expr_or_arg
  60. FOR_ITER
  61. store list_iter jb_or_c
  62. # This is seen in PyPy, but possibly it appears on other Python 3?
  63. list_if ::= expr jmp_false list_iter COME_FROM
  64. list_if_not ::= expr jmp_true list_iter COME_FROM
  65. jb_or_c ::= JUMP_BACK
  66. jb_or_c ::= CONTINUE
  67. jb_cfs ::= JUMP_BACK _come_froms
  68. stmt ::= set_comp_func
  69. # TODO this can be simplified
  70. set_comp_func ::= BUILD_SET_0 LOAD_ARG FOR_ITER store comp_iter
  71. JUMP_BACK ending_return
  72. set_comp_func ::= BUILD_SET_0 LOAD_FAST FOR_ITER store comp_iter
  73. JUMP_BACK ending_return
  74. set_comp_func ::= BUILD_SET_0 LOAD_ARG FOR_ITER store comp_iter
  75. COME_FROM JUMP_BACK ending_return
  76. comp_body ::= dict_comp_body
  77. comp_body ::= set_comp_body
  78. dict_comp_body ::= expr expr MAP_ADD
  79. set_comp_body ::= expr SET_ADD
  80. expr_or_arg ::= LOAD_ARG
  81. expr_or_arg ::= expr
  82. # See also common Python p_list_comprehension
  83. """
  84. def p_dict_comp3(self, args):
  85. """ "
  86. expr ::= dict_comp
  87. stmt ::= dict_comp_func
  88. dict_comp_func ::= BUILD_MAP_0 LOAD_ARG FOR_ITER store
  89. comp_iter JUMP_BACK RETURN_VALUE RETURN_LAST
  90. dict_comp_func ::= BUILD_MAP_0 LOAD_ARG FOR_ITER store
  91. comp_iter JUMP_BACK RETURN_VALUE_LAMBDA LAMBDA_MARKER
  92. dict_comp_func ::= BUILD_MAP_0 LOAD_FAST FOR_ITER store
  93. comp_iter JUMP_BACK RETURN_VALUE RETURN_LAST
  94. dict_comp_func ::= BUILD_MAP_0 LOAD_FAST FOR_ITER store
  95. comp_iter JUMP_BACK RETURN_VALUE_LAMBDA LAMBDA_MARKER
  96. comp_iter ::= comp_if_not
  97. comp_if_not ::= expr jmp_true comp_iter
  98. """
  99. def p_grammar(self, args):
  100. """
  101. sstmt ::= stmt
  102. stmt ::= ifelsestmtr
  103. sstmt ::= return RETURN_LAST
  104. return_if_stmts ::= return_if_stmt come_from_opt
  105. return_if_stmts ::= _stmts return_if_stmt _come_froms
  106. return_if_stmt ::= return_expr RETURN_END_IF
  107. returns ::= _stmts return_if_stmt
  108. stmt ::= break
  109. break ::= BREAK_LOOP
  110. stmt ::= continue
  111. continue ::= CONTINUE
  112. continues ::= _stmts lastl_stmt continue
  113. continues ::= lastl_stmt continue
  114. continues ::= continue
  115. kwarg ::= LOAD_STR expr
  116. kwargs ::= kwarg+
  117. classdef ::= build_class store
  118. # FIXME: we need to add these because don't detect this properly
  119. # in custom rules. Specifically if one of the exprs is CALL_FUNCTION
  120. # then we'll mistake that for the final CALL_FUNCTION.
  121. # We can fix by triggering on the CALL_FUNCTION op
  122. # Python3 introduced LOAD_BUILD_CLASS
  123. # Other definitions are in a custom rule
  124. build_class ::= LOAD_BUILD_CLASS mkfunc expr call CALL_FUNCTION_3
  125. build_class ::= LOAD_BUILD_CLASS mkfunc expr call expr CALL_FUNCTION_4
  126. stmt ::= classdefdeco
  127. classdefdeco ::= classdefdeco1 store
  128. expr ::= LOAD_ASSERT
  129. assert ::= assert_expr jmp_true LOAD_ASSERT RAISE_VARARGS_1 COME_FROM
  130. stmt ::= assert2
  131. assert2 ::= assert_expr jmp_true LOAD_ASSERT expr
  132. CALL_FUNCTION_1 RAISE_VARARGS_1 COME_FROM
  133. assert_expr ::= expr
  134. assert_expr ::= assert_expr_or
  135. assert_expr ::= assert_expr_and
  136. assert_expr_or ::= assert_expr jmp_true expr
  137. assert_expr_and ::= assert_expr jmp_false expr
  138. ifstmt ::= testexpr _ifstmts_jump
  139. testexpr ::= testfalse
  140. testexpr ::= testtrue
  141. testfalse ::= expr jmp_false
  142. testtrue ::= expr jmp_true
  143. _ifstmts_jump ::= return_if_stmts
  144. _ifstmts_jump ::= stmts _come_froms
  145. _ifstmts_jumpl ::= c_stmts_opt come_froms
  146. iflaststmt ::= testexpr stmts_opt JUMP_ABSOLUTE
  147. iflaststmt ::= testexpr _ifstmts_jumpl
  148. # ifstmts where we are in a loop
  149. _ifstmts_jumpl ::= _ifstmts_jump
  150. iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK
  151. iflaststmtl ::= testexpr _ifstmts_jumpl
  152. # These are used to keep parse tree indices the same
  153. jump_forward_else ::= JUMP_FORWARD ELSE
  154. jump_absolute_else ::= JUMP_ABSOLUTE ELSE
  155. # Note: in if/else kinds of statements, we err on the side
  156. # of missing "else" clauses. Therefore we include grammar
  157. # rules with and without ELSE.
  158. ifelsestmt ::= testexpr stmts_opt JUMP_FORWARD
  159. else_suite opt_come_from_except
  160. ifelsestmt ::= testexpr stmts_opt jump_forward_else
  161. else_suite _come_froms
  162. # ifelsestmt ::= testexpr c_stmts_opt jump_forward_else
  163. # pass _come_froms
  164. # FIXME: remove this
  165. stmt ::= ifelsestmtc
  166. c_stmts ::= ifelsestmtc
  167. ifelsestmtc ::= testexpr c_stmts_opt JUMP_ABSOLUTE else_suitec
  168. ifelsestmtc ::= testexpr c_stmts_opt jump_absolute_else else_suitec
  169. ifelsestmtc ::= testexpr c_stmts_opt jump_forward_else else_suitec _come_froms
  170. # "if"/"else" statement that ends in a RETURN
  171. ifelsestmtr ::= testexpr return_if_stmts returns
  172. ifelsestmtl ::= testexpr c_stmts_opt JUMP_BACK else_suitel
  173. ifelsestmtl ::= testexpr c_stmts_opt cf_jump_back else_suitel
  174. ifelsestmtl ::= testexpr c_stmts_opt continue else_suitel
  175. cf_jump_back ::= COME_FROM JUMP_BACK
  176. # FIXME: this feels like a hack. Is it just 1 or two
  177. # COME_FROMs? the parsed tree for this and even with just the
  178. # one COME_FROM for Python 2.7 seems to associate the
  179. # COME_FROM targets from the wrong places
  180. # this is nested inside a try_except
  181. tryfinallystmt ::= SETUP_FINALLY suite_stmts_opt
  182. POP_BLOCK LOAD_CONST
  183. COME_FROM_FINALLY suite_stmts_opt END_FINALLY
  184. except_handler_else ::= except_handler
  185. except_handler ::= jmp_abs COME_FROM except_stmts
  186. END_FINALLY
  187. except_handler ::= jmp_abs COME_FROM_EXCEPT except_stmts
  188. END_FINALLY
  189. # FIXME: remove this
  190. except_handler ::= JUMP_FORWARD COME_FROM except_stmts
  191. END_FINALLY COME_FROM
  192. except_handler ::= JUMP_FORWARD COME_FROM except_stmts
  193. END_FINALLY COME_FROM_EXCEPT
  194. except_stmts ::= except_stmt+
  195. except_stmt ::= except_cond1 except_suite
  196. except_stmt ::= except_cond2 except_suite
  197. except_stmt ::= except_cond2 except_suite_finalize
  198. except_stmt ::= except
  199. ## FIXME: what's except_pop_except?
  200. except_stmt ::= except_pop_except
  201. # Python3 introduced POP_EXCEPT
  202. except_suite ::= c_stmts_opt POP_EXCEPT jump_except
  203. jump_except ::= JUMP_ABSOLUTE
  204. jump_except ::= JUMP_BACK
  205. jump_except ::= JUMP_FORWARD
  206. jump_except ::= CONTINUE
  207. # This is used in Python 3 in
  208. # "except ... as e" to remove 'e' after the c_stmts_opt finishes
  209. except_suite_finalize ::= SETUP_FINALLY c_stmts_opt except_var_finalize
  210. END_FINALLY _jump
  211. except_var_finalize ::= POP_BLOCK POP_EXCEPT LOAD_CONST COME_FROM_FINALLY
  212. LOAD_CONST store delete
  213. except_suite ::= returns
  214. except_cond1 ::= DUP_TOP expr COMPARE_OP
  215. jmp_false POP_TOP POP_TOP POP_TOP
  216. except_cond2 ::= DUP_TOP expr COMPARE_OP
  217. jmp_false POP_TOP store POP_TOP
  218. except ::= POP_TOP POP_TOP POP_TOP c_stmts_opt POP_EXCEPT _jump
  219. except ::= POP_TOP POP_TOP POP_TOP returns
  220. jmp_abs ::= JUMP_ABSOLUTE
  221. jmp_abs ::= JUMP_BACK
  222. with ::= expr SETUP_WITH POP_TOP suite_stmts_opt
  223. POP_BLOCK LOAD_CONST COME_FROM_WITH
  224. WITH_CLEANUP END_FINALLY
  225. with_as ::= expr SETUP_WITH store suite_stmts_opt
  226. POP_BLOCK LOAD_CONST COME_FROM_WITH
  227. WITH_CLEANUP END_FINALLY
  228. expr_jt ::= expr jmp_true
  229. expr_jitop ::= expr JUMP_IF_TRUE_OR_POP
  230. ## FIXME: Right now we have erroneous jump targets
  231. ## This below is probably not correct when the COME_FROM is put in the right place
  232. and ::= expr jmp_false expr COME_FROM
  233. or ::= expr_jt expr COME_FROM
  234. or ::= expr_jt expr
  235. or ::= expr_jitop expr COME_FROM
  236. and ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM
  237. # # something like the below is needed when the jump targets are fixed
  238. ## or ::= expr JUMP_IF_TRUE_OR_POP COME_FROM expr
  239. ## and ::= expr JUMP_IF_FALSE_OR_POP COME_FROM expr
  240. """
  241. def p_misc3(self, args):
  242. """
  243. except_handler ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts
  244. END_FINALLY COME_FROM
  245. except_handler ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts
  246. END_FINALLY COME_FROM_EXCEPT_CLAUSE
  247. for_block ::= l_stmts_opt COME_FROM_LOOP JUMP_BACK
  248. for_block ::= l_stmts
  249. iflaststmtl ::= testexpr c_stmts_opt
  250. """
  251. def p_def_annotations3(self, args):
  252. """
  253. # Annotated functions
  254. stmt ::= function_def_annotate
  255. function_def_annotate ::= mkfunc_annotate store
  256. mkfuncdeco0 ::= mkfunc_annotate
  257. # This has the annotation value.
  258. # LOAD_NAME is used in an annotation type like
  259. # int, float, str
  260. annotate_arg ::= LOAD_NAME
  261. # LOAD_CONST is used in an annotation string
  262. annotate_arg ::= expr
  263. # This stores the tuple of parameter names
  264. # that have been annotated
  265. annotate_tuple ::= LOAD_CONST
  266. """
  267. def p_come_from3(self, args):
  268. """
  269. opt_come_from_except ::= COME_FROM_EXCEPT
  270. opt_come_from_except ::= _come_froms
  271. opt_come_from_except ::= come_from_except_clauses
  272. come_from_except_clauses ::= COME_FROM_EXCEPT_CLAUSE+
  273. """
  274. def p_jump3(self, args):
  275. """
  276. jmp_false ::= POP_JUMP_IF_FALSE
  277. jmp_true ::= POP_JUMP_IF_TRUE
  278. # FIXME: Common with 2.7
  279. ret_and ::= expr JUMP_IF_FALSE_OR_POP return_expr_or_cond COME_FROM
  280. ret_or ::= expr JUMP_IF_TRUE_OR_POP return_expr_or_cond COME_FROM
  281. if_exp_ret ::= expr POP_JUMP_IF_FALSE expr RETURN_END_IF COME_FROM
  282. return_expr_or_cond
  283. # compared_chained_middle is used exclusively in chained_compare
  284. compared_chained_middle ::= expr DUP_TOP ROT_THREE COMPARE_OP JUMP_IF_FALSE_OR_POP
  285. compared_chained_middle COME_FROM
  286. compared_chained_middle ::= expr DUP_TOP ROT_THREE COMPARE_OP JUMP_IF_FALSE_OR_POP
  287. compare_chained_right COME_FROM
  288. """
  289. def p_stmt3(self, args):
  290. """
  291. stmt ::= if_exp_lambda
  292. stmt ::= if_exp_not_lambda
  293. if_exp_lambda ::= expr jmp_false expr return_if_lambda
  294. return_stmt_lambda LAMBDA_MARKER
  295. if_exp_not_lambda ::= expr jmp_true expr return_if_lambda
  296. return_stmt_lambda LAMBDA_MARKER
  297. return_stmt_lambda ::= return_expr RETURN_VALUE_LAMBDA
  298. return_if_lambda ::= RETURN_END_IF_LAMBDA
  299. stmt ::= return_closure
  300. return_closure ::= LOAD_CLOSURE RETURN_VALUE RETURN_LAST
  301. stmt ::= whileTruestmt
  302. ifelsestmt ::= testexpr c_stmts_opt JUMP_FORWARD else_suite _come_froms
  303. # FIXME: go over this
  304. _stmts ::= _stmts last_stmt
  305. stmts ::= last_stmt
  306. stmts_opt ::= stmts
  307. last_stmt ::= iflaststmt
  308. last_stmt ::= forelselaststmt
  309. iflaststmt ::= testexpr last_stmt JUMP_ABSOLUTE
  310. iflaststmt ::= testexpr stmts JUMP_ABSOLUTE
  311. _iflaststmts_jump ::= stmts last_stmt
  312. _ifstmts_jump ::= stmts_opt JUMP_FORWARD _come_froms
  313. iflaststmt ::= testexpr _iflaststmts_jump
  314. ifelsestmt ::= testexpr stmts_opt jump_absolute_else else_suite
  315. ifelsestmt ::= testexpr stmts_opt jump_forward_else else_suite _come_froms
  316. else_suite ::= stmts
  317. else_suitel ::= stmts
  318. # FIXME: remove this
  319. _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD _come_froms
  320. # statements with continue and break
  321. c_stmts ::= _stmts
  322. c_stmts ::= _stmts lastc_stmt
  323. c_stmts ::= lastc_stmt
  324. c_stmts ::= continues
  325. lastc_stmt ::= iflaststmtl
  326. lastc_stmt ::= forelselaststmt
  327. lastc_stmt ::= ifelsestmtc
  328. # Statements in a loop
  329. lstmt ::= stmt
  330. l_stmts ::= lstmt+
  331. """
  332. def p_loop_stmt3(self, args):
  333. """
  334. stmt ::= whileelsestmt2
  335. for ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK
  336. COME_FROM_LOOP
  337. forelsestmt ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK
  338. else_suite COME_FROM_LOOP
  339. forelselaststmt ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK
  340. else_suitec COME_FROM_LOOP
  341. forelselaststmtl ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK
  342. else_suitel COME_FROM_LOOP
  343. whilestmt ::= SETUP_LOOP testexpr l_stmts_opt COME_FROM JUMP_BACK
  344. POP_BLOCK COME_FROM_LOOP
  345. whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
  346. JUMP_BACK COME_FROM_LOOP
  347. whilestmt ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
  348. COME_FROM_LOOP
  349. whilestmt ::= SETUP_LOOP testexpr returns POP_BLOCK
  350. COME_FROM_LOOP
  351. while1elsestmt ::= SETUP_LOOP l_stmts JUMP_BACK
  352. else_suitel
  353. whileelsestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_cfs POP_BLOCK
  354. else_suitel COME_FROM_LOOP
  355. whileelsestmt2 ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
  356. else_suitel JUMP_BACK COME_FROM_LOOP
  357. whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK
  358. COME_FROM_LOOP
  359. # FIXME: Python 3.? starts adding branch optimization? Put this starting there.
  360. while1stmt ::= SETUP_LOOP l_stmts COME_FROM_LOOP
  361. while1stmt ::= SETUP_LOOP l_stmts COME_FROM JUMP_BACK COME_FROM_LOOP
  362. while1elsestmt ::= SETUP_LOOP l_stmts JUMP_BACK
  363. else_suite COME_FROM_LOOP
  364. # FIXME: investigate - can code really produce a NOP?
  365. whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK NOP
  366. COME_FROM_LOOP
  367. whileTruestmt ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK NOP
  368. COME_FROM_LOOP
  369. for ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK NOP
  370. COME_FROM_LOOP
  371. """
  372. def p_generator_exp3(self, args):
  373. """
  374. load_genexpr ::= LOAD_GENEXPR
  375. load_genexpr ::= BUILD_TUPLE_1 LOAD_GENEXPR LOAD_STR
  376. """
  377. def p_expr3(self, args):
  378. """
  379. expr ::= LOAD_STR
  380. expr ::= if_exp_not
  381. if_exp_not ::= expr jmp_true expr jump_forward_else expr COME_FROM
  382. # a JUMP_FORWARD to another JUMP_FORWARD can get turned into
  383. # a JUMP_ABSOLUTE with no COME_FROM
  384. if_exp ::= expr jmp_false expr jump_absolute_else expr
  385. # if_exp_true are for conditions which always evaluate true
  386. # There is dead or non-optional remnants of the condition code though,
  387. # and we use that to match on to reconstruct the source more accurately
  388. expr ::= if_exp_true
  389. if_exp_true ::= expr JUMP_FORWARD expr COME_FROM
  390. """
  391. @staticmethod
  392. def call_fn_name(token):
  393. """Customize CALL_FUNCTION to add the number of positional arguments"""
  394. if token.attr is not None:
  395. return "%s_%i" % (token.kind, token.attr)
  396. else:
  397. return "%s_0" % (token.kind)
  398. def custom_build_class_rule(self, opname, i, token, tokens, customize, is_pypy):
  399. """
  400. # Should the first rule be somehow folded into the 2nd one?
  401. build_class ::= LOAD_BUILD_CLASS mkfunc
  402. LOAD_CLASSNAME {expr}^n-1 CALL_FUNCTION_n
  403. LOAD_CONST CALL_FUNCTION_n
  404. build_class ::= LOAD_BUILD_CLASS mkfunc
  405. expr
  406. call
  407. CALL_FUNCTION_3
  408. """
  409. # FIXME: I bet this can be simplified
  410. # look for next MAKE_FUNCTION
  411. for i in range(i + 1, len(tokens)):
  412. if tokens[i].kind.startswith("MAKE_FUNCTION"):
  413. break
  414. elif tokens[i].kind.startswith("MAKE_CLOSURE"):
  415. break
  416. pass
  417. assert i < len(
  418. tokens
  419. ), "build_class needs to find MAKE_FUNCTION or MAKE_CLOSURE"
  420. assert (
  421. tokens[i + 1].kind == "LOAD_STR"
  422. ), "build_class expecting CONST after MAKE_FUNCTION/MAKE_CLOSURE"
  423. call_fn_tok = None
  424. for i in range(i, len(tokens)):
  425. if tokens[i].kind.startswith("CALL_FUNCTION"):
  426. call_fn_tok = tokens[i]
  427. break
  428. if not call_fn_tok:
  429. raise RuntimeError(
  430. "build_class custom rule for %s needs to find CALL_FUNCTION" % opname
  431. )
  432. # customize build_class rule
  433. # FIXME: What's the deal with the two rules? Different Python versions?
  434. # Different situations? Note that the above rule is based on the CALL_FUNCTION
  435. # token found, while this one doesn't.
  436. if self.version < (3, 6):
  437. call_function = self.call_fn_name(call_fn_tok)
  438. pos_args_count, kw_args_count = self.get_pos_kw(call_fn_tok)
  439. rule = "build_class ::= LOAD_BUILD_CLASS mkfunc %s" "%s" % (
  440. ("expr " * (pos_args_count - 1) + ("kwarg " * kw_args_count)),
  441. call_function,
  442. )
  443. else:
  444. # 3.6+ handling
  445. call_function = call_fn_tok.kind
  446. if call_function.startswith("CALL_FUNCTION_KW"):
  447. self.addRule("classdef ::= build_class_kw store", nop_func)
  448. if is_pypy:
  449. pos_args_count, kw_args_count = self.get_pos_kw(call_fn_tok)
  450. rule = "build_class_kw ::= LOAD_BUILD_CLASS mkfunc %s%s%s" % (
  451. "expr " * (pos_args_count - 1),
  452. "kwarg " * (kw_args_count),
  453. call_function,
  454. )
  455. else:
  456. rule = (
  457. "build_class_kw ::= LOAD_BUILD_CLASS mkfunc %sLOAD_CONST %s"
  458. % ("expr " * (call_fn_tok.attr - 1), call_function)
  459. )
  460. else:
  461. call_function = self.call_fn_name(call_fn_tok)
  462. rule = "build_class ::= LOAD_BUILD_CLASS mkfunc %s%s" % (
  463. "expr " * (call_fn_tok.attr - 1),
  464. call_function,
  465. )
  466. self.addRule(rule, nop_func)
  467. return
  468. def custom_classfunc_rule(self, opname, token, customize, next_token, is_pypy):
  469. """
  470. call ::= expr {expr}^n CALL_FUNCTION_n
  471. call ::= expr {expr}^n CALL_FUNCTION_VAR_n
  472. call ::= expr {expr}^n CALL_FUNCTION_VAR_KW_n
  473. call ::= expr {expr}^n CALL_FUNCTION_KW_n
  474. classdefdeco2 ::= LOAD_BUILD_CLASS mkfunc {expr}^n-1 CALL_FUNCTION_n
  475. """
  476. pos_args_count, kw_args_count = self.get_pos_kw(token)
  477. # Additional exprs for * and ** args:
  478. # 0 if neither
  479. # 1 for CALL_FUNCTION_VAR or CALL_FUNCTION_KW
  480. # 2 for * and ** args (CALL_FUNCTION_VAR_KW).
  481. # Yes, this computation based on instruction name is a little bit hoaky.
  482. nak = (len(opname) - len("CALL_FUNCTION")) // 3
  483. uniq_param = kw_args_count + pos_args_count
  484. # Note: 3.5+ have subclassed this method; so we don't handle
  485. # 'CALL_FUNCTION_VAR' or 'CALL_FUNCTION_EX' here.
  486. if is_pypy and self.version >= (3, 6):
  487. if token == "CALL_FUNCTION":
  488. token.kind = self.call_fn_name(token)
  489. rule = (
  490. "call ::= expr "
  491. + ("pos_arg " * pos_args_count)
  492. + ("kwarg " * kw_args_count)
  493. + token.kind
  494. )
  495. else:
  496. token.kind = self.call_fn_name(token)
  497. rule = (
  498. "call ::= expr "
  499. + ("pos_arg " * pos_args_count)
  500. + ("kwarg " * kw_args_count)
  501. + "expr " * nak
  502. + token.kind
  503. )
  504. self.add_unique_rule(rule, token.kind, uniq_param, customize)
  505. if "LOAD_BUILD_CLASS" in self.seen_ops:
  506. if (
  507. next_token == "CALL_FUNCTION"
  508. and next_token.attr == 1
  509. and pos_args_count > 1
  510. ):
  511. rule = "classdefdeco2 ::= LOAD_BUILD_CLASS mkfunc %s%s_%d" % (
  512. ("expr " * (pos_args_count - 1)),
  513. opname,
  514. pos_args_count,
  515. )
  516. self.add_unique_rule(rule, token.kind, uniq_param, customize)
  517. def add_make_function_rule(self, rule, opname, attr, customize):
  518. """Python 3.3 added a an additional LOAD_STR before MAKE_FUNCTION and
  519. this has an effect on many rules.
  520. """
  521. if self.version >= (3, 3):
  522. load_op = "LOAD_STR "
  523. new_rule = rule % ((load_op) * 1)
  524. else:
  525. new_rule = rule % (("LOAD_STR ") * 0)
  526. self.add_unique_rule(new_rule, opname, attr, customize)
  527. def customize_grammar_rules(self, tokens, customize):
  528. """The base grammar we start out for a Python version even with the
  529. subclassing is, well, is pretty base. And we want it that way: lean and
  530. mean so that parsing will go faster.
  531. Here, we add additional grammar rules based on specific instructions
  532. that are in the instruction/token stream. In classes that
  533. inherit from from here and other versions, grammar rules may
  534. also be removed.
  535. For example if we see a pretty rare DELETE_DEREF instruction we'll
  536. add the grammar for that.
  537. More importantly, here we add grammar rules for instructions
  538. that may access a variable number of stack items. CALL_FUNCTION,
  539. BUILD_LIST and so on are like this.
  540. Without custom rules, there can be an super-exponential number of
  541. derivations. See the deparsing paper for an elaboration of
  542. this.
  543. """
  544. self.is_pypy = False
  545. # For a rough break out on the first word. This may
  546. # include instructions that don't need customization,
  547. # but we'll do a finer check after the rough breakout.
  548. customize_instruction_basenames = frozenset(
  549. (
  550. "BUILD",
  551. "CALL",
  552. "CONTINUE",
  553. "DELETE",
  554. "GET",
  555. "JUMP",
  556. "LOAD",
  557. "LOOKUP",
  558. "MAKE",
  559. "RETURN",
  560. "RAISE",
  561. "SETUP",
  562. "UNPACK",
  563. "WITH",
  564. )
  565. )
  566. # Opcode names in the custom_ops_processed set have rules that get added
  567. # unconditionally and the rules are constant. So they need to be done
  568. # only once and if we see the opcode a second we don't have to consider
  569. # adding more rules.
  570. #
  571. # Note: BUILD_TUPLE_UNPACK_WITH_CALL gets considered by
  572. # default because it starts with BUILD. So we'll set to ignore it from
  573. # the start.
  574. custom_ops_processed = {"BUILD_TUPLE_UNPACK_WITH_CALL"}
  575. # A set of instruction operation names that exist in the token stream.
  576. # We use this customize the grammar that we create.
  577. # 2.6-compatible set comprehensions
  578. self.seen_ops = frozenset([t.kind for t in tokens])
  579. self.seen_op_basenames = frozenset(
  580. [opname[: opname.rfind("_")] for opname in self.seen_ops]
  581. )
  582. # Loop over instructions adding custom grammar rules based on
  583. # a specific instruction seen.
  584. if "PyPy" in customize:
  585. self.is_pypy = True
  586. self.addRule(
  587. """
  588. stmt ::= assign3_pypy
  589. stmt ::= assign2_pypy
  590. assign3_pypy ::= expr expr expr store store store
  591. assign2_pypy ::= expr expr store store
  592. stmt ::= if_exp_lambda
  593. stmt ::= if_exp_not_lambda
  594. if_expr_lambda ::= expr jmp_false expr return_if_lambda
  595. return_expr_lambda LAMBDA_MARKER
  596. if_exp_not_lambda ::= expr jmp_true expr return_if_lambda
  597. return_expr_lambda LAMBDA_MARKER
  598. """,
  599. nop_func,
  600. )
  601. n = len(tokens)
  602. # Determine if we have an iteration CALL_FUNCTION_1.
  603. has_get_iter_call_function1 = False
  604. for i, token in enumerate(tokens):
  605. if (
  606. token == "GET_ITER"
  607. and i < n - 2
  608. and self.call_fn_name(tokens[i + 1]) == "CALL_FUNCTION_1"
  609. ):
  610. has_get_iter_call_function1 = True
  611. for i, token in enumerate(tokens):
  612. opname = token.kind
  613. # Do a quick breakout before testing potentially
  614. # each of the dozen or so instruction in if elif.
  615. if (
  616. opname[: opname.find("_")] not in customize_instruction_basenames
  617. or opname in custom_ops_processed
  618. ):
  619. continue
  620. opname_base = opname[: opname.rfind("_")]
  621. # The order of opname listed is roughly sorted below
  622. if opname_base == "BUILD_CONST_KEY_MAP":
  623. # This is in 3.6+
  624. kvlist_n = "expr " * (token.attr)
  625. rule = "dict ::= %sLOAD_CONST %s" % (kvlist_n, opname)
  626. self.addRule(rule, nop_func)
  627. elif opname in ("BUILD_CONST_LIST", "BUILD_CONST_DICT", "BUILD_CONST_SET"):
  628. if opname == "BUILD_CONST_DICT":
  629. rule = (
  630. """
  631. add_consts ::= ADD_VALUE*
  632. const_list ::= COLLECTION_START add_consts %s
  633. dict ::= const_list
  634. expr ::= dict
  635. """
  636. % opname
  637. )
  638. else:
  639. rule = (
  640. """
  641. add_consts ::= ADD_VALUE*
  642. const_list ::= COLLECTION_START add_consts %s
  643. expr ::= const_list
  644. """
  645. % opname
  646. )
  647. self.addRule(rule, nop_func)
  648. elif opname.startswith("BUILD_DICT_OLDER"):
  649. rule = """dict ::= COLLECTION_START key_value_pairs BUILD_DICT_OLDER
  650. key_value_pairs ::= key_value_pair+
  651. key_value_pair ::= ADD_KEY ADD_VALUE
  652. """
  653. self.addRule(rule, nop_func)
  654. elif opname.startswith("BUILD_LIST_UNPACK"):
  655. v = token.attr
  656. rule = "build_list_unpack ::= %s%s" % ("expr " * v, opname)
  657. self.addRule(rule, nop_func)
  658. rule = "expr ::= build_list_unpack"
  659. self.addRule(rule, nop_func)
  660. elif opname_base in ("BUILD_MAP", "BUILD_MAP_UNPACK"):
  661. kvlist_n = "kvlist_%s" % token.attr
  662. if opname == "BUILD_MAP_n":
  663. # PyPy sometimes has no count. Sigh.
  664. rule = (
  665. "dict_comp_func ::= BUILD_MAP_n LOAD_FAST FOR_ITER store "
  666. "comp_iter JUMP_BACK RETURN_VALUE RETURN_LAST"
  667. )
  668. self.add_unique_rule(rule, "dict_comp_func", 1, customize)
  669. kvlist_n = "kvlist_n"
  670. rule = "kvlist_n ::= kvlist_n kv3"
  671. self.add_unique_rule(rule, "kvlist_n", 0, customize)
  672. rule = "kvlist_n ::="
  673. self.add_unique_rule(rule, "kvlist_n", 1, customize)
  674. rule = "dict ::= BUILD_MAP_n kvlist_n"
  675. elif self.version >= (3, 5):
  676. if not opname.startswith("BUILD_MAP_WITH_CALL"):
  677. # FIXME: Use the attr
  678. # so this doesn't run into exponential parsing time.
  679. if opname.startswith("BUILD_MAP_UNPACK"):
  680. # FIXME: start here. The LHS should be dict_unpack, not dict.
  681. # FIXME: really we need a combination of dict_entry-like things.
  682. # It just so happens the most common case is not to mix
  683. # dictionary comphensions with dictionary, elements
  684. if "LOAD_DICTCOMP" in self.seen_ops:
  685. rule = "dict ::= %s%s" % (
  686. "dict_comp " * token.attr,
  687. opname,
  688. )
  689. self.addRule(rule, nop_func)
  690. rule = """
  691. expr ::= dict_unpack
  692. dict_unpack ::= %s%s
  693. """ % (
  694. "expr " * token.attr,
  695. opname,
  696. )
  697. else:
  698. rule = "%s ::= %s %s" % (
  699. kvlist_n,
  700. "expr " * (token.attr * 2),
  701. opname,
  702. )
  703. self.add_unique_rule(rule, opname, token.attr, customize)
  704. rule = "dict ::= %s" % kvlist_n
  705. else:
  706. rule = kvlist_n + " ::= " + "expr expr STORE_MAP " * token.attr
  707. self.add_unique_rule(rule, opname, token.attr, customize)
  708. rule = "dict ::= %s %s" % (opname, kvlist_n)
  709. self.add_unique_rule(rule, opname, token.attr, customize)
  710. elif opname.startswith("BUILD_MAP_UNPACK_WITH_CALL"):
  711. v = token.attr
  712. rule = "build_map_unpack_with_call ::= %s%s" % ("expr " * v, opname)
  713. self.addRule(rule, nop_func)
  714. elif opname.startswith("BUILD_TUPLE_UNPACK_WITH_CALL"):
  715. v = token.attr
  716. rule = "starred ::= %s %s" % ("expr " * v, opname)
  717. self.addRule(rule, nop_func)
  718. elif opname in ("BUILD_CONST_LIST", "BUILD_CONST_DICT", "BUILD_CONST_SET"):
  719. if opname == "BUILD_CONST_DICT":
  720. rule = (
  721. """
  722. add_consts ::= ADD_VALUE*
  723. const_list ::= COLLECTION_START add_consts %s
  724. dict ::= const_list
  725. expr ::= dict
  726. """
  727. % opname
  728. )
  729. else:
  730. rule = (
  731. """
  732. add_consts ::= ADD_VALUE*
  733. const_list ::= COLLECTION_START add_consts %s
  734. expr ::= const_list
  735. """
  736. % opname
  737. )
  738. self.addRule(rule, nop_func)
  739. elif opname_base in (
  740. "BUILD_LIST",
  741. "BUILD_SET",
  742. "BUILD_TUPLE",
  743. "BUILD_TUPLE_UNPACK",
  744. ):
  745. v = token.attr
  746. is_LOAD_CLOSURE = False
  747. if opname_base == "BUILD_TUPLE":
  748. # If is part of a "load_closure", then it is not part of a
  749. # "list".
  750. is_LOAD_CLOSURE = True
  751. for j in range(v):
  752. if tokens[i - j - 1].kind != "LOAD_CLOSURE":
  753. is_LOAD_CLOSURE = False
  754. break
  755. if is_LOAD_CLOSURE:
  756. rule = "load_closure ::= %s%s" % (("LOAD_CLOSURE " * v), opname)
  757. self.add_unique_rule(rule, opname, token.attr, customize)
  758. if not is_LOAD_CLOSURE or v == 0:
  759. # We do this complicated test to speed up parsing of
  760. # pathelogically long literals, especially those over 1024.
  761. build_count = token.attr
  762. thousands = build_count // 1024
  763. thirty32s = (build_count // 32) % 32
  764. if thirty32s > 0 or thousands > 0:
  765. rule = "expr32 ::=%s" % (" expr" * 32)
  766. self.add_unique_rule(rule, opname_base, build_count, customize)
  767. pass
  768. if thousands > 0:
  769. self.add_unique_rule(
  770. "expr1024 ::=%s" % (" expr32" * 32),
  771. opname_base,
  772. build_count,
  773. customize,
  774. )
  775. pass
  776. collection = opname_base[opname_base.find("_") + 1 :].lower()
  777. rule = (
  778. ("%s ::= " % collection)
  779. + "expr1024 " * thousands
  780. + "expr32 " * thirty32s
  781. + "expr " * (build_count % 32)
  782. + opname
  783. )
  784. self.add_unique_rules(["expr ::= %s" % collection, rule], customize)
  785. continue
  786. continue
  787. elif opname_base == "BUILD_SLICE":
  788. if token.attr == 2:
  789. self.add_unique_rules(
  790. [
  791. "expr ::= build_slice2",
  792. "build_slice2 ::= expr expr BUILD_SLICE_2",
  793. ],
  794. customize,
  795. )
  796. else:
  797. assert token.attr == 3, (
  798. "BUILD_SLICE value must be 2 or 3; is %s" % v
  799. )
  800. self.add_unique_rules(
  801. [
  802. "expr ::= build_slice3",
  803. "build_slice3 ::= expr expr expr BUILD_SLICE_3",
  804. ],
  805. customize,
  806. )
  807. elif opname in frozenset(
  808. (
  809. "CALL_FUNCTION",
  810. "CALL_FUNCTION_EX",
  811. "CALL_FUNCTION_EX_KW",
  812. "CALL_FUNCTION_VAR",
  813. "CALL_FUNCTION_VAR_KW",
  814. )
  815. ) or opname.startswith("CALL_FUNCTION_KW"):
  816. if opname == "CALL_FUNCTION" and token.attr == 1:
  817. rule = """
  818. dict_comp ::= LOAD_DICTCOMP LOAD_STR MAKE_FUNCTION_0 expr
  819. GET_ITER CALL_FUNCTION_1
  820. classdefdeco1 ::= expr classdefdeco2 CALL_FUNCTION_1
  821. classdefdeco1 ::= expr classdefdeco1 CALL_FUNCTION_1
  822. """
  823. self.addRule(rule, nop_func)
  824. self.custom_classfunc_rule(
  825. opname, token, customize, tokens[i + 1], self.is_pypy
  826. )
  827. # Note: don't add to custom_ops_processed.
  828. elif opname_base == "CALL_METHOD":
  829. # PyPy and Python 3.7+ only - DRY with parse2
  830. pos_args_count, kw_args_count = self.get_pos_kw(token)
  831. # number of apply equiv arguments:
  832. nak = (len(opname_base) - len("CALL_METHOD")) // 3
  833. rule = (
  834. "call ::= expr "
  835. + ("pos_arg " * pos_args_count)
  836. + ("kwarg " * kw_args_count)
  837. + "expr " * nak
  838. + opname
  839. )
  840. self.add_unique_rule(rule, opname, token.attr, customize)
  841. elif opname == "CONTINUE":
  842. self.addRule("continue ::= CONTINUE", nop_func)
  843. custom_ops_processed.add(opname)
  844. elif opname == "CONTINUE_LOOP":
  845. self.addRule("continue ::= CONTINUE_LOOP", nop_func)
  846. custom_ops_processed.add(opname)
  847. elif opname == "DELETE_ATTR":
  848. self.addRule("delete ::= expr DELETE_ATTR", nop_func)
  849. custom_ops_processed.add(opname)
  850. elif opname == "DELETE_DEREF":
  851. self.addRule(
  852. """
  853. stmt ::= del_deref_stmt
  854. del_deref_stmt ::= DELETE_DEREF
  855. """,
  856. nop_func,
  857. )
  858. custom_ops_processed.add(opname)
  859. elif opname == "DELETE_SUBSCR":
  860. self.addRule(
  861. """
  862. delete ::= delete_subscript
  863. delete_subscript ::= expr expr DELETE_SUBSCR
  864. """,
  865. nop_func,
  866. )
  867. custom_ops_processed.add(opname)
  868. elif opname == "GET_ITER":
  869. self.addRule(
  870. """
  871. expr ::= get_iter
  872. get_iter ::= expr GET_ITER
  873. """,
  874. nop_func,
  875. )
  876. custom_ops_processed.add(opname)
  877. elif opname == "JUMP_IF_NOT_DEBUG":
  878. v = token.attr
  879. self.addRule(
  880. """
  881. stmt ::= assert_pypy
  882. stmt ::= assert_not_pypy
  883. stmt ::= assert2_pypy
  884. stmt ::= assert2_not_pypy
  885. assert_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_true
  886. LOAD_ASSERT RAISE_VARARGS_1 COME_FROM
  887. assert_not_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_false
  888. LOAD_ASSERT RAISE_VARARGS_1 COME_FROM
  889. assert2_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_true
  890. LOAD_ASSERT expr CALL_FUNCTION_1
  891. RAISE_VARARGS_1 COME_FROM
  892. assert2_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_true
  893. LOAD_ASSERT expr CALL_FUNCTION_1
  894. RAISE_VARARGS_1 COME_FROM
  895. assert2_not_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_false
  896. LOAD_ASSERT expr CALL_FUNCTION_1
  897. RAISE_VARARGS_1 COME_FROM
  898. """,
  899. nop_func,
  900. )
  901. custom_ops_processed.add(opname)
  902. elif opname == "LOAD_BUILD_CLASS":
  903. self.custom_build_class_rule(
  904. opname, i, token, tokens, customize, self.is_pypy
  905. )
  906. # Note: don't add to custom_ops_processed.
  907. elif opname == "LOAD_CLASSDEREF":
  908. # Python 3.4+
  909. self.addRule("expr ::= LOAD_CLASSDEREF", nop_func)
  910. custom_ops_processed.add(opname)
  911. elif opname == "LOAD_CLASSNAME":
  912. self.addRule("expr ::= LOAD_CLASSNAME", nop_func)
  913. custom_ops_processed.add(opname)
  914. elif opname == "LOAD_DICTCOMP":
  915. if has_get_iter_call_function1:
  916. rule_pat = (
  917. "dict_comp ::= LOAD_DICTCOMP %sMAKE_FUNCTION_0 expr "
  918. "GET_ITER CALL_FUNCTION_1"
  919. )
  920. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  921. pass
  922. custom_ops_processed.add(opname)
  923. elif opname == "LOAD_ATTR":
  924. self.addRule(
  925. """
  926. expr ::= attribute
  927. attribute ::= expr LOAD_ATTR
  928. """,
  929. nop_func,
  930. )
  931. custom_ops_processed.add(opname)
  932. elif opname == "LOAD_LISTCOMP":
  933. self.add_unique_rule(
  934. "expr ::= list_comp", opname, token.attr, customize
  935. )
  936. custom_ops_processed.add(opname)
  937. elif opname == "LOAD_SETCOMP":
  938. # Should this be generalized and put under MAKE_FUNCTION?
  939. if has_get_iter_call_function1:
  940. self.addRule("expr ::= set_comp", nop_func)
  941. rule_pat = (
  942. "set_comp ::= LOAD_SETCOMP %sMAKE_FUNCTION_0 expr "
  943. "GET_ITER CALL_FUNCTION_1"
  944. )
  945. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  946. pass
  947. custom_ops_processed.add(opname)
  948. elif opname == "LOOKUP_METHOD":
  949. # A PyPy speciality - DRY with parse3
  950. self.addRule(
  951. """
  952. attribute ::= expr LOOKUP_METHOD
  953. """,
  954. nop_func,
  955. )
  956. custom_ops_processed.add(opname)
  957. elif opname.startswith("MAKE_CLOSURE"):
  958. # DRY with MAKE_FUNCTION
  959. # Note: this probably doesn't handle kwargs proprerly
  960. if opname == "MAKE_CLOSURE_0" and "LOAD_DICTCOMP" in self.seen_ops:
  961. # Is there something general going on here?
  962. # Note that 3.6+ doesn't do this, but we'll remove
  963. # this rule in parse36.py
  964. rule = """
  965. dict_comp ::= load_closure LOAD_DICTCOMP LOAD_STR
  966. MAKE_CLOSURE_0 expr
  967. GET_ITER CALL_FUNCTION_1
  968. """
  969. self.addRule(rule, nop_func)
  970. pos_args_count, kw_args_count, annotate_args = token.attr
  971. # FIXME: Fold test into add_make_function_rule
  972. if self.version < (3, 3):
  973. j = 1
  974. else:
  975. j = 2
  976. if self.is_pypy or (i >= j and tokens[i - j] == "LOAD_LAMBDA"):
  977. rule_pat = "lambda_body ::= %sload_closure LOAD_LAMBDA %%s%s" % (
  978. "pos_arg " * pos_args_count,
  979. opname,
  980. )
  981. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  982. if has_get_iter_call_function1:
  983. rule_pat = (
  984. "generator_exp ::= %sload_closure load_genexpr %%s%s expr "
  985. "GET_ITER CALL_FUNCTION_1"
  986. % ("pos_arg " * pos_args_count, opname)
  987. )
  988. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  989. if has_get_iter_call_function1:
  990. if self.is_pypy or (
  991. i >= j and tokens[i - j] == "LOAD_LISTCOMP"
  992. ):
  993. # In the tokens we saw:
  994. # LOAD_LISTCOMP LOAD_CONST MAKE_FUNCTION (>= 3.3) or
  995. # LOAD_LISTCOMP MAKE_FUNCTION (< 3.3) or
  996. # and have GET_ITER CALL_FUNCTION_1
  997. # Todo: For Pypy we need to modify this slightly
  998. rule_pat = (
  999. "list_comp ::= %sload_closure LOAD_LISTCOMP %%s%s expr "
  1000. "GET_ITER CALL_FUNCTION_1"
  1001. % ("pos_arg " * pos_args_count, opname)
  1002. )
  1003. self.add_make_function_rule(
  1004. rule_pat, opname, token.attr, customize
  1005. )
  1006. if self.is_pypy or (i >= j and tokens[i - j] == "LOAD_SETCOMP"):
  1007. rule_pat = (
  1008. "set_comp ::= %sload_closure LOAD_SETCOMP %%s%s expr "
  1009. "GET_ITER CALL_FUNCTION_1"
  1010. % ("pos_arg " * pos_args_count, opname)
  1011. )
  1012. self.add_make_function_rule(
  1013. rule_pat, opname, token.attr, customize
  1014. )
  1015. if self.is_pypy or (
  1016. i >= j and tokens[i - j] == "LOAD_DICTCOMP"
  1017. ):
  1018. self.add_unique_rule(
  1019. "dict_comp ::= %sload_closure LOAD_DICTCOMP %s "
  1020. "expr GET_ITER CALL_FUNCTION_1"
  1021. % ("pos_arg " * pos_args_count, opname),
  1022. opname,
  1023. token.attr,
  1024. customize,
  1025. )
  1026. if kw_args_count > 0:
  1027. kwargs_str = "kwargs "
  1028. else:
  1029. kwargs_str = ""
  1030. # Note order of kwargs and pos args changed between 3.3-3.4
  1031. if self.version <= (3, 2):
  1032. if annotate_args > 0:
  1033. rule = (
  1034. "mkfunc_annotate ::= %s%s%sannotate_tuple load_closure LOAD_CODE %s"
  1035. % (
  1036. kwargs_str,
  1037. "pos_arg " * pos_args_count,
  1038. "annotate_arg " * (annotate_args),
  1039. opname,
  1040. )
  1041. )
  1042. else:
  1043. rule = "mkfunc ::= %s%sload_closure LOAD_CODE %s" % (
  1044. kwargs_str,
  1045. "pos_arg " * pos_args_count,
  1046. opname,
  1047. )
  1048. self.add_unique_rule(rule, opname, token.attr, customize)
  1049. elif (3, 3) <= self.version < (3, 6):
  1050. # FIXME move this into version-specific custom rules.
  1051. # In fact, some of this has been done for 3.3.
  1052. if annotate_args > 0:
  1053. rule = (
  1054. "mkfunc_annotate ::= %s%s%sannotate_tuple load_closure LOAD_CODE LOAD_STR %s"
  1055. % (
  1056. kwargs_str,
  1057. "pos_arg " * pos_args_count,
  1058. "annotate_arg " * (annotate_args),
  1059. opname,
  1060. )
  1061. )
  1062. else:
  1063. if self.version == (3, 3):
  1064. # 3.3 puts kwargs before pos_arg
  1065. pos_kw_tuple = (
  1066. ("kwargs " * kw_args_count),
  1067. ("pos_arg " * pos_args_count),
  1068. )
  1069. else:
  1070. # 3.4 and 3.5 puts pos_arg before kwargs
  1071. pos_kw_tuple = (
  1072. "pos_arg " * (pos_args_count),
  1073. ("kwargs " * kw_args_count),
  1074. )
  1075. rule = (
  1076. "mkfunc ::= %s%s%s " "load_closure LOAD_CODE LOAD_STR %s"
  1077. ) % (
  1078. pos_kw_tuple[0],
  1079. pos_kw_tuple[1],
  1080. "annotate_pair " * (annotate_args),
  1081. opname,
  1082. )
  1083. self.add_unique_rule(rule, opname, token.attr, customize)
  1084. if self.version >= (3, 4):
  1085. if not self.is_pypy:
  1086. load_op = "LOAD_STR"
  1087. else:
  1088. load_op = "LOAD_CONST"
  1089. if annotate_args > 0:
  1090. rule = (
  1091. "mkfunc_annotate ::= %s%s%sannotate_tuple load_closure %s %s"
  1092. % (
  1093. "pos_arg " * pos_args_count,
  1094. kwargs_str,
  1095. "annotate_arg " * (annotate_args),
  1096. load_op,
  1097. opname,
  1098. )
  1099. )
  1100. else:
  1101. rule = "mkfunc ::= %s%s load_closure LOAD_CODE %s %s" % (
  1102. "pos_arg " * pos_args_count,
  1103. kwargs_str,
  1104. load_op,
  1105. opname,
  1106. )
  1107. self.add_unique_rule(rule, opname, token.attr, customize)
  1108. if kw_args_count == 0:
  1109. rule = "mkfunc ::= %sload_closure load_genexpr %s" % (
  1110. "pos_arg " * pos_args_count,
  1111. opname,
  1112. )
  1113. self.add_unique_rule(rule, opname, token.attr, customize)
  1114. if self.version < (3, 4):
  1115. rule = "mkfunc ::= %sload_closure LOAD_CODE %s" % (
  1116. "expr " * pos_args_count,
  1117. opname,
  1118. )
  1119. self.add_unique_rule(rule, opname, token.attr, customize)
  1120. pass
  1121. elif opname_base.startswith("MAKE_FUNCTION"):
  1122. # DRY with MAKE_CLOSURE
  1123. if self.version >= (3, 6):
  1124. # The semantics of MAKE_FUNCTION in 3.6 are totally different from
  1125. # before.
  1126. pos_args_count, kw_args_count, annotate_args, closure = token.attr
  1127. stack_count = pos_args_count + kw_args_count + annotate_args
  1128. if closure:
  1129. if pos_args_count:
  1130. rule = "lambda_body ::= %s%s%s%s" % (
  1131. "expr " * stack_count,
  1132. "load_closure " * closure,
  1133. "BUILD_TUPLE_1 LOAD_LAMBDA LOAD_STR ",
  1134. opname,
  1135. )
  1136. else:
  1137. rule = "lambda_body ::= %s%s%s" % (
  1138. "load_closure " * closure,
  1139. "LOAD_LAMBDA LOAD_STR ",
  1140. opname,
  1141. )
  1142. self.add_unique_rule(rule, opname, token.attr, customize)
  1143. else:
  1144. rule = "lambda_body ::= %sLOAD_LAMBDA LOAD_STR %s" % (
  1145. ("expr " * stack_count),
  1146. opname,
  1147. )
  1148. self.add_unique_rule(rule, opname, token.attr, customize)
  1149. rule = "mkfunc ::= %s%s%s%s" % (
  1150. "expr " * stack_count,
  1151. "load_closure " * closure,
  1152. "LOAD_CODE LOAD_STR ",
  1153. opname,
  1154. )
  1155. self.add_unique_rule(rule, opname, token.attr, customize)
  1156. if has_get_iter_call_function1:
  1157. rule_pat = (
  1158. "generator_exp ::= %sload_genexpr %%s%s expr "
  1159. "GET_ITER CALL_FUNCTION_1"
  1160. % ("pos_arg " * pos_args_count, opname)
  1161. )
  1162. self.add_make_function_rule(
  1163. rule_pat, opname, token.attr, customize
  1164. )
  1165. rule_pat = (
  1166. "generator_exp ::= %sload_closure load_genexpr %%s%s expr "
  1167. "GET_ITER CALL_FUNCTION_1"
  1168. % ("pos_arg " * pos_args_count, opname)
  1169. )
  1170. self.add_make_function_rule(
  1171. rule_pat, opname, token.attr, customize
  1172. )
  1173. if self.is_pypy or (
  1174. i >= 2 and tokens[i - 2] == "LOAD_LISTCOMP"
  1175. ):
  1176. if self.version >= (3, 6):
  1177. # 3.6+ sometimes bundles all of the
  1178. # 'exprs' in the rule above into a
  1179. # tuple.
  1180. rule_pat = (
  1181. "list_comp ::= load_closure LOAD_LISTCOMP %%s%s "
  1182. "expr GET_ITER CALL_FUNCTION_1" % (opname,)
  1183. )
  1184. self.add_make_function_rule(
  1185. rule_pat, opname, token.attr, customize
  1186. )
  1187. rule_pat = (
  1188. "list_comp ::= %sLOAD_LISTCOMP %%s%s expr "
  1189. "GET_ITER CALL_FUNCTION_1"
  1190. % ("expr " * pos_args_count, opname)
  1191. )
  1192. self.add_make_function_rule(
  1193. rule_pat, opname, token.attr, customize
  1194. )
  1195. if self.is_pypy or (i >= 2 and tokens[i - 2] == "LOAD_LAMBDA"):
  1196. rule_pat = "lambda_body ::= %s%sLOAD_LAMBDA %%s%s" % (
  1197. ("pos_arg " * pos_args_count),
  1198. ("kwarg " * kw_args_count),
  1199. opname,
  1200. )
  1201. self.add_make_function_rule(
  1202. rule_pat, opname, token.attr, customize
  1203. )
  1204. continue
  1205. if self.version < (3, 6):
  1206. pos_args_count, kw_args_count, annotate_args = token.attr
  1207. else:
  1208. pos_args_count, kw_args_count, annotate_args, closure = token.attr
  1209. if self.version < (3, 3):
  1210. j = 1
  1211. else:
  1212. j = 2
  1213. if has_get_iter_call_function1:
  1214. rule_pat = (
  1215. "generator_exp ::= %sload_genexpr %%s%s expr "
  1216. "GET_ITER CALL_FUNCTION_1"
  1217. % ("pos_arg " * pos_args_count, opname)
  1218. )
  1219. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  1220. if self.is_pypy or (i >= j and tokens[i - j] == "LOAD_LISTCOMP"):
  1221. # In the tokens we saw:
  1222. # LOAD_LISTCOMP LOAD_CONST MAKE_FUNCTION (>= 3.3) or
  1223. # LOAD_LISTCOMP MAKE_FUNCTION (< 3.3) or
  1224. # and have GET_ITER CALL_FUNCTION_1
  1225. # Todo: For Pypy we need to modify this slightly
  1226. rule_pat = (
  1227. "list_comp ::= %sLOAD_LISTCOMP %%s%s expr "
  1228. "GET_ITER CALL_FUNCTION_1"
  1229. % ("expr " * pos_args_count, opname)
  1230. )
  1231. self.add_make_function_rule(
  1232. rule_pat, opname, token.attr, customize
  1233. )
  1234. # FIXME: Fold test into add_make_function_rule
  1235. if self.is_pypy or (i >= j and tokens[i - j] == "LOAD_LAMBDA"):
  1236. rule_pat = "lambda_body ::= %s%sLOAD_LAMBDA %%s%s" % (
  1237. ("pos_arg " * pos_args_count),
  1238. ("kwarg " * kw_args_count),
  1239. opname,
  1240. )
  1241. self.add_make_function_rule(rule_pat, opname, token.attr, customize)
  1242. if kw_args_count == 0:
  1243. kwargs = "no_kwargs"
  1244. self.add_unique_rule("no_kwargs ::=", opname, token.attr, customize)
  1245. else:
  1246. kwargs = "kwargs"
  1247. if self.version < (3, 3):
  1248. # positional args after keyword args
  1249. rule = "mkfunc ::= %s %s%s%s" % (
  1250. kwargs,
  1251. "pos_arg " * pos_args_count,
  1252. "LOAD_CODE ",
  1253. opname,
  1254. )
  1255. self.add_unique_rule(rule, opname, token.attr, customize)
  1256. rule = "mkfunc ::= %s%s%s" % (
  1257. "pos_arg " * pos_args_count,
  1258. "LOAD_CODE ",
  1259. opname,
  1260. )
  1261. elif self.version == (3, 3):
  1262. # positional args after keyword args
  1263. rule = "mkfunc ::= %s %s%s%s" % (
  1264. kwargs,
  1265. "pos_arg " * pos_args_count,
  1266. "LOAD_CODE LOAD_STR ",
  1267. opname,
  1268. )
  1269. elif self.version >= (3, 6):
  1270. # positional args before keyword args
  1271. rule = "mkfunc ::= %s%s %s%s" % (
  1272. "pos_arg " * pos_args_count,
  1273. kwargs,
  1274. "LOAD_CODE LOAD_STR ",
  1275. opname,
  1276. )
  1277. elif self.version >= (3, 4):
  1278. # positional args before keyword args
  1279. rule = "mkfunc ::= %s%s %s%s" % (
  1280. "pos_arg " * pos_args_count,
  1281. kwargs,
  1282. "LOAD_CODE LOAD_STR ",
  1283. opname,
  1284. )
  1285. else:
  1286. rule = "mkfunc ::= %s%sexpr %s" % (
  1287. kwargs,
  1288. "pos_arg " * pos_args_count,
  1289. opname,
  1290. )
  1291. self.add_unique_rule(rule, opname, token.attr, customize)
  1292. if re.search("^MAKE_FUNCTION.*_A", opname):
  1293. if self.version >= (3, 6):
  1294. rule = (
  1295. "mkfunc_annotate ::= %s%sannotate_tuple LOAD_CODE LOAD_STR %s"
  1296. % (
  1297. ("pos_arg " * pos_args_count),
  1298. ("call " * annotate_args),
  1299. opname,
  1300. )
  1301. )
  1302. self.add_unique_rule(rule, opname, token.attr, customize)
  1303. rule = (
  1304. "mkfunc_annotate ::= %s%sannotate_tuple LOAD_CODE "
  1305. "LOAD_STR %s"
  1306. ) % (
  1307. ("pos_arg " * pos_args_count),
  1308. ("annotate_arg " * annotate_args),
  1309. opname,
  1310. )
  1311. if self.version >= (3, 3):
  1312. if self.version == (3, 3):
  1313. # 3.3 puts kwargs before pos_arg
  1314. pos_kw_tuple = (
  1315. ("kwargs " * kw_args_count),
  1316. ("pos_arg " * pos_args_count),
  1317. )
  1318. else:
  1319. # 3.4 and 3.5 puts pos_arg before kwargs
  1320. pos_kw_tuple = (
  1321. "pos_arg " * (pos_args_count),
  1322. ("kwargs " * kw_args_count),
  1323. )
  1324. rule = (
  1325. "mkfunc_annotate ::= %s%s%sannotate_tuple LOAD_CODE "
  1326. "LOAD_STR %s"
  1327. ) % (
  1328. pos_kw_tuple[0],
  1329. pos_kw_tuple[1],
  1330. ("annotate_arg " * annotate_args),
  1331. opname,
  1332. )
  1333. else:
  1334. rule = (
  1335. "mkfunc_annotate ::= %s%s%sannotate_tuple LOAD_CODE %s"
  1336. % (
  1337. ("kwargs " * kw_args_count),
  1338. ("pos_arg " * (pos_args_count)),
  1339. ("annotate_arg " * annotate_args),
  1340. opname,
  1341. )
  1342. )
  1343. self.add_unique_rule(rule, opname, token.attr, customize)
  1344. rule = (
  1345. "mkfunc_annotate ::= %s%s%sannotate_tuple LOAD_CODE %s"
  1346. % (
  1347. ("kwargs " * kw_args_count),
  1348. ("pos_arg " * pos_args_count),
  1349. ("call " * annotate_args),
  1350. opname,
  1351. )
  1352. )
  1353. self.addRule(rule, nop_func)
  1354. elif opname == "RETURN_VALUE_LAMBDA":
  1355. self.addRule(
  1356. """
  1357. return_expr_lambda ::= return_expr RETURN_VALUE_LAMBDA
  1358. """,
  1359. nop_func,
  1360. )
  1361. custom_ops_processed.add(opname)
  1362. elif opname == "RAISE_VARARGS_0":
  1363. self.addRule(
  1364. """
  1365. stmt ::= raise_stmt0
  1366. raise_stmt0 ::= RAISE_VARARGS_0
  1367. """,
  1368. nop_func,
  1369. )
  1370. custom_ops_processed.add(opname)
  1371. elif opname == "RAISE_VARARGS_1":
  1372. self.addRule(
  1373. """
  1374. stmt ::= raise_stmt1
  1375. raise_stmt1 ::= expr RAISE_VARARGS_1
  1376. """,
  1377. nop_func,
  1378. )
  1379. custom_ops_processed.add(opname)
  1380. elif opname == "RAISE_VARARGS_2":
  1381. self.addRule(
  1382. """
  1383. stmt ::= raise_stmt2
  1384. raise_stmt2 ::= expr expr RAISE_VARARGS_2
  1385. """,
  1386. nop_func,
  1387. )
  1388. custom_ops_processed.add(opname)
  1389. elif opname == "SETUP_EXCEPT":
  1390. self.addRule(
  1391. """
  1392. try_except ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
  1393. except_handler opt_come_from_except
  1394. try_except ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
  1395. except_handler opt_come_from_except
  1396. tryelsestmtl ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
  1397. except_handler else_suitel come_from_except_clauses
  1398. stmt ::= tryelsestmtl3
  1399. tryelsestmtl3 ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
  1400. except_handler_else COME_FROM else_suitel
  1401. opt_come_from_except
  1402. tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
  1403. except_handler_else else_suite come_froms
  1404. """,
  1405. nop_func,
  1406. )
  1407. custom_ops_processed.add(opname)
  1408. elif opname_base in ("UNPACK_EX",):
  1409. before_count, after_count = token.attr
  1410. rule = (
  1411. "unpack ::= " + opname + " store" * (before_count + after_count + 1)
  1412. )
  1413. self.addRule(rule, nop_func)
  1414. elif opname_base in ("UNPACK_TUPLE", "UNPACK_SEQUENCE"):
  1415. rule = "unpack ::= " + opname + " store" * token.attr
  1416. self.addRule(rule, nop_func)
  1417. elif opname_base == "UNPACK_LIST":
  1418. rule = "unpack_list ::= " + opname + " store" * token.attr
  1419. self.addRule(rule, nop_func)
  1420. custom_ops_processed.add(opname)
  1421. pass
  1422. pass
  1423. # FIXME: Put more in this table
  1424. self.reduce_check_table = {
  1425. "except_handler_else": except_handler_else,
  1426. # "ifstmt": ifstmt,
  1427. "ifstmtl": ifstmt,
  1428. "ifelsestmtc": ifelsestmt,
  1429. "ifelsestmt": ifelsestmt,
  1430. "or": or_check,
  1431. "testtrue": testtrue,
  1432. "tryelsestmtl3": tryelsestmtl3,
  1433. "try_except": tryexcept,
  1434. }
  1435. if self.version == (3, 6):
  1436. self.reduce_check_table["and"] = and_invalid
  1437. self.check_reduce["and"] = "AST"
  1438. self.check_reduce["annotate_tuple"] = "noAST"
  1439. self.check_reduce["aug_assign1"] = "AST"
  1440. self.check_reduce["aug_assign2"] = "AST"
  1441. self.check_reduce["except_handler_else"] = "tokens"
  1442. self.check_reduce["ifelsestmt"] = "AST"
  1443. self.check_reduce["ifelsestmtc"] = "AST"
  1444. self.check_reduce["ifstmt"] = "AST"
  1445. self.check_reduce["ifstmtl"] = "AST"
  1446. if self.version == (3, 6):
  1447. self.reduce_check_table["iflaststmtl"] = iflaststmt
  1448. self.check_reduce["iflaststmt"] = "AST"
  1449. self.check_reduce["iflaststmtl"] = "AST"
  1450. self.check_reduce["or"] = "AST"
  1451. self.check_reduce["testtrue"] = "tokens"
  1452. if self.version < (3, 6) and not self.is_pypy:
  1453. # 3.6+ can remove a JUMP_FORWARD which messes up our testing here
  1454. # Pypy we need to go over in better detail
  1455. self.check_reduce["try_except"] = "AST"
  1456. self.check_reduce["tryelsestmtl3"] = "AST"
  1457. self.check_reduce["while1stmt"] = "noAST"
  1458. self.check_reduce["while1elsestmt"] = "noAST"
  1459. return
  1460. def reduce_is_invalid(self, rule, ast, tokens, first, last):
  1461. lhs = rule[0]
  1462. n = len(tokens)
  1463. last = min(last, n - 1)
  1464. fn = self.reduce_check_table.get(lhs, None)
  1465. if fn:
  1466. if fn(self, lhs, n, rule, ast, tokens, first, last):
  1467. return True
  1468. pass
  1469. # FIXME: put more in reduce_check_table
  1470. if lhs in ("aug_assign1", "aug_assign2") and ast[0][0] == "and":
  1471. return True
  1472. elif lhs == "annotate_tuple":
  1473. return not isinstance(tokens[first].attr, tuple)
  1474. elif lhs == "kwarg":
  1475. arg = tokens[first].attr
  1476. return not (isinstance(arg, str) or isinstance(arg, unicode))
  1477. elif rule == ("ifstmt", ("testexpr", "_ifstmts_jump")):
  1478. # FIXME: go over what's up with 3.0. Evetually I'd like to remove RETURN_END_IF
  1479. if self.version <= (3, 0) or tokens[last] == "RETURN_END_IF":
  1480. return False
  1481. if ifstmt(self, lhs, n, rule, ast, tokens, first, last):
  1482. return True
  1483. # FIXME: do we need the below or is it covered by "ifstmt" above?
  1484. condition_jump = ast[0].last_child()
  1485. if condition_jump.kind.startswith("POP_JUMP_IF"):
  1486. condition_jump2 = tokens[min(last - 1, len(tokens) - 1)]
  1487. # If there are two *distinct* condition jumps, they should not jump to the
  1488. # same place. Otherwise we have some sort of "and"/"or".
  1489. if (
  1490. condition_jump2.kind.startswith("POP_JUMP_IF")
  1491. and condition_jump != condition_jump2
  1492. ):
  1493. return condition_jump.attr == condition_jump2.attr
  1494. if (
  1495. tokens[last] == "COME_FROM"
  1496. and tokens[last].off2int() != condition_jump.attr
  1497. ):
  1498. return False
  1499. # if condition_jump.attr < condition_jump2.off2int():
  1500. # print("XXX", first, last)
  1501. # for t in range(first, last): print(tokens[t])
  1502. # from trepan.api import debug; debug()
  1503. return condition_jump.attr < condition_jump2.off2int()
  1504. return False
  1505. elif rule == ("ifstmt", ("testexpr", "\\e__ifstmts_jump")):
  1506. # I am not sure what to check.
  1507. # Probably needs fixing elsewhere
  1508. return True
  1509. elif lhs == "ifelsestmt" and rule[1][2] == "jump_forward_else":
  1510. last = min(last, len(tokens) - 1)
  1511. if tokens[last].off2int() == -1:
  1512. last -= 1
  1513. jump_forward_else = ast[2]
  1514. return (
  1515. tokens[first].off2int()
  1516. <= jump_forward_else[0].attr
  1517. < tokens[last].off2int()
  1518. )
  1519. elif lhs == "while1stmt":
  1520. if while1stmt(self, lhs, n, rule, ast, tokens, first, last):
  1521. return True
  1522. if self.version == (3, 0):
  1523. return False
  1524. if 0 <= last < len(tokens) and tokens[last] in (
  1525. "COME_FROM_LOOP",
  1526. "JUMP_BACK",
  1527. ):
  1528. # jump_back should be right before COME_FROM_LOOP?
  1529. last += 1
  1530. while last < len(tokens) and isinstance(tokens[last].offset, str):
  1531. last += 1
  1532. if last < len(tokens):
  1533. offset = tokens[last].offset
  1534. assert tokens[first] == "SETUP_LOOP"
  1535. if offset != tokens[first].attr:
  1536. return True
  1537. return False
  1538. elif lhs == "while1elsestmt":
  1539. n = len(tokens)
  1540. if last == n:
  1541. # Adjust for fuzziness in parsing
  1542. last -= 1
  1543. if tokens[last] == "COME_FROM_LOOP":
  1544. last -= 1
  1545. elif tokens[last - 1] == "COME_FROM_LOOP":
  1546. last -= 2
  1547. if tokens[last] in ("JUMP_BACK", "CONTINUE"):
  1548. # These indicate inside a loop, but token[last]
  1549. # should not be in a loop.
  1550. # FIXME: Not quite right: refine by using target
  1551. return True
  1552. # if SETUP_LOOP target spans the else part, then this is
  1553. # not while1else. Also do for whileTrue?
  1554. last += 1
  1555. while last < n and isinstance(tokens[last].offset, str):
  1556. last += 1
  1557. if last == n:
  1558. return False
  1559. # 3.8+ Doesn't have SETUP_LOOP
  1560. return self.version < (3, 8) and tokens[first].attr > tokens[last].offset
  1561. elif rule == (
  1562. "ifelsestmt",
  1563. (
  1564. "testexpr",
  1565. "c_stmts_opt",
  1566. "jump_forward_else",
  1567. "else_suite",
  1568. "_come_froms",
  1569. ),
  1570. ):
  1571. # Make sure the highest/smallest "come from" offset comes inside the "if".
  1572. come_froms = ast[-1]
  1573. if not isinstance(come_froms, Token):
  1574. return tokens[first].offset > come_froms[-1].attr
  1575. return False
  1576. return False
  1577. class Python30Parser(Python3Parser):
  1578. def p_30(self, args):
  1579. """
  1580. jmp_true ::= JUMP_IF_TRUE_OR_POP POP_TOP
  1581. _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD POP_TOP COME_FROM
  1582. """
  1583. class Python3ParserSingle(Python3Parser, PythonParserSingle):
  1584. pass
  1585. def info(args):
  1586. # Check grammar
  1587. p = Python3Parser()
  1588. if len(args) > 0:
  1589. arg = args[0]
  1590. if arg == "3.5":
  1591. from uncompyle6.parser.parse35 import Python35Parser
  1592. p = Python35Parser()
  1593. elif arg == "3.3":
  1594. from uncompyle6.parser.parse33 import Python33Parser
  1595. p = Python33Parser()
  1596. elif arg == "3.2":
  1597. from uncompyle6.parser.parse32 import Python32Parser
  1598. p = Python32Parser()
  1599. elif arg == "3.0":
  1600. p = Python30Parser()
  1601. p.check_grammar()
  1602. if len(sys.argv) > 1 and sys.argv[1] == "dump":
  1603. print("-" * 50)
  1604. p.dump_grammar()
  1605. if __name__ == "__main__":
  1606. import sys
  1607. info(sys.argv)