Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Implementing "++" operator, stepping into parse.y

Implementing "++" operator, stepping into parse.y

More Decks by Misaki Shioi(塩井美咲/しおい)

Other Decks in Programming

Transcript

  1. )BWFZPVFWFSXJTIFE 3VCZIBEJODSFNFOUEFDSFNFOUPQFSBUPST  i = 0 while i < 100

    i++ puts "FizzBuzz" if i % 15 == 0 puts "Fizz" if i % 3 == 0 puts "Buzz" if i % 5 == 0 end 'PSFYBNQMF
  2. ʜJUDBVTFTBTZOUBYFSSPSBUQBSTJOH # test.rb i = 0 i++ SVCZUFTUSC J J

     UFTUSCTZOUBYFSSPS VOFYQFDUFEFOEPGJOQVU 4ZOUBY&SSPS
  3. SVCZZFJJ  BEE@EFMBZFE@UPLFO cc  4UBSUJOHQBSTF ʜ &OUFSJOHTUBUF 4UBDLOPX 3FEVDJOHTUBDLCZSVMF

    MJOF  OUFSNMIT /0%&@-"4(/  UPLFO   OUFSNMFY@DUYU   OUFSNBSH@SIT /0%&@-*5  OUFSNBSH /0%&@-"4(/  ʜ 5IFQBSTJOHMPHTIPXTXIZ "DDPSEJOHUPJU JUXPSLT fi OFVQUPAJA AJATFFNTUPCFQBSTFEKVTU fi OF
  4. SVCZZFJJ  ʜ &OUFSJOHTUBUF 4UBDLOPX /FYUUPLFOJTUPLFO   4IJGUJOHUPLFO 

     &OUFSJOHTUBUF 4UBDLOPX 3FEVDJOHTUBDLCZSVMF MJOF  UPLFO   OUFSNUFSN   &OUFSJOHTUBUF 4UBDLOPX 3FEVDJOHTUBDLCZSVMF MJOF  OUFSNUFSN   OUFSNUFSNT   5IFQBSTJOHMPHTIPXTXIZ 5IFOUIF fi STUFYQSFTTJPOJTQSPQFSMZFOEFEXJUIAA 5IJTFYQSFTTJPOJTTVDDFTTGVMMZFOEFE AABMTPTFFNTUPCFQBSTFEDPSSFDUMZ
  5. SVCZZFJJ  ʜ &OUFSJOHTUBUF 4UBDLOPX 3FBEJOHBUPLFO QBSTFS@EJTQBUDI@TDBO@FWFOU cc  MFY@TUBUF#&($.%"3(BUMJOF

    MFY@TUBUF$.%"3(&/%c-"#&-BUMJOF QBSTFS@EJTQBUDI@TDBO@FWFOU cc  /FYUUPLFOJTUPLFOMPDBMWBSJBCMFPSNFUIPE J  4IJGUJOHUPLFOMPDBMWBSJBCMFPSNFUIPE J  5IFQBSTJOHMPHTIPXTXIZ *OUIFMBUFSQBSU UIFWBSJBCMFAJAJT fi STUSFBE 5IFWBSJBCMFAJAJTSFBE
  6. SVCZZFJJ  ʜ &OUFSJOHTUBUF 4UBDLOPX /FYUUPLFOJTUPLFO    4IJGUJOHUPLFO

       &OUFSJOHTUBUF 4UBDLOPX 3FBEJOHBUPLFO MFY@TUBUF#&(#&(BUMJOF QBSTFS@EJTQBUDI@TDBO@FWFOU cc  /FYUUPLFOJTUPLFOVOBSZ    4IJGUJOHUPLFOVOBSZ    5IFQBSTJOHMPHTIPXTXIZ 5XPA ATBSFUIFOSFBE5IJT TFDPOEA AJT EFUFSNJOFEBTUIFA APGBVOBSZPQFSBUPS 'JSTUA A 4FDPOEA A *UTEFUFSNJOFEUIBUBVOBSZPQFSBUPS
  7. SVCZZFJJ  ʜ &OUFSJOHTUBUF 4UBDLOPX 3FBEJOHBUPLFO QBSTFS@EJTQBUDI@TDBO@FWFOU cc  /PXBUFOEPGJOQVU

    FTZOUBYFSSPS VOFYQFDUFEFOEPGJOQVU JJ 5IFQBSTJOHMPHTIPXTXIZ .3*FYQFDUTTPNFOVNFSJDUPCFSFBEBGUFS BVOBSZPQFSBUPSJOUIJTDPOUFYU )PXFWFS JOSFBMJUZ UIFMJOFFOETBCSVQUMZIFSF 5IJTJTBOVOFYQFDUFEFOEPGJOQVU "TZOUBYFSSPSIBTPDDVSSFE 5IFMJOFFOEFEVOFYQFDUFEMZ
  8. .3*SFBETUIFTFUPLFOTPOFCZPOF GSPNMFGUUPSJHIU  VTJOHBGVODUJPODBMMFETDBOOFS )PXTDBOOFSXPSLT SFBETUIFUPLFOJT puts "Hello" QVUT 4DBOOFS

    /PUF4DBOOFSJTBMTPDBMMFEMFYJDBMBOBMZ[FSPSMFYFS  CVUKVTUDBMMJUTDBOOFSJOUIJTTMJEF
  9. 5IFTDBOOFSTFUTUIFWBMVFPGUIFUPLFOUPBTZNCPM 5IJTWBMVFDBOCFBOJE BO3/PEF PSTPNFUIJOHFMTF )PXTDBOOFSXPSLT TFUTU*%&/5*'*&3UPBNFUIPEJE QVUT puts "Hello" U*%&/5*'*&3

    QVUT 4ZNCPM 5PLFO /PUF4PNFUPLFOTIBWFOPWBMVF  /PUF7BMVFJTDBMMFETFNBOUJDWBMVF CVUKVTUDBMMJUWBMVFJOUIJTTMJEF 4DBOOFS
  10. )PXQBSTFSXPSLT 5IFTZOUBYSVMFTMPPLMJLFUIJT )FSFUIFSJHIUBOEMFGUIBOETJEFTBSFEF fi OFE // An example of a

    grammar rule operation : tIDENTIFIER | tCONSTANT | tFID ; 5IFMFGUIBOETJEF 5IFSJHIUIBOETJEF 5IFMFGUIBOETJEFEF fi OFTTZNCPMTUIBUNBLFTZNCPMTNPSFBCTUSBDU 5IFSJHIUIBOETJEFEF fi OFTUIFPSJHJOBMTZNCPMT
  11. )PXQBSTFSXPSLT 4ZNCPMTBSFUVSOFEJOUPNPSFBCTUSBDUTZNCPM XIFOUIFZNBUDIUIFSJHIUIBOETJEFPGUIFTZOUBYSVMFT 5IJTDIBOHFJTDBMMFESFEVDUJPO // An example of a grammar

    rule operation : tIDENTIFIER | tCONSTANT | tFID ; .PSFBCTUSBDUTZNCPM 0SJHJOBMTZNCPMTBSFUVSOFEJOUP NPSFBCTUSBDUTZNCPM
  12. )PXQBSTFSXPSLT 5IFWBMVFTFUGPSUIFTZNCPMCFGPSFSFEVDUJPOXJMMCF DBSSJFEPWFSUPUIFTZNCPMBGUFSSFEVDUJPO 6OMFTTBOBDUJPOUIBUXJMMCFEJTDVTTFEMBUFSJTEF fi OFE // An example of

    a grammar rule operation : tIDENTIFIER | tCONSTANT | tFID ; 5IFNFUIPEJEQVUT UIFWBMVFPGU*%&/5*'*&3 JT TFUUPPQFSBUJPOBGUFSSFEVDUJPO
  13. )PXQBSTFSXPSLT "MUIPVHIPQUJPOBM XIBUUPCFQFSGPSNFEXIFOB SFEVDUJPOIBTPDDVSSFEDBOCFEF fi OFEJOBHSBNNBSSVMF 5IJTJTDBMMFEBTFNBOUJDBDUJPO /PUF4JNQMZDBMMJUBOBDUJPOJOUIJTTMJEF // An

    example of a grammar rule fcall : operation { $$ = NEW_FCALL($1, 0, &@$); nd_set_line($$, p->tokline); } 5IJTBDUJPOJTFYFDVUFE XIFOPQFSBUJPOJTSFEVDFEUPGDBMM
  14. )PXQBSTFSXPSLT *ONBOZDBTFT UIFBDUJPOEF fi OFTBQSPDFTTUPDSFBUFBO 3/PEFGSPNUIFWBMVFTFUJOUIFTZNCPMCFGPSFSFEVDUJPO 5IF3/PEFDSFBUFEJOUIJTXBZJTTFUUPUIFTZNCPMBGUFS SFEVDUJPO // An

    example of a grammar rule fcall : operation { $$ = NEW_FCALL($1, 0, &@$); nd_set_line($$, p->tokline); } $SFBUFBO3/PEFGSPN BOETFUJUUP
  15. 5IF fi STUJEFBJT3FQMBDFA AXJUI*OUFHFSTVDD  XIFOA AJTSFBEGSPNUIFTPVSDFDPEF i = 0

    i++ # => Call Integer#succ and return 1 *OUFHFSTVDDSFUVSOTUIFWBMVFPGUIFSFTVMU XIJDIJTJODSFNFOUFECZUIFSFDFJWFS*OUFHFSPCKFDU i = 0 i.succ # => 1 $BMMJOHBNFUIPEXJUIA A A ABDUTMJLFBOBMJBTGPS*OUFHFSTVDDJOUIJTJEFB
  16. 5IFSFBSFUXPOFDFTTBSZUIJOHTUPJNQMFNFOUUIJT "OFXTZNCPMGPS  4ZNCPM i++ $BMMJOHBNFUIPEXJUIA A   5PLFO

    %F fi OFBOFXTZNCPMGPSUIFUPLFO  BOENBLFUIF TDBOOFSSFUVSOTUIFTZNCPMXIFOJUJTSFBE UPLFO
  17. 5IFSFBSFUXPOFDFTTBSZUIJOHTUPJNQMFNFOUUIJT "EEHSBNNBSSVMFTUPQBSTFBTDSJQUMJLFAJ A BOEDBMM*OUFHFSTVDDJOTJEFPGUIFBDUJPO -FUTHFUUPJU ⬇︎ i = 0 i++

    # Call Integer#succ internally $BMMJOHBNFUIPEXJUIA A %F fi OFBOFXTZNCPMGPSUIFUPLFO  BOENBLFUIF TDBOOFSSFUVSOTUIFTZNCPMXIFOJUJTSFBE UPLFO
  18. // ruby/parse.y // ... %token <id> tIDENTIFIER "local variable or

    method" %token <id> tFID "method" %token <id> tGVAR "global variable" %token <id> tIVAR "instance variable" %token <id> tCONSTANT "constant" %token <id> tCVAR "class variable" %token <id> tLABEL "label" %token <node> tINTEGER "integer literal" %token <node> tFLOAT "float literal" %token <node> tRATIONAL "rational literal" // ... %F fi OFBOFXTZNCPM *OQBSTFZ TZNCPMTBSFEF fi OFEMJLFUIJT
  19. // ruby/parse.y // ... %token <id> tINCOP "increment operator" %token

    <id> tIDENTIFIER "local variable or method" %token <id> tFID "method" %token <id> tGVAR "global variable" %token <id> tIVAR "instance variable" %token <id> tCONSTANT "constant" %token <id> tCVAR "class variable" %token <id> tLABEL "label" %token <node> tINTEGER "integer literal" %token <node> tFLOAT "float literal" %token <node> tRATIONAL "rational literal" // ... /PXMFU`TBEEBOFXTZNCPMU*/$01IFSF GPSUIFUPLFO  %F fi OFBOFXTZNCPM %F fi OFBOFXTZNCPM
  20. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... .BLFUIFTDBOOFSSFUVSOU*/$01 5IFO NPEJGZUIFTDBOOFSUPSFUVSOU*/$01 XIFO JTSFBE *O.3* BGVODUJPOQBSTFS@ZZMFY EPFTNBOZPGXIBU BTDBOOFSEPFTGPSMFYJDBMBOBMZTJT
  21. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... .BLFUIFTDBOOFSSFUVSOU*/$01 5IFSFJTBIVHFTXJUDITUBUFNFOUJOJU 5IJTJTUPSFBEUIFDIBSBDUFSTJOUIFTDSJQUPOFBUB UJNFBOEEPTPNFUIJOHEFQFOEJOH POUIFDIBSBDUFSSFBE %PTPNFUIJOHEFQFOEJOHPOUIFDIBSBDUFSTSFBE
  22. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': // ... .BLFUIFTDBOOFSSFUVSOU*/$01 *OUIJTTXJUDITUBUFNFOU JUJTBMSFBEZEF fi OFE XIBUUPEPJGUIFDIBSBDUFSSFBEJT  *GUIFDIBSBDUFSSFBEJT 
  23. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': c = nextc(p); if (IS_AFTER_OPERATOR()) // ... if (c == '=') // ... .BLFUIFTDBOOFSSFUVSOU*/$01 *OJU BOBQQSPQSJBUFTZNCPMJTSFUVSOFEEFQFOEJOHPO UIFDIBSBDUFSCFGPSFBOEBGUFSUIF  3FBEUIFOFYUDIBSBDUFSPGUIF  3FUVSOTPNFUPLFOJGUIFQSFWJPVTDIBSBDUFSJT 3FUVSOTPNFUPLFOJGUIFOFYUDIBSBDUFSJT "OEPUIFS
  24. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': c = nextc(p); if (c == '+') .BLFUIFTDBOOFSSFUVSOU*/$01 -FUTBEEBOFXDPOEJUJPOIFSF *GUIFOFYUDIBSBDUFSBGUFS JT BHBJO  3FBEUIFOFYUDIBSBDUFSPGUIF  *GUIFOFYUDIBSBDUFSJT BHBJO
  25. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': c = nextc(p); if (c == '+') { return tINCOP; } // ... .BLFUIFTDBOOFSSFUVSOU*/$01 SFUVSOU*/$01 UIFOFXTZNCPMEF fi OFEFBSMJFS 5IFTDBOOFSNPEJ fi DBUJPOJTOPXDPNQMFUF 3FBEUIFOFYUDIBSBDUFSPGUIF  *GUIFOFYUDIBSBDUFSJT BHBJO 3FUVSOU*/$01
  26. // ruby/parse.y method_call : fcall paren_args // ... | primary_value

    call_op operation2 opt_paren_args // ... | primary_value tCOLON2 operation2 paren_args // ... | primary_value tCOLON2 operation3 // ... | primary_value call_op paren_args // ... %F fi OFBOFXHSBNNBSSVMF /FYU MFU`TEF fi OFBOFXHSBNNBSSVMFUPUIFQBSTFS GPSUIFTZOUBYMJLFAJ A QBSTFZEF fi OFTNBOZHSBNNBSSVMFTMJLFUIJTUP TVQQPSUWBSJPVTQBUUFSOTPGNFUIPEDBMMT
  27. // ruby/parse.y method_call : fcall paren_args // ... | primary_value

    call_op operation2 opt_paren_args // ... | primary_value tCOLON2 operation2 paren_args // ... | primary_value tCOLON2 operation3 // ... | primary_value call_op paren_args // ... | ???? %F fi OFBOFXHSBNNBSSVMF *UTFFNTBHPPEJEFBUPEF fi OFBOFXHSBNNBSSVMF IFSFGPSBNFUIPEDBMM %F fi OFBOFXHSBNNBSSVMF
  28. // ruby/parse.y method_call : // ... | primary_value tINCOP %F

    fi OFBOFXHSBNNBSSVMF )FSFJTUIFHSBNNBSSVMFUPCFBEEFE 5IFOFXHSBNNBSSVMFDIFDLTUIBUUIFTZNCPMT  QSJNBSZ@WBMVFBOEU*/$01BSFJOBSPX %F fi OFBOFXHSBNNBSSVMF
  29. // ruby/parse.y method_call : // ... | primary_value tINCOP QSJNBSZ@WBMVFJTUIFTZNCPMGPSUIFSFDFJWFSPGUIJT

    FYQSFTTJPO BOEU*/$01JTGPSA A 5IJTNBLFTFYQSFTTJPOTMJLFAJ AWBMJEBTBTZOUBY   5IFTFTZNCPMTNFBOTʜ J # In a Ruby script i++ %F fi OFBOFXHSBNNBSSVMF
  30. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    // ... %F fi OFBOFXBDUJPOUPDBMM*OUFHFSTVDD /FYU EF fi OFBOBDUJPO XIJDIDBMMT*OUFHFSTVDD XIFOSFEVDUJPOIBTPDDVSSFEGPSUIJTHSBNNBSSVMF
  31. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); %F fi OFBOFXBDUJPOUPDBMM*OUFHFSTVDD 5IF fi STUXFOFFEUPEPJTUPUFMMUIFTDBOOFSUIBUUIJT FYQSFTTJPOFOETXIFO JTSFBE 5IJTJTOFFEFEUPQSFWFOUUIFTDBOOFSSFBETUIFOFYU UPLFOBGUFS BOEDBVTJOHBTZOUBYFSSPS5PEPTP  DBMMUIFNBDSP4&5@-&9@45"5&XJUI&913@&/% 5FSNJOBUFUIJTFYQSFTTJPO /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  32. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); ??? %F fi OFBOFXBDUJPOUPDBMM*OUFHFSTVDD /FYU MFUT fi OBMMZDBMM*OUFHFSTVDD )PXDBOXFEPUIBU /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  33. // ruby/parse.y static NODE * new_qcall(struct parser_params* p, ID atype,

    NODE *recv, ID mid, NODE *args, const YYLTYPE *op_loc, const YYLTYPE *loc) OFX@RDBMM .3*QSPWJEFTOFX@RDBMM UPDSFBUFBO3/PEF UPDBMMBNFUIPE -FUTVTFUIJTGVODUJPOUPEPXIBUJTUIFTBNF BTUIFNFUIPEDBMMJOUIFBDUJPO
  34. // ruby/parse.y static NODE * new_qcall(struct parser_params* p, ID atype,

    NODE *recv, ID mid, NODE *args, const YYLTYPE *op_loc, const YYLTYPE *loc) OFX@RDBMM 4PNFBSHVNFOUTBSFSFRVJSFEUPDBMMUIJTGVODUJPO "O3/PEFUIBUJTUIFSFDFJWFSPGUIFNFUIPE 5IFNFUIPEJE "O3/PEFUIBUJTUIFBSHVNFOUTPGUIFNFUIPE
  35. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); new_qcall(p, $2, ???, ???, ???, &@2, &@$); $BMMOFX@RDBMM UPDBMM*OUFHFSTVDD 4PMFUTQSFQBSFUIFBSHVNFOUTUPDBMMOFX@RDBMM  OFX@RDBMM OFFETBSHVNFOUT /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  36. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); new_qcall(p, $2, ???, ???, ???, &@2, &@$); $BMMOFX@RDBMM UPDBMM*OUFHFSTVDD 'JSTU OFX@RDBMM OFFETBO3/PEFUIBUJTUIFSFDFJWFS BTUIFUIJSEBSHVNFOU "O3/PEFUIBUJTUIFSFDFJWFS /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  37. // ruby/parse.y method_call : // ... | primary_value tINCOP $BMMOFX@RDBMM

    UPDBMM*OUFHFSTVDD "TNFOUJPOFEFBSMJFS QSJNBSZ@WBMVFJTUIFTZNCPM UIBUJTUIFSFDFJWFSPGUIJTFYQSFTTJPO 5IJTTZNCPMIBTBO3/PEFPGUIFSFDFJWFSBTJUTWBMVF QSJNBSZ@WBMVF ʹUIFSFDFJWFS IBT BO3/PEFPGUIFSFDFJWFSPCKFDUBTJUTWBMVF /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  38. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    // ... $1; $BMMOFX@RDBMM UPDBMM*OUFHFSTVDD 3FNFNCFS XFDBOHFUUIFTZNCPMTWBMVFXJUI BOVNCFSPGUIFPSEFSPGUIFTZNCPMT JOBOBDUJPO 5IFWBMVFPGQSJNBSZ@WBMVF JF UIF3/PEFUIBUJT UIFSFDFJWFSJTTUPSFEGPS 5IFWBMVFPGQSJNBSZ@WBMVF   /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  39. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); new_qcall(p, $2, $1, ???, ???, &@2, &@$); $BMMOFX@RDBMM UPDBMM*OUFHFSTVDD 4PDBOCFQBTTFEBTJTBTUIFUIJSEBSHVNFOUPG OFX@RDBMM  /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF 5IFWBMVFPGQSJNBSZ@WBMVF 5IF3/PEFUIBUJTUIFSFDFJWFS
  40. $BMMOFX@RDBMM UPDBMM*OUFHFSTVDD // ruby/parse.y method_call : // ... | primary_value

    tINCOP { SET_LEX_STATE(EXPR_END); new_qcall(p, $2, $1, ???, ???, &@2, &@$); /FYU UIFGPVSUIBSHVNFOUPGOFX@RDBMM JT BNFUIPEJEPGUIFDBMMJOHNFUIPE /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF 5IFNFUIPEJE
  41. $BMMOFX@RDBMM UPDBMM*OUFHFSTVDD // ruby/parse.y method_call : // ... | primary_value

    tINCOP { SET_LEX_STATE(EXPR_END); ID succ = rb_intern("succ"); new_qcall(p, $2, $1, succ, ???, &@2, &@$); (FUUIFNFUIPEJEPG*OUFHFSTVDDBOEQBTTJU UPOFX@RDBMM  (FUUIFNFUIPEJEPG*OUFHFSTVDD /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF 1BTTUIFNFUIPEJE
  42. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); ID succ = rb_intern("succ"); new_qcall(p, $2, $1, succ, ???, &@2, &@$); // ... } $BMMOFX@RDBMM UPDBMM*OUFHFSTVDD 5IF fi GUIBSHVNFOUJTBO3/PEFXIJDIJT UIFDBMMJOHNFUIPEBSHVNFOU /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF 5IFBSHVNFOUTPGUIFDBMMJOHNFUIPE
  43. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); ID succ = rb_intern("succ"); new_qcall(p, $2, $1, succ, Qnull, &@2, &@$); // ... } $BMMOFX@RDBMM UPDBMM*OUFHFSTVDD )PXFWFS *OUFHFSTVDDOPBSHVNFOU -FUTQBTTOJMIFSF /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF 1BTTOJM
  44. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); ID succ = rb_intern("succ"); $$ = new_qcall(p, $2, $1, succ, Qnull, &@2, &@$); $BMMOFX@RDBMM UPDBMM*OUFHFSTVDD 'JOBMMZ TFUUIF3/PEFPGUIFNFUIPEDBMM UIFSFUVSO WBMVFPGOFX@RDBMM UPUIFTZNCPMBGUFSSFEVDUJPO 5IJTDPNQMFUFTUIFWJUBMQBSUPGUIFJNQMFNFOUBUJPO "TTJHOUIFSFUVSOWBMVFUPUIFTZNCPMBGUFSSFEVDUJPO /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  45. *UMPPLTXPSLJOH NBLFSVO HFOFSBUJOHQBSTFD DPNQJMJOHQBSTFD MJOLJOHNJOJSVCZ NJOJSVCZ*SVCZMJC*a *FYUDPNNPOa SBSNEBSXJOGBLF SVCZUFTUSC 

    # ruby/test.rb i = 0 i++ *USFUVSOTBOJODSFNFOUFEWBMVFXJUIPVUBOZ TZOUBYFSSPS 5IFJNQMFNFOUBUJPOPG JTTVDDFTTGVM *USFUVSOTJODSFNFOUFEWBMVF
  46. *GPVOEBQSPCMFNXJUIUIJTJNQMFNFOUBUJPO i = 0 i++ # => It returns 1

    i # => But i is still 0... *UJTUIBU*OUFHFSTVDDEPFTOPUBTTJHOJUTSFUVSOWBMVF UPUIFSFDFJWFSWBSJBCMF
  47. *OUIFQSFWJPVTJNQMFNFOUBUJPO  UIFSFJTBQSPCMFNUIBU*OUFHFSTVDDEJEOPUBTTJHO UIFSFUVSOWBMVFUPUIFSFDFJWFS i = 0 i++ # =>

    Call Integer#succ, then i is still 0 4P JOTUFBEPG*OUFHFSTVDD MFUTDBMMTPNFPUIFS UIBUDBOBTTJHOUIFJODSFNFOUFEWBMVFUPUIFSFDFJWFS i = 0 i++ # => Call some other method, then i becomes 1 $BMMJOHBNFUIPEXJUIA A SFWJTFE NFUIPE
  48. # ruby/numeric.rb class Integer def __plusplus__(name, b) b.local_variable_set(name, self.succ) end

    # ... %F fi OF*OUFHFS@@QMVTQMVT@@ ,FSOFMMPDBM@WBSJBCMF@TFUPSTPNFUIJOH  %FUFSNJOFUIFUZQFPGUIFWBSJBCMFGSPNUIFWBSJBCMFOBNF  1BTTUIFBSHVNFOUT ɾWBSJBCMFOBNF ɾB#JOEJOHPCKFDU 'JSTU MFU`TEF fi OF*OUFHFS@@QMVTQMVT@@ *UJODSFNFOUTTFMGBOETFUTJUTWBMVFUPBWBSJBCMF JOJUTFOWJSPONFOUVTJOHUIFBSHVNFOUT
  49. # ruby/numeric.rb class Integer def __plusplus__(name, b) b.local_variable_set(name, self.succ) end

    # ... %F fi OF*OUFHFS@@QMVTQMVT@@ *OUFHFS@@QMVTQMVT@@DBOCFDBMMFEMJLFUIJT JOB3VCZTDSJQU *UBTTJHOTBOJODSFNFOUFEWBMVFUPUIFSFDFJWFS # In a Ruby script i = 0 i.__plusplus__("i", binding) i # => 1 1BTTUIFBSHVNFOUT ɾWBSJBCMFOBNF ɾ,FSOFMCJOEJOH
  50. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); ID succ = rb_intern("succ"); $$ = new_qcall(p, $2, $1, succ, Qnull, &@2, &@$); // ... } .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@ /FYU MFU`TNPEJGZUIFBDUJPOUPDBMM *OUFHFS@@QMVTQMVT@@JOTUFBEPG*OUFHFSTVDD *OUFHFSTVDDJTDBMMFEJOUIFQSFWJPVTJNQMFNFOUBUJPO /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  51. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); // ... $$ = new_qcall(p, $2, $1, ???, ???, &@3, &@$); .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@ 'JSTU JOUIFTBNFXBZBTCFGPSF  DBMMUIF4&5@-&9@45"5&NBDSPBOEQBTT BTUIFUIJSEBSHVNFOUUPOFX@RDBMM  5FSNJOBUFUIJTFYQSFTTJPO /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF 1BTTUIFWBMVFPGUIFSFDFJWFS
  52. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); ID plusplus = rb_intern("__plusplus__"); $$ = new_qcall(p, $2, $1, plusplus, ???, &@3, &@$); .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@ 1BTTUIFNFUIPEJEPG*OUFHFS@@QMVTQMVT@@ BTUIFGPVSUIBSHVNFOU /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF 1BTTUIFNFUIPEJE (FUUIFNFUIPEJEPG*OUFHFS@@QMVTQMVT@@
  53. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); ID plusplus = rb_intern("__plusplus__"); $$ = new_qcall(p, $2, $1, plusplus, ???, &@3, &@$); .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@ /PX *OUFHFS@@QMVTQMVT@@SFRVJSFTUXPBSHVNFOUT /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF # In a Ruby script i = 0 i.__plusplus__("i", binding)
  54. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); ID plusplus = rb_intern("__plusplus__"); $$ = new_qcall(p, $2, $1, plusplus, ???, &@3, &@$); .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@ 5IF fi STUJTBTUSJOHMJUFSBMPGUIFWBSJBCMFOBNF  BOEUIFTFDPOEJTBNFUIPEDBMMPG,FSOFMCJOEJOH /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF # In a Ruby script i = 0 i.__plusplus__("i", binding) 1BTTUIFBSHVNFOUT ɾWBSJBCMFOBNF ɾ,FSOFMCJOEJOH
  55. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    SET_LEX_STATE(EXPR_END); ID plusplus = rb_intern("__plusplus__"); $$ = new_qcall(p, $2, $1, plusplus, ???, &@3, &@$); .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@ 5IFTFBSHVNFOUTNVTUCFQSFQBSFEBTBO3/PEF UIBUJTBOBSSBZBOEUIFOQBTTFEUPUIF fi GUIBSHVNFOU PGOFX@RDBMM  1BTTUIFBSHVNFOUTIFSF BTBO3/PEFUIBUJTBOBSSBZ /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  56. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    // $1; // $1->u1.id; .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@ 4P MFUTDSFBUFUIFTUSJOHMJUFSBMPGUIFSFDFJWFS`T WBSJBCMFOBNF 8FDBOHFUUIF3/PEFPGUIFSFDFJWFSGSPN 5IFWBSJBCMFJEJTTUPSFEJOBNFNCFSPGUIJT3/PEF /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF 5IFWBMVFPGQSJNBSZ@WBMVF 5IF3/PEFPGUIFSFDFJWFSPCKFDU 5IFWBSJBCMFJEPGUIFSFDFJWFS
  57. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    // ... VALUE v = QUOTE_ID($1->u1.id); NODE *receiver = NEW_LIT(v, &NULL_LOC); .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@ $SFBUFB7"-6&PG4USJOHGSPNUIFWBSJBCMFJE  BOEDSFBUFBO3/PEFPGBMJUFSBMGSPNUIJTWBMVF *UDBOCFUIF fi STUBSHVNFOUPG*OUFHFS@@QMVTQMVT@@ "O3/PEFUIBUJTBTUSJOHMJUFSBMGSPNUIF7"-6& 7"-6&PGUIFTUSJOHGSPNUIFWBSJBCMFJE /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  58. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    // ... VALUE v = QUOTE_ID($1->u1.id); NODE *receiver = NEW_LIT(v, &NULL_LOC); NODE *binding = NEW_VCALL(rb_intern("binding"), &@$); .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@ /FYU DSFBUFBO3/PEFUIBUDBMMT,FSOFCJOEJOH  BTUIFTFDPOEBSHVNFOUPG*OUFHFS@@QMVTQMVT@@ "O3/PEFUIBUDBMMT,FSOFMCJOEJOH /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  59. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    // ... VALUE v = QUOTE_ID($1->u1.id); NODE *receiver = NEW_LIT(v, &NULL_LOC); NODE *binding = NEW_VCALL(rb_intern("binding"), &@$); NODE *args = NEW_LIST(receiver, &NULL_LOC); args = list_append(p, args, binding); .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@ $SFBUFBO3/PEFUIBUJTBOBSSBZGSPNBO3/PEF PGUIFMJUFSBMBOEBO3/PEFPGUIFNFUIPEDBMM "O3/PEFUIBUJTBOBSSBZPGUIFBSHVNFOUT /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  60. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    // ... VALUE v = QUOTE_ID($1->u1.id); NODE *receiver = NEW_LIT(v, &NULL_LOC); NODE *binding = NEW_VCALL(rb_intern("binding"), &@$); NODE *args = NEW_LIST(receiver, &NULL_LOC); args = list_append(p, args, binding); ID plusplus = rb_intern("__plusplus__"); $$ = new_qcall(p, $2, $1, plusplus, args, &@2, &@$); .PEJGZUIFBDUJPOUPDBMM*OUFHFS@@QMVTQMVT@@ 5IFOQBTTJUUPOFX@RDBMM BTJUT fi GUIBSHVNFOU 5IJTDPNQMFUFTUIFWJUBMQBSUPGUIFJNQMFNFOUBUJPO /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  61. *UMPPLTXPSLJOH NBLFSVO HFOFSBUJOHQBSTFD DPNQJMJOHQBSTFD MJOLJOHNJOJSVCZ NJOJSVCZ*SVCZMJC*a *FYUDPNNPOa SBSNEBSXJOGBLF SVCZUFTUSC 

    # ruby/test.rb i = 0 i++ p i JJTOPXJODSFNFOUFE 5IFOUIFDPNQJMBUJPOTVDDFFEFE BOEUIFWBSJBCMFXBT BTTJHOFEBOJODSFNFOUFEWBMVF 5IFJNQMFNFOUBUJPOPG JTTVDDFTTGVM
  62. 5IFSFDFJWFSJTOPUBMXBZTBWBSJBCMF // ruby/parse.y method_call : // ... | primary_value tINCOP

    { // ... SET_LEX_STATE(EXPR_END); VALUE v = QUOTE_ID($1->u1.id); 5IFSFBTPOJTUIBUUIJTJNQMFNFOUBUJPOOFFET UIFWBSJBCMFJEPGUIFSFDFJWFS 8FUSZUPHFUUIFWBSJBCMFJEVOEFSUIFBTTVNQUJPO UIBUUIF3/PEFPGUIFSFDFJWFSPCKFDUIBTJU &YQFDUJOHJTBO3/PEF UIBUIBTUIFWBSJBCMFJE /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF
  63. // ruby/parse.y method_call : // ... | primary_value tINCOP {

    // ... SET_LEX_STATE(EXPR_END); VALUE v = QUOTE_ID($1->u1.id); )PXFWFS JGUIFSFDFJWFSJTBMJUFSBM UIJT3/PEFEPFTOU IBWFUIFWBSJBCMFJE *OUIBUDBTF BOVOJOUFOEFENFNPSZBSFBJTBDDFTTFE BOEBTFHNFOUBUJPOGBVMUPDDVST 6OMFTTUIFSFDFJWFSJTBWBSJBCMF  XFDBO`UBDDFTTWBSJBCMFJE /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF 5IFSFDFJWFSJTOPUBMXBZTBWBSJBCMF
  64. 4P XIZOPUKVTUDSFBUFUIFTBNF"45XJUIA A $ ruby -e "pp RubyVM::AbstractSyntaxTree.parse('i+= 1')" (SCOPE@1:0-1:5

    tbl: [:i] args: nil body: (LASGN@1:0-1:5 :i (CALL@1:0-1:5 (LVAR@1:0-1:1 :i) :+ (LIST@1:4-1:5 (LIT@1:4-1:5 1) nil)))) 5VSOA AJOUPA A 5IF"45PGAJ A
  65. *OQBSTFZ BHSBNNBSSVMFJTEF fi OFEUPQBSTFTDSJQUT TVDIBTAJ A i++ i += 1

    4PJGXFDBOEPFYBDUMZUIFTBNFUIJOHBTAJ A XIFOUIFTDBOOFSSFBEBTDSJQUMJLFAJ A  XF`MMCFBCMFUPQBSTFJUBTAJ A MJLFBTZOUBYTVHBS  5VSOA AJOUPA A ⬇︎
  66. 8IFOUIFTDBOOFSSFBETA A JUSFUVSOTUIFTZNCPM U01@"4(/GPSA ABOEU*/5&(&3GPSAA i += 1 i++ 3FUVSOUIFTBNFTZNCPMTBTA

    A U01@"4(/  U01@"4(/  U*/5&(&3 3/PEF   4ZNCPM 7BMVF U*/5&(&3 3/PEF   4PJUXPVMECFOJDFJGUIFTDBOOFSDPVMESFUVSOCPUIU01@"4(/ BOEU*/5&(&3BUPODFXIFOJUSFBETA A  CVUVOGPSUVOBUFMZ UIFTDBOOFSPOMZSFUVSOTPOFTZNCPMQFSSFBE
  67. 4PIPXBCPVUNPEJGZJOHUIFTDBOOFSMJLFUIJT i += 1 i++ 3FUVSOUIFTBNFTZNCPMTBTA A U01@"4(/  U01@"4(/

     U*/5&(&3 3/PEF   4ZNCPM 7BMVF U*/5&(&3 3/PEF   'PSUIF fi STUA A SFUVSOUIFTZNCPMBOEWBMVFPGA A 'PSUIFTFDPOEA A SFUVSOUIFTZNCPMBOEWBMVFPGJOUFHFS
  68. 5IBOLGVMMZ .3*TDBOOFSIBTMPDBUJPOBMJOGPSNBUJPOJOUIF SFBEJOHMJOF5IFZDPVMECFIFMQGVMJOUIJTUJNF // ruby/parse.y /* Structure of Lexer Buffer:

    lex.pbeg lex.ptok lex.pcur lex.pend | | | | |------------+------------+------------| |<---------->| token */ 5PQQPTJUJPOPGUIFMJOFSFBE &OEQPTJUJPOPGUIFMJOFSFBE $VSSFOUQPTJUJPOPGDVSTPS 5IFTDBOOFSIBTMPDBUJPOBMJOGPSNBUJPO
  69. i++ 5IFOFYUDIBSBDUFSJTUIF fi STU  8IFOUIFTDBOOFSSFBET  EPOPUSFUVSOUIFTZNCPM JNNFEJBUFMZ CVUQFFLOFYUDIBSBDUFS

    LFFQJOHUIFDVSTPS QPTJUJPO  8IBUUIFNPEJ fi FETDBOOFSEPFT 5IFDVSTPSJTIFSF 5IJTJT 
  70. // ruby/parse.y static eunm yytokentype set_integer_literal(struct parser_params *p, VALUE v,

    int suffix) TFU@JOUFHFS@MJUFSBM .3*QSPWJEFTTFU@JOUFHFS@MJUFSBM  *UDSFBUFTBO3/PEFUIBUJTBOJOUFHFSMJUFSBMBOE SFUVSOTUIFTZNCPMU*/5&(&3TFUXJUIJU
  71. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': // ... .BLFUIFTDBOOFSSFUVSOU01@"4(/GPSUIF fi STU  "TXFTBXFBSMJFS QBSTFS@ZZMFY UIBUFYFDVUFTMFYJDBM BOBMZTJTIBTBTXJUDITUBUFNFOUUPCFEF fi OFEBT XIBUUPEPJGUIFSFBEDIBSBDUFSJT  -FUTNPEJGZJU *GUIFDIBSBDUFSSFBEJT  i++
  72. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': peekc(p); .BLFUIFTDBOOFSSFUVSOU01@"4(/GPSUIF fi STU  'JSTU XIFOUIFTDBOOFSSFBET  LFFQUIFDVSTPS QPTJUJPOBOEQFFLUIFOFYUDIBSBDUFSBGUFSJU 5IFSFJTBGVODUJPOQFFLD GPSJUJO.3* 1FFLUIFOFYUDIBSBDUFSPG  i++
  73. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': if (peekc(p) == '+') { set_yylval_id('+'); SET_LEX_STATE(EXPR_BEG); return tOP_ASGN; } .BLFUIFTDBOOFSSFUVSOU01@"4(/GPSUIF fi STU  *GUIFOFYUDIBSBDUFSJT  SFUVSOUIFTZNCPM U01@"4(/XIJDINFBOTA A 3FUVSOU01@"4(/ *GUIFOFYUDIBSBDUFSJT  i++ U01@"4(/
  74. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': if (peekc(p) == '+') { set_yylval_id('+'); SET_LEX_STATE(EXPR_BEG); return tOP_ASGN; } .BLFUIFTDBOOFSSFUVSOU01@"4(/GPSUIF fi STU  5IFOUIFDVSTPSNPWFTBIFBEUPPOFDIBSBDUFSBOE QBSTFS@ZZMFY BUUFNQUTUPSFBEUIFOFYUDIBSBDUFS 5IFDVSTPSNPWFTBIFBE i++
  75. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': if (peekc(p) == '+') { // ... } peekc_n(p, -2) .BLFUIFTDBOOFSSFUVSOU*/5&(&3GPSUIFTFDPOE  /FYU XIFOUIFTDBOOFSSFBETUIFTFDPOE  LFFQUIF DVSTPSQPTJUJPOBOEDIFDLUIFDIBSBDUFSPOFCFGPSFJU QFFLD@O QSPWJEFECZ.3*DBOCFVTFEGPSUIJT 1FFLUIFQSFWJPVTDIBSBDUFSPG  *GUIFDIBSBDUFSSFBEJT  i++
  76. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': if (peekc(p) == '+') { // ... } if (peekc_n(p, -2) == '+') { VALUE i = rb_cstr_to_inum("1", 16, FALSE); .BLFUIFTDBOOFSSFUVSOU*/5&(&3GPSUIFTFDPOE  *GUIFQSFWJPVTDIBSBDUFSXBTBMTPB   UIFODSFBUFB7"-6&UIBUJTBOJOUFHFS $SFBUFB7"-6&UIBUJTBJOUFHFS *GUIFQSFWJPVTDIBSBDUFSJT 
  77. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': if (peekc(p) == '+') { set_yylval_id('+'); SET_LEX_STATE(EXPR_BEG); return tOP_ASGN; } if (peekc_n(p, -2) == '+') { VALUE i = rb_cstr_to_inum("1", 16, FALSE); return set_integer_literal(p, i, 0); } // ... .BLFUIFTDBOOFSSFUVSOU*/5&(&3GPSUIFTFDPOE  3FUVSOUIFSFTVMUPGTFU@JOUFHFS@MJUFSBM i++ U*/5&(&3 1BTTJUBTBOBSHVNFOUUPDBMMTFU@JOUFHFS@MJUFSBM  BOESFUVSOUIFSFTVMUGSPNUIFTDBOOFS
  78. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': if (peekc(p) == '+') { set_yylval_id('+'); SET_LEX_STATE(EXPR_BEG); return tOP_ASGN; } if (peekc_n(p, -2) == '+') { VALUE i = rb_cstr_to_inum("1", 16, FALSE); return set_integer_literal(p, i, 0); } // ... .BLFUIFTDBOOFSSFUVSOU*/5&(&3GPSUIFTFDPOE  5IJTTIPVMESFUVSOUIFTBNFSFTVMUBTJGA A IBECFFOSFBE"OEUIJTJNQMFNFOUBUJPOJTDPNQMFUF U01@"4(/ U*/5&(&3 i++
  79. *TJUXPSLJOH NBLFSVO # ruby/test.rb i = 0 i++ p i

    3VOUIFDPNQJMFDPNNBOE 8JUIUIJTJNQMFNFOUBUJPO XSJUFBTDSJQUDPOUBJOJOH A ABOEDIFDLJOHUIFWBMVFPGUIFSFDFJWFS  UIFOFYFDVUFTUIFDPNQJMFDPNNBOE
  80. *UMPPLTXPSLJOH NBLFSVO HFOFSBUJOHQBSTFD DPNQJMJOHQBSTFD MJOLJOHNJOJSVCZ NJOJSVCZ*SVCZMJC*a *FYUDPNNPOa SBSNEBSXJOGBLF SVCZUFTUSC 

    # ruby/test.rb i = 0 i++ p i JJTOPXJODSFNFOUFE 5IFOUIFDPNQJMBUJPOTVDDFFEFE BOEUIFWBSJBCMFXBT BTTJHOFEBOJODSFNFOUFEWBMVF
  81. NBLFSVO NJOJSVCZ*SVCZMJC*a *FYUDPNNPOa SBSNEBSXJOGBLF SVCZUFTUSCSVCZUFTUSC TZOUBYFSSPS  VOFYQFDUFEPQFSBUPSBTTJHONFOU  FYQFDUJOHFOEPGJOQVU

    4ZOUBY&SSPS  NBLF <SVO>&SSPS *UMPPLTXPSLJOH # ruby/test.rb 1++ "OTZOUBYFSSPSIBTPDDVSSFE $BMMJOHA AXJUIBOJOUFHFSMJUFSBMEPFTOPUDBVTF BTFHNFOUBUJPOGBVMU CVUBTZOUBYFSSPSBTTBNFBT A A5IJTJTUIFJOUFOEFECFIBWJPS 5IFJNQMFNFOUBUJPOPG JTTVDDFTTGVM
  82. *GPVOEBQSPCMFNJOUIJTJNQMFNFOUBUJPOBHBJO i = 0 i++ * 2 # => 2

    p i # => ? 8IFOFYFDVUJOHBTDSJQUMJLFUIJT  XIBUXPVMECFBOBQQSPQSJBUFWBMVFGPSUIFWBSJBCMFAJA
  83. 5IJTJTBLJOEPGMBOHVBHFEFTJHONBUUFS BOEUIFSFBSF NBOZXBZTUPUIJOLBCPVUJU1FSTPOBMMZ *UIJOLJUJT BQQSPQSJBUFGPSUIFWBSJBCMFAJAUPCFBTTJHOFE i = 0 i++ *

    2 # => Expect: (i += 1) * 2 p i # => Expect: 1 *FYQFDUUIFWBSJBCMFAJAUPCFBTTJHOFE fi STUBOE NVMUJQMJFECZOFYU
  84. )PXFWFS UIJTA AJTFRVJWBMFOUUPA A5IFSFGPSF  UIFSFTVMUJTBTTJHOFEUPUIFWBSJBCMFAJABGUFSUIF NVMUJQMJDBUJPOPG JTDPNQVUFE fi STUCZQSFDFEFODF

    i = 0 i++ * 2 # => Actual: i += (1 * 2) p i # => Actual: 2 5IFOUIFWBSJBCMFAJAJTBTTJHOFE *GFFMUIJTJTBOBUVSBMCFIBWJPSGPSA A CVUBCJU TUSBOHFGPSA A
  85. 4JODFUIFQSFDFEFODFPGPQFSBUPSTJTEF fi OFEJOQBSTFZ  JUJTQPTTJCMFUPBWPJEUIJTQSPCMFNCZNBLJOHUIF QSFDFEFODFPGA AIJHIFSUIBOA A // ruby/parse.y

    // ... %right '=' tOP_ASGN %left modifier_rescue %right '?' ':' // ... %left '&' %left tLSHFT tRSHFT %left '+' '-' %left '*' '/' ‘%' // ... 5IFQSFDFEFODF )JHIFS -PXFS
  86. )PXFWFS UIFQSPCMFNUIJTUJNFJTPOMZGPSUIFDBTFPG SFBEJOHA A*EPOUXBOUUPDIBOHFUIFQSFDFEFODFGPS UIFDBTFPGSFBEJOHA AVTVBMMZ x = 0 x

    += 1 ** 2 p x # => Intend: 2 (Keeping current behavior) y = 0 y++ ** 2 p y # => Intend: 1 (Changing current behavior)
  87. *OUIFQSFWJPVTJNQMFNFOUBUJPO XFUSJFEUPNBLFUIF TBNF"45XJUIA ACZUIFTDBOOFS i = 0 i++ * 2

    # => i += (1 * 2) p i # => 2 #VUXFGPVOEUIBUJGA AJTGPMMPXFECZBOFYQSFTTJPO  XFDBOOPUIBOEMFJU 5VSOA AJOUPA A 3FWJTFE
  88. // ruby/parse.y %token <id> tCOLON2 RUBY_TOKEN(COLON2) "::" %token tCOLON3 "::

    at EXPR_BEG" %token <id> tOP_ASGN "operator-assignment" /* +=, -= etc. */ %token <id> tINCOP "increment-operator" %token tASSOC "=>" %token tLPAREN "(" %token tLPAREN_ARG "( arg" %token tRPAREN ")" %token tLBRACK "[" %token tLBRACE “{" %token tSTAR "*" %token tDSTAR "**arg" %token tAMPER "&" // ... %F fi OFTZNCPMU*/$01 'JSTU EF fi OFU*/$01BTUIFTZNCPM GPSUIFUPLFO  %F fi OFBOFXTZNCPMGPS 
  89. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': c = nextc(p); // ... if (c == '+') .BLFUIFTDBOOFSSFUVSOU*/$01 5IFONPEJGZQBSTFS@ZZMFY  *G JTSFBEUXJDFJOBSPX *GUIFOFYUDIBSBDUFSJTBMTP  3FBEOFYUDIBSBDUFSPGUIF  8IFOUIFDIBSBDUFSSFBEJT 
  90. // ruby/parse.y static enum yytokentype parser_yylex(struct parser_params *p) { //

    ... switch (c = nextc(p)) { // ... case '+': c = nextc(p); // ... if (c == '+') { SET_LEX_STATE(EXPR_BEG); return tINCOP; } // ... .BLFUIFTDBOOFSSFUVSOU*/$01 SFUVSOU*/$01 5IFTDBOOFSNPEJ fi DBUJPOJTOPXDPNQMFUF 3FUVSOU*/$01
  91. // ruby/parse.y arg : lhs '=' lex_ctxt arg_rhs // ...

    | var_lhs tOP_ASGN lex_ctxt arg_rhs // ... | ???? %F fi OFBOFXHSBNNBSSVMF /FYU EF fi OFBOFXHSBNNBSSVMFGPSA A 4JODFBHSBNNBSSVMFGPSBTDSJQUTVDIBTAJ AJT EF fi OFEJOQBSTFZ MFUTEF fi OFUIFOFXPOFOFBSIFSF %F fi OFUIFOFXHSBNNBSSVMF "HSBNNBSSVMFGPS 3VCZTDSJQUTMJLFAJ A
  92. // ruby/parse.y arg : // ... | var_lhs lex_ctxt tINCOP

    %F fi OFBOFXHSBNNBSSVMF )FSFJTUIFHSBNNBSSVMFUPCFBEEFE 5IFOFXHSBNNBSSVMFDIFDLTUIBUUIFTZNCPMT  WBS@MIT MFY@DUYU BOEU*/$01BSFJOBSPX %F fi OFBOFXHSBNNBSSVMF
  93. // ruby/parse.y arg : // ... | var_lhs lex_ctxt tINCOP

    5IFNJEEMFPOF MFY@DUYU JTOPUTPSFMFWBOUUIJTUJNF TPTLJQJU WBS@MITJTUIFMFGUTJEFPGA A BOEU*/$01JTA A  MFY@DUYUJTOPUTPSFMFWBOU TPXFTLJQJU  5IJTNBLFTFYQSFTTJPOTMJLFAJ AWBMJEBTBTZOUBY   5IFTFTZNCPMTNFBOTʜ J # In a Ruby script i++ OPOF  %F fi OFBOFXHSBNNBSSVMF
  94. // ruby/parse.y arg : // ... | var_lhs lex_ctxt tINCOP

    { // ... %F fi OFBOFXBDUJPOUPEPUIFTBNFUIJOHA AEPFT -FUTOPXEF fi OFUIFBDUJPOUPCFFYFDVUFEVQPO SFEVDJOHUIJTHSBNNBSSVMF
  95. // ruby/parse.y arg : // ... | var_lhs lex_ctxt tINCOP

    { SET_LEX_STATE(EXPR_END); 'JSTU DBMM4&5@-&9@45"5&XJUI&913@&/%UPUFMM UIFTDBOOFSUPFOEUIJTFYQSFTTJPO /PUF5IFEF fi OJUJPOTPGBDUJPOTGPS3JQQFSBSFTLJQQFEJOUIJTTMJEF 5FSNJOBUFUIJTFYQSFTTJPO %F fi OFBOFXBDUJPOUPEPUIFTBNFUIJOHA AEPFT
  96. // ruby/parse.y arg : // ... | var_lhs lex_ctxt tINCOP

    { SET_LEX_STATE(EXPR_END); ??? /FYU MFUTEPUIFTBNFUIJOHBTA A )PXDBOXFEPUIBU /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF %F fi OFBOFXBDUJPOUPEPUIFTBNFUIJOHA AEPFT
  97. // ruby/parse.y static NODE * new_op_assign(struct parser_params *p, NODE *lhs,

    ID op, NODE *rhs, struct lex_context ctxt, const YYLTYPE *loc); OFX@PQ@BTTJHO .3*QSPWJEFTOFX@PQ@BTTJHO UPDSFBUFBO3/PEF UIBUJTBOFYQSFTTJPOXJUIA APSAA -FUTVTFUIJTGVODUJPOUPEPXIBUJTUIFTBNF BTA A
  98. // ruby/parse.y static NODE * new_op_assign(struct parser_params *p, NODE *lhs,

    ID op, NODE *rhs, struct lex_context ctxt, const YYLTYPE *loc); OFX@PQ@BTTJHO 4PNFBSHVNFOUTBSFSFRVJSFEUPDBMMUIJTGVODUJPO "O3/PEFUIBUJTUIFWBMVFPOUIFMFGUTJEFPGUIFFYQSFTTJPO "OPQFSBUPS A APSAA "O3/PEFUIBUJTUIFWBMVFPOUIFSJHIUTJEFPGUIFFYQSFTTJPO
  99. // ruby/parse.y arg : // ... | var_lhs lex_ctxt tINCOP

    { SET_LEX_STATE(EXPR_END); // ... new_op_assign(p, ???, ???, ???, $2, &@$); } $BMMOFX@PQ@BTTJHO /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF 4PMFUTQSFQBSFUIFBSHVNFOUT UPDBMMOFX@PQ@BTTJHO  OFX@PQ@BTTJHO SFRVJSFTBSHVNFOUT
  100. // ruby/parse.y arg : // ... | var_lhs lex_ctxt tINCOP

    { SET_LEX_STATE(EXPR_END); // ... new_op_assign(p, $1, '+', ???, $2, &@$); } 1BTTUIFMFGUIBOETJEFPGA ABTUIFTFDPOE BSHVNFOUBOEA ABTUIFUIJSEBSHVNFOU -FGUIBOETJEF   /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF $BMMOFX@PQ@BTTJHO
  101. // ruby/parse.y arg : // ... | var_lhs lex_ctxt tINCOP

    { SET_LEX_STATE(EXPR_END); // ... new_op_assign(p, $1, '+', ???, $2, &@$); } 5IFGPVSUIBSHVNFOUJTUIFWBMVFPGUIFSJHIUTJEFPG A A*OUIFDBTFPGA A UIFSJHIUTJEFJTBMXBZTBO JOUFHFS TPXFOFFEUPDSFBUFBWBMVFPGUIJT 3FRVJSFTBOJOUFHFSWBMVFAA /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF $BMMOFX@PQ@BTTJHO
  102. // ruby/parse.y arg : // ... | var_lhs lex_ctxt tINCOP

    { SET_LEX_STATE(EXPR_END); // ... new_op_assign(p, $1, '+', ???, $2, &@$); } TFU@JOUFHFS@MJUFSBM VTFEJOPOFQSFWJPVT JNQMFNFOUBUJPODBOOPUCFVTFEIFSF  BTJUJTBGVODUJPOUPTFUBWBMVFUPBTZNCPM 8FOFFEUPDSFBUFBO3/PEFUIBUJTBOJOUFHFS /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF $BMMOFX@PQ@BTTJHO
  103. // ruby/parse.y arg : // ... | var_lhs lex_ctxt tINCOP

    { SET_LEX_STATE(EXPR_END); VALUE v = rb_cstr_to_inum("1", 16, FALSE); NODE *one = NEW_LIT(v, &NULL_LOC); 5PEPUIJT DSFBUFB7"-6&PGJOUFHFS BOEUIFO DSFBUFBO3/PEFUIBUJTMJUFSBMGSPNUIJT7"-6& "7"-6&PGBOJOUFHFS "O3/PFPGBMJUFSBM /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF $BMMOFX@PQ@BTTJHO
  104. // ruby/parse.y arg : // ... | var_lhs lex_ctxt tINCOP

    { SET_LEX_STATE(EXPR_END); VALUE v = rb_cstr_to_inum("1", 16, FALSE); NODE *one = NEW_LIT(v, &NULL_LOC); RB_OBJ_WRITTEN(p->ast, Qnil, x); new_op_assign(p, $1, '+', one, $2, &@$); } 5IFOQBTTJUUPUIFGPVSUIBSHVNFOUPG OFX@PQ@BTTJHO  1BTTUIF3/PEFUIBUJTBJOUFHFSMJUFSBM /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF $BMMOFX@PQ@BTTJHO
  105. // ruby/parse.y arg : // ... | var_lhs lex_ctxt tINCOP

    { SET_LEX_STATE(EXPR_END); VALUE v = rb_cstr_to_inum("1", 16, FALSE); NODE *one = NEW_LIT(v, &NULL_LOC); RB_OBJ_WRITTEN(p->ast, Qnil, x); $$ = new_op_assign(p, $1, '+', one, $2, &@$); } 'JOBMMZ TFUUIF3/PEF UIFSFUVSOWBMVFPG OFX@PQ@BTTJHO UPUIFTZNCPMBGUFSSFEVDUJPO /PUFUIFEF fi OJUJPOPGBDUJPOTJTTMJHIUMZTJNQMJ fi FEJOUIJTTMJEF "TTJHOUIFSFUVSOWBMVFUPUIFTZNCPMBGUFSSFEVDUJPO $BMMOFX@PQ@BTTJHO
  106. *OPSEJOBSZ3VCZ XFDBOVTFBOZOVNCFSPG JO TVDDFTTJPOXJUIPVUDBVTJOHTZOUBYFSSPST # Normal Ruby i = 0

    i + 1 # => 1 i ++ 1 # => 1 i +++ 1 # => 1 i ++++ 1 # => 1 i +++++ 1 # => 1 5IJTJTCFDBVTFJGUIFSFBSFUXPPSNPSF T  UIFTFDPOEBOETVCTFRVFOU TBSFDPOTJEFSFE VOBSZ PQFSBUPST "MM`T/05XFMMUIBUFOETXFMM "MMTZOUBY0,
  107. #VUJO3VCZXJUI PQFSBUPS  XFHFUBTZOUBYFSSPSXJUIVOFYQFDUFEJOUFHFSMJUFSBM JGXFUSZUPQVUBOJOUFHFSBGUFSA A # Ruby with "++"

    operator # ruby/test.rb i = 0 i + 1 # => 1 i ++ 1 # => SyntaxError i = 0 i + (+1) # => 1 i ++ +1 # => 3 "MM`T/05XFMMUIBUFOETXFMM SVCZSVCZUFTUSC SVCZUFTUSCSVCZUFTUSC TZOUBYFSSPS VOFYQFDUFEJOUFHFSMJUFSBM  FYQFDUJOHFOEPGJOQVU 4ZOUBY&SSPS  J  J ? 5IFZBSFTZOUBY0, ɾ5PVTFBVOBSZPQFSBUPSXJUIQBSFOUIFTFT ɾ5PVTFA ABOEBVOBSZPQFSBUPSBUUIFTBNFUJNF
  108. *TUIJTBWBMJETQFDJ fi DBUJPO  )PXTIPVMEUIF PQFSBUPSBOEVOBSZPQFSBUPST DPPQFSBUFXJUIFBDIPUIFS  5IFTFBSFRVFTUJPOTUIBUTIPVMECFDPOTJEFSFEJO3VCZ UIBUBEEFEUIFOFXTZOUBYXJUIUIF

    PQFSBUPS 5IJTJTBOJTTVFPGMBOHVBHFEFTJHO 'PSUIFNPNFOU UIJTJTUIFTQFDJ fi DBUJPOPGUIF JNQMFNFOUBUJPOTPGBS 5IFMBOHVBHFEFTJHOBGUFSBEEJOHBOFXTZOUBY
  109. "OEBT*IBWFTIPXO .3*IBTNBOZVTFGVMUPPMLJUTGPS SFBMJ[JOHUIFTFJEFBT 7BSJPVTUPPMLJUTUPTVQQPSUZPVSJEFB 'PSFYBNQMF )PXUPNPEJGZUIFTDBOOFS QBSTFS@ZZMFY  )PXUPEF fi

    OFOFXTZOUBYSVMFTBOEBDUJPOTXJUITFNBOUJDWBMVFT 8IBUJTUIFPCKFDUPSJFOUFETFNBOUJDT "NBDSPUPDIBOHFUIFTUBUFPGUIFTDBOOFS 4&5@-&9@45"5&  4PNFVTFGVMGVODUJPOTUPDSFBUF3/PEFT FHOFX@RDBMM OFX@PQ@BTHO  4PNFVTFGVMNBDSPTUPDSFBUF3/PEFT FH/&8@-*5 /&8@7$"-- /&8@-*45  5IFMPDBUJPOBMJOGPSNBUJPOPGUIFTDBOOFSBOETPNFVTFGVMGVODUJPOT UPQFFLBUUIFDIBSBDUFSPOBTPVSDFDPEF FHQFFLD QFFLD@O
  110. 5IBOLZPVGPSZPVSBUUFOUJPO 4QFDJBMUIBOLTUP !TQJLFPMBG !NJOFSPBPLJ !PLVSBNBTBGVNJ 3FGFSFODFUP 3VCZ)BDLJOH(VJEF 1BSU4ZOUBYBOBMZTJT  IUUQTSVCZIBDLJOHHVJEFHJUIVCJP

     3VCZ6OEFSB.JDSPTDPQF"O*MMVTUSBUFE(VJEFUP3VCZ*OUFSOBMT $IBQUFS5PLFOJ[BUJPOBOE1BSTJOH  IUUQTQBUTIBVHIOFTTZOFUSVCZVOEFSBNJDSPTDPQF