Slide 1

Slide 1 text

੩తݕࠪͷ͍Ζ͸ ࣄલ஌ࣝͳ͠Ͱཧղ͢Δ Kuniwak - DeNA Co.,Ltd. 2018.09.07 builderscon tokyo 2018

Slide 2

Slide 2 text

"CPVUNF

Slide 3

Slide 3 text

,VOJXBL w ॴଐˠ w HJUIVCDPN,VOJXBL w RJJUBDPN,VOJXBL w ίϯϐϡʔλαΠΤϯεΛ
 ֶΜͰ͖͍ͯ·ͤΜ w ࣄલ஌ࣝͳ͠Ͱ੩తղੳ
 πʔϧΛ։ൃ͖ͯͨ͠

Slide 4

Slide 4 text

͜Ε·Ͱʹ͖ͭͬͯͨ͘
 ੩తݕࠪܥͷπʔϧͷ঺հ

Slide 5

Slide 5 text

7JNTDSJQUͷ੩తݕࠪπʔϧ https://github.com/Kuniwak/Vint

Slide 6

Slide 6 text

$44ͷมߋ఺ΛՄࢹԽ͢Δπʔϧ https://github.com/mixi-inc/css-semdiff $ css-astdiff a.css b.css --verbose extra: .extra-1 { border: none; } missing: .missing-1 { border: none; } --------------------------------- 1 extra rules and 1 missing rules

Slide 7

Slide 7 text

मਖ਼ͷӨڹൣғΛڭ͑ͯ͘ΕΔπʔϧ https://twitter.com/orga_chem/status/674847225684475905 ˞લ৬

Slide 8

Slide 8 text

͜ͷൃදΛฉ͘ͱ
 Θ͔Δ͜ͱ ͸͡Ίʹ

Slide 9

Slide 9 text

੩తղੳΛߏ੒͢Δ͍͔ͭ͘ͷߟ͑ํ ͕Θ͔ΔΑ͏ʹͳΔ ߟ͑ํ͑͞ཧղͰ͖Ε͹ɺ੩తղੳΛ
 ࣮૷͢Δͷ͸೉͘͠ͳ͍͜ͱ͕Θ͔Δ

Slide 10

Slide 10 text

΋͏ͪΐͬͱ۩ମతʹ ͜ͷൃදͷ໨ඪ

Slide 11

Slide 11 text

if isEmpty('') { //CATCH_ME_IF_YOU_CAN } CATCH_ME_IF_YOU_CANͱॻ͔Εͨੜҙؾͳ
 ίϝϯτʢจࣈྻ಺ͷ͸/(ʣΛݕ஌͢Δ
 ੩తݕࠪΛ៉ྷʹ࣮૷Ͱ͖ΔΑ͏ʹͳΔ

Slide 12

Slide 12 text

؆୯͗͢ͳ͍ʁͱ
 ࢥͬͨ͋ͳͨ΁

Slide 13

Slide 13 text

ಉ͡ϓϩάϥϜͰ࣍ͷίʔυ΋
 ղੳͰ͖·͔͢ʁ fake('', ' //CATCH_ME_IF_YOU_CAN ↩︎ ') ͜Ε͸จࣈྻͳͷͰݕ஌ͯ͠͸͍͚ͳ͍ ͜ͷվߦ͸ҙਤతͰ͢

Slide 14

Slide 14 text

͜ͷൃදͰ͸ɺҙ஍ѱͳέʔεʹ΋
 ରԠͰ͖Δ੩తղੳΛઆ໌͠·͢

Slide 15

Slide 15 text

੩తղੳͱ͸ Ͱ͸ͬͦ͘͞

Slide 16

Slide 16 text

੩తݕࠪͱ͸ɺݕ͍ࠪͨ͠ϓϩάϥϜΛ
 ࣮ߦ͠ͳ͍··֤छͷҟৗΛݕࠪ͢Δख๏ͷ͜ͱ ݴޠ͝ͱʹ༷ʑͳ੩తݕࠪͷͨΊͷπʔϧ͕͋Δɿ w 1ZUIPOͳΒ1ZqBLFT΍NZQZͳͲ w 3VCZͳΒ3VCPDPQͳͲ w +BWB4DSJQUͳΒ&4-JOUͳͲ w +BWBͳΒ4QPU#VHTͳͲ

Slide 17

Slide 17 text

͜͜Ͱٙ໰ ͳͥ੩తʹݕ͍ࠪͨ͠ͷ͔

Slide 18

Slide 18 text

ݕ͍ࠪͨ͠ϓϩάϥϜΛ࣮ߦͯ͠ʢಈతʣ
 ݕࠪ͢Δ৔߹ɺݕࠪதʹ௨ա͍ͯ͠ͳ͍
 ίʔυ͸ݕࠪͰ͖ͳ͍ isFoo = true if isFoo { } else { } ͪ͜Β͸ಈతʹݕࠪͰ͖Δ ͪ͜Β͸ಈతʹݕࠪͰ͖ͳ͍

Slide 19

Slide 19 text

੩తݕࠪ͸ಈతݕ͕ࠪۤखͳ
 ໢ཏతͳݕ͕ࠪಘҙ ͔͠͠੩తݕࠪ͸ಈతݕࠪ΄Ͳ
 ݕࠪ݁Ռ͕ਖ਼֬ʹͳΒͳ͍

Slide 20

Slide 20 text

੩తݕࠪΛ஌Δ͜ͱͰ
 ։ൃΛޮ཰ԽͰ͖Δཧ༝ ͳΜͷ໾ʹཱͭͷ͔ٙ໰ͳ͋ͳͨ΁

Slide 21

Slide 21 text

  ίʔυϨϏϡʔͷҰ෦Λ
 ࣗಈԽͰ͖ΔΑ͏ʹͳΔ ศརͳࣾ಺πʔϧΛͭͬͯ͘
 ͋Γ͕͕ͨΒΕΔ طଘͷ੩తղੳπʔϧΛվྑɾ
 σόοάͰ͖ΔΑ͏ʹͳΔ 

Slide 22

Slide 22 text

ίʔυϨϏϡʔࣗಈԽͷྫ http://alpha.mixi.co.jp/entry/2015/12/20/000000 $ css-astdiff a.css b.css --verbose extra: .extra-1 { border: none; } missing: .missing-1 { border: none; } --------------------------------- 1 extra rules and 1 missing rules  ߦͷ$44Λ
 ো֐θϩͰ-FTT΁
 Ҡߦͨ͠ࡍͷπʔϧ

Slide 23

Slide 23 text

ศརͳࣾ಺πʔϧʢʁʣͷྫ https://twitter.com/orga_chem/status/674847225684475905 ऍ໌ WJTVBMJ[BUJPO͸ఘΊ·͕ͨ͠ɺ
 ґଘΛҰཡͰݟΒΕΔαʔϏε
 ͭͬͨ͘Βศརʹ࢖ΘΕ·ͨ͠

Slide 24

Slide 24 text

શମతͳઆ໌ͷྲྀΕ ͜Ε͔Βͷ

Slide 25

Slide 25 text

֓೦Λཧղ͢Δ  ந৅ߏจ໦Λཧղ͢Δ  ந৅ߏจ໦ͷ࡞ΓํΛཧղ͢Δ  ந৅ߏจ໦ͷѻ͍ํΛཧղ͢Δ ࡞ΓํΛཧղ͢Δ  ؆୯ͳ੩తղੳΛ࣮૷͢Δ  ੩తղੳͷσβΠϯύλʔϯΛ஌Δ  ࣮ࡍͷ੩తղੳΛಡΉ

Slide 26

Slide 26 text

ந৅ߏจ໦Λཧղ͢Δ ·ͣ͸

Slide 27

Slide 27 text

੩తݕࠪͰऔΓѻ͏୅දతͳ
 σʔλͷछྨ͸͍͔ͭ͋͘Δ

Slide 28

Slide 28 text

ந৅ߏจ໦ ίʔυΛ໦ߏ଄Ͱදݱͨ͠΋ͷ ଟ͘ͷ੩తղੳͷجຊ τʔΫϯྻ ίʔυͷখ͞ͳߏ੒୯ҐΛ
 ग़ݱॱʹฒ΂ͨ΋ͷ ελΠϧʹؔ͢Δ੩తղੳͰ
 Α͘࢖ΘΕΔ ੍ޚϑϩʔάϥϑ ίʔυͷ৚݅෼ذͳͲͷ
 ੍ޚߏ଄Λ࿈݁ͨ͠ϒϩοΫͰ
 දݱͨ͠΋ͷ ίʔϧάϥϑ ؔ਺ͷݺͼग़ؔ͠܎ΛάϥϑͰ
 දݱͨ͠΋ͷ ະ࢖༻ؔ਺ͷղੳͳͲʹΑ͘
 ࢖ΘΕΔ

Slide 29

Slide 29 text

τʔΫϯྻ ίʔυͷখ͞ͳߏ੒୯ҐΛ
 ग़ݱॱʹฒ΂ͨ΋ͷ ελΠϧʹؔ͢Δ੩తղੳͰ
 Α͘࢖ΘΕΔ ੍ޚϑϩʔάϥϑ ίʔυͷ৚݅෼ذͳͲͷ
 ੍ޚߏ଄Λ࿈݁ͨ͠ϒϩοΫͰ
 දݱͨ͠΋ͷ ίʔϧάϥϑ ؔ਺ͷݺͼग़ؔ͠܎ΛάϥϑͰ
 දݱͨ͠΋ͷ ະ࢖༻ؔ਺ͷղੳͳͲʹΑ͘
 ࢖ΘΕΔ ந৅ߏจ໦ ίʔυΛ໦ߏ଄Ͱදݱͨ͠΋ͷ ଟ͘ͷ੩తղੳͷجຊ ࠓճղઆ͢Δ΋ͷ

Slide 30

Slide 30 text

if isEmpty('') { // COMMENT } 1SPHSBN *G4UBUFNFOU 4USJOH-JUFSBM 'VOD$BMM *EFOUJpFS $PNNFOU ந৅ߏจ໦ ίʔυ

Slide 31

Slide 31 text

if isEmpty('') { // COMMENT } ந৅ߏจ໦ ίʔυ ˞4UBUFNFOU͸ʮจʯͷҙຯͳͷͰɺ*G4UBUFNFOU͸ʮJGจʯͷҙຯͰ͢ 1SPHSBN 4USJOH-JUFSBM 'VOD$BMM *EFOUJpFS $PNNFOU *G4UBUFNFOU

Slide 32

Slide 32 text

if isEmpty('') { // COMMENT } 1SPHSBN *G4UBUFNFOU 4USJOH-JUFSBM *EFOUJpFS $PNNFOU 'VOD$BMM ந৅ߏจ໦ ίʔυ

Slide 33

Slide 33 text

if isEmpty('') { // COMMENT } 1SPHSBN *G4UBUFNFOU 4USJOH-JUFSBM 'VOD$BMM $PNNFOU *EFOUJpFS ந৅ߏจ໦ ίʔυ

Slide 34

Slide 34 text

if isEmpty('') { // COMMENT } 1SPHSBN *G4UBUFNFOU 'VOD$BMM *EFOUJpFS $PNNFOU 4USJOH-JUFSBM ந৅ߏจ໦ ίʔυ

Slide 35

Slide 35 text

if isEmpty('') { // COMMENT } 1SPHSBN *G4UBUFNFOU 4USJOH-JUFSBM 'VOD$BMM *EFOUJpFS $PNNFOU ந৅ߏจ໦ ίʔυ

Slide 36

Slide 36 text

if isEmpty('') { // COMMENT } ந৅ߏจ໦ *G4UBUFNFOU 4USJOH-JUFSBM 'VOD$BMM *EFOUJpFS $PNNFOU 1SPHSBN ίʔυ

Slide 37

Slide 37 text

if isEmpty('') { // COMMENT } 1SPHSBN *G4UBUFNFOU 4USJOH-JUFSBM 'VOD$BMM *EFOUJpFS $PNNFOU ந৅ߏจ໦ ίʔυ ந৅ߏจ໦͸ɺίʔυͷߏ଄Λ
 ໦ߏ଄ͷσʔλͱͯ͠දݱͨ͠΋ͷ

Slide 38

Slide 38 text

໦ߏ଄Ͱ͸1SPHSBN΍
 $PNNFOUͷΑ͏ͳ
 ໦Λߏ੒͢Δઅ఺ͷ͜ͱΛ
 ʮϊʔυʯͱݺͿ 1SPHSBN *G4UBUFNFOU 4USJOH-JUFSBM 'VOD$BMM *EFOUJpFS $PNNFOU

Slide 39

Slide 39 text

࣮ࡍͷϝδϟʔͳݴޠͷ
 ந৅ߏจ໦ΛݟͯΈΑ͏ ந৅ߏจ໦͸ͳΜͱͳ͘Θ͔ͬͨͷͰ

Slide 40

Slide 40 text

ϝδϟʔͳݴޠͷந৅ߏจ໦͸
 ҙ֎ͱ؆୯ʹΈΒΕΔ ݴޠʹΑͬͯ͸ඪ४ϥΠϒϥϦ͚ͩͰ
 ந৅ߏจ໦ΛΈΒΕͨΓ͢Δ

Slide 41

Slide 41 text

1ZUIPOͷந৅ߏจ໦ͷݟํ import ast source = "if is_empty(''):\n" \ " pass\n" node = ast.parse(source, "sample.py") print(ast.dump(node))

Slide 42

Slide 42 text

if is_empty(''): pass ந৅ߏจ໦ 1ZUIPO Module( body=[ If( test=Call( func=Name( id='is_empty', ctx=Load() ), args=[ Str(s='') ], keywords=[] ), body=[ Pass() ], orelse=[] ) ] )

Slide 43

Slide 43 text

if is_empty(''): pass ந৅ߏจ໦ 1ZUIPO Module( body=[ If( test=Call( func=Name( id='is_empty', ctx=Load() ), args=[ Str(s='') ], keywords=[] ), body=[ Pass() ], orelse=[] ) ] )

Slide 44

Slide 44 text

if is_empty(''): pass ந৅ߏจ໦ 1ZUIPO Module( body=[ If( test=Call( func=Name( id='is_empty', ctx=Load() ), args=[ Str(s='') ], keywords=[] ), body=[ Pass() ], orelse=[] ) ] )

Slide 45

Slide 45 text

if is_empty(''): pass ந৅ߏจ໦ 1ZUIPO Module( body=[ If( test=Call( func=Name( id='is_empty', ctx=Load() ), args=[ Str(s='') ], keywords=[] ), body=[ Pass() ], orelse=[] ) ] )

Slide 46

Slide 46 text

if is_empty(''): pass ந৅ߏจ໦ 1ZUIPO Module( body=[ If( test=Call( func=Name( id='is_empty', ctx=Load() ), args=[ Str(s='') ], keywords=[] ), body=[ Pass() ], orelse=[] ) ] )

Slide 47

Slide 47 text

if is_empty(''): pass ந৅ߏจ໦ 1ZUIPO Module( body=[ If( test=Call( func=Name( id='is_empty', ctx=Load() ), args=[ Str(s='') ], keywords=[] ), body=[ Pass() ], orelse=[] ) ] )

Slide 48

Slide 48 text

3VCZͷந৅ߏจ໦ͷݟํ require 'ripper' require 'pp' example = <<~END if is_empty('') end END pp Ripper.sexp(example)

Slide 49

Slide 49 text

ந৅ߏจ໦ 3VCZ [:program, [ [:if, [:method_add_arg, [:fcall, [:@ident, "is_empty", [1, 3] ] ], [:arg_paren, [:args_add_block, [[:string_literal, [:string_content]]], false ] ] ], [[:void_stmt]], nil ] ] ] if is_empty('') end

Slide 50

Slide 50 text

[:program, [ [:if, [:method_add_arg, [:fcall, [:@ident, "is_empty", [1, 3] ] ], [:arg_paren, [:args_add_block, [[:string_literal, [:string_content]]], false ] ] ], [[:void_stmt]], nil ] ] ] ந৅ߏจ໦ 3VCZ if is_empty('') end

Slide 51

Slide 51 text

[:program, [ [:if, [:method_add_arg, [:fcall, [:@ident, "is_empty", [1, 3] ] ], [:arg_paren, [:args_add_block, [[:string_literal, [:string_content]]], false ] ] ], [[:void_stmt]], nil ] ] ] ந৅ߏจ໦ 3VCZ if is_empty('') end

Slide 52

Slide 52 text

[:program, [ [:if, [:method_add_arg, [:fcall, [:@ident, "is_empty", [1, 3] ] ], [:arg_paren, [:args_add_block, [[:string_literal, [:string_content]]], false ] ] ], [[:void_stmt]], nil ] ] ] ந৅ߏจ໦ 3VCZ if is_empty('') end

Slide 53

Slide 53 text

[:program, [ [:if, [:method_add_arg, [:fcall, [:@ident, "is_empty", [1, 3] ] ], [:arg_paren, [:args_add_block, [[:string_literal, [:string_content]]], false ] ] ], [[:void_stmt]], nil ] ] ] ந৅ߏจ໦ 3VCZ if is_empty('') end

Slide 54

Slide 54 text

+BWB4DSJQUͷந৅ߏจ໦ͷݟํ import {default as Esprima} from "esprima"; const program = "if (isEmpty('')) {\n" + "}\n"; const node = Esprima.parseScript(program); console.log("%j", node);

Slide 55

Slide 55 text

ந৅ߏจ໦ +BWB4DSJQU { "type": "Program", "body": [ { "type": "IfStatement", "test": { "type": "CallExpression", "callee": { "type": "Identifier", "name": "isEmpty" }, "arguments": [ { "type": "Literal", "value": "", "raw": "''" } ] }, "consequent": { "type": "BlockStatement", "body": [] }, "alternate": null } ], "sourceType": "script" } if (isEmpty('')) { }

Slide 56

Slide 56 text

ந৅ߏจ໦ +BWB4DSJQU { "type": "Program", "body": [ { "type": "IfStatement", "test": { "type": "CallExpression", "callee": { "type": "Identifier", "name": "isEmpty" }, "arguments": [ { "type": "Literal", "value": "", "raw": "''" } ] }, "consequent": { "type": "BlockStatement", "body": [] }, "alternate": null } ], "sourceType": "script" } if (isEmpty('')) { }

Slide 57

Slide 57 text

ந৅ߏจ໦ +BWB4DSJQU if (isEmpty('')) { } { "type": "Program", "body": [ { "type": "IfStatement", "test": { "type": "CallExpression", "callee": { "type": "Identifier", "name": "isEmpty" }, "arguments": [ { "type": "Literal", "value": "", "raw": "''" } ] }, "consequent": { "type": "BlockStatement", "body": [] }, "alternate": null } ], "sourceType": "script" }

Slide 58

Slide 58 text

ந৅ߏจ໦ +BWB4DSJQU if (isEmpty('')) { } { "type": "Program", "body": [ { "type": "IfStatement", "test": { "type": "CallExpression", "callee": { "type": "Identifier", "name": "isEmpty" }, "arguments": [ { "type": "Literal", "value": "", "raw": "''" } ] }, "consequent": { "type": "BlockStatement", "body": [] }, "alternate": null } ], "sourceType": "script" }

Slide 59

Slide 59 text

ந৅ߏจ໦ +BWB4DSJQU { "type": "Program", "body": [ { "type": "IfStatement", "test": { "type": "CallExpression", "callee": { "type": "Identifier", "name": "isEmpty" }, "arguments": [ { "type": "Literal", "value": "", "raw": "''" } ] }, "consequent": { "type": "BlockStatement", "body": [] }, "alternate": null } ], "sourceType": "script" } if (isEmpty('')) { }

Slide 60

Slide 60 text

ந৅ߏจ໦ͷ·ͱΊ w ந৅ߏจ໦͸ϓϩάϥϜΛ໦ߏ଄Ͱදݱͨ͠΋ͷ w ଟ͘ͷ੩తղੳʹந৅ߏจ໦͕ొ৔͢Δ w ϝδϟʔͳݴޠͰ͋Ε͹؆୯ʹΈΒΕΔ

Slide 61

Slide 61 text

ந৅ߏจ໦Λͭ͘Δ
 ߏจղੳΛ஌Ζ͏ ந৅ߏจ໦Λ׬શʹཧղͨ͠ͷͰ

Slide 62

Slide 62 text

ϓϩάϥϜͷςΩετ͔Βந৅ߏจ໦Λ
 ࡞੒͢ΔॲཧΛߏจղੳͱݺͿ ߏจղੳΛ஌Δͱɺطଘͷߏจղੳ
 ϥΠϒϥϦΛ࢖͏ͱ͖ͷ஫ҙ఺͕Θ͔Δ ͨͱ͑͹ɺੑೳྼԽ͠΍͍͢෦෼ͳͲ͕Θ͔Δ

Slide 63

Slide 63 text

ߏจղੳͷ୅දత࣮૷ख๏ w ࠶ؼԼ߱๏ w όοΫτϥοΫ͋Γ w ૉ௚ͳ࣮૷ w 1BSTFS$PNCJOBUPS w 1BSTFS&YQSFTTJPO(SBNNBS w όοΫτϥοΫͳ͠ w ʜ w ԋࢉࢠॱҐ๏ w ʜ ࠓճղઆ͢Δ࣮૷

Slide 64

Slide 64 text

ͪΌΜͱͨ͠ఆٛ͸೉͘͠ฉ͑͜Δ͕ɺ
 ࣮ࡍͷίʔυΛΈΕ͹͙͢ʹཧղͰ͖Δ श͏ΑΓ׳ΕΑ͏

Slide 65

Slide 65 text

จ๏نଇͷ঺հ ࠓ͔ΒߏจղੳΛ࣮૷͢Δ

Slide 66

Slide 66 text

<ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> := "if " <ࣜ> " {\n" <จ>* "}" "\n" <ࣜจ> := <ࣜ> "\n" <ίϝϯτจ> := "//" [A-Z_ ]* "\n" <ࣜ> := <จࣈྻϦςϥϧ> | <ؔ਺ݺͼग़ࣜ͠> <จࣈྻϦςϥϧ> := "'" ("\'" | [A-Z_ ])* "'" <ؔ਺ݺͼग़ࣜ͠> := <ؔ਺໊> "(" <ࣜ> ")" <ؔ਺໊> := [a-z] [a-z]* ͜ͷ··ͩͱΘ͔ΓͮΒ͍ͷͰɺ۩ମྫΛग़͠·͢

Slide 67

Slide 67 text

ίϝϯτ͚ͩϓϩάϥϜ // COMMENT ↩︎ EOF &0'͸ϑΝΠϧͷऴྃʢ&OEPG'JMFʣΛҙຯ͢Δه߸

Slide 68

Slide 68 text

<ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ίϝϯτจ> := "//" [A-Z_ ]* "\n" ίϝϯτ͚ͩϓϩάϥϜ ద༻͞Εͨจ๏نଇ ͔͜͜ΒݟΔ // COMMENT ↩︎ EOF

Slide 69

Slide 69 text

<ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ίϝϯτจ> := "//" [A-Z_ ]* "\n" ίϝϯτ͚ͩϓϩάϥϜ ద༻͞Εͨจ๏نଇ จͷ܁Γฦ͠ʹଓ͍ͯ&0'͕͘Δ // COMMENT ↩︎ EOF

Slide 70

Slide 70 text

<ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ίϝϯτจ> := "//" [A-Z_ ]* "\n" ίϝϯτ͚ͩϓϩάϥϜ ద༻͞Εͨจ๏نଇ จͷத਎Λݟʹ͍͘ // COMMENT ↩︎ EOF

Slide 71

Slide 71 text

<ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ίϝϯτจ> := "//" [A-Z_ ]* "\n" ίϝϯτ͚ͩϓϩάϥϜ ద༻͞Εͨจ๏نଇ จ͸͜ͷ͏ͪͷͲΕ͔ͭ // COMMENT ↩︎ EOF

Slide 72

Slide 72 text

<ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ίϝϯτจ> := "//" [A-Z_ ]* "\n" ίϝϯτ͚ͩϓϩάϥϜ ద༻͞Εͨจ๏نଇ ࠓճͷจ͸ίϝϯτจ // COMMENT ↩︎ EOF

Slide 73

Slide 73 text

<ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ίϝϯτจ> := "//" [A-Z_ ]* "\n" ίϝϯτจͷத਎Λݟʹ͍͘ ίϝϯτ͚ͩϓϩάϥϜ ద༻͞Εͨจ๏نଇ // COMMENT ↩︎ EOF

Slide 74

Slide 74 text

<ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ίϝϯτจ> := "//" [A-Z_ ]* "\n" ʹଓ͍ͯӳେจࣈͱ@ͱۭന͕Կճ͔ଓ͍ͯɺվߦͰऴΘΔ ίϝϯτ͚ͩϓϩάϥϜ ద༻͞Εͨจ๏نଇ // COMMENT ↩︎ EOF

Slide 75

Slide 75 text

// COMMENT ↩︎ EOF <ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ίϝϯτจ> := "//" [A-Z_ ]* "\n" ίϝϯτ͚ͩϓϩάϥϜ ద༻͞Εͨจ๏نଇ

Slide 76

Slide 76 text

// COMMENT ↩︎ EOF <ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ίϝϯτจ> := "//" [A-Z_ ]* "\n" ίϝϯτ͚ͩϓϩάϥϜ ద༻͞Εͨจ๏نଇ ίʔυͱͷରԠ͕Ͱ͖ͨΒɺݟͨॱ൪ΛٯʹḪ͍ͬͯ͘

Slide 77

Slide 77 text

// COMMENT ↩︎ EOF <ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ίϝϯτจ> := "//" [A-Z_ ]* "\n" จ΋ίϝϯτจͰରԠ͕औΕͨͷͰḪΔ ίϝϯτ͚ͩϓϩάϥϜ ద༻͞Εͨจ๏نଇ

Slide 78

Slide 78 text

<ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ίϝϯτจ> := "//" [A-Z_ ]* "\n" // COMMENT EOF ࠓճͷจ͸ճ܁Γฦ͚ͩ͠Ͱɺத਎͸ίϝϯτจ ίϝϯτ͚ͩϓϩάϥϜ ద༻͞Εͨจ๏نଇ

Slide 79

Slide 79 text

<ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ίϝϯτจ> := "//" [A-Z_ ]* "\n" // COMMENT EOF ࠷ޙ͸&0'ͰऴΘΔ ίϝϯτ͚ͩϓϩάϥϜ ద༻͞Εͨจ๏نଇ

Slide 80

Slide 80 text

͜͜·ͰಡΊΕ͹ɺଞͷίʔυͷ
 จ๏نଇ΋ಡΊΔΑ͏ʹͳΔ

Slide 81

Slide 81 text

print("TEXT") EOF ؔ਺ݺͼग़͚ͩ͠ϓϩάϥϜ ద༻͞Εͨจ๏نଇ <ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ࣜจ> := <ࣜ> "\n" <ࣜ> := <จࣈྻϦςϥϧ> | <ؔ਺ݺͼग़ࣜ͠> <ؔ਺ݺͼग़͠> := <ؔ਺໊> "(" <ࣜ> ")" <ؔ਺໊> := [a-z] [a-z]*

Slide 82

Slide 82 text

print("TEXT") EOF ؔ਺ݺͼग़͚ͩ͠ϓϩάϥϜ ద༻͞Εͨจ๏نଇ <ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ࣜจ> := <ࣜ> "\n" <ࣜ> := <จࣈྻϦςϥϧ> | <ؔ਺ݺͼग़ࣜ͠> <ؔ਺ݺͼग़͠> := <ؔ਺໊> "(" <ࣜ> ")" <ؔ਺໊> := [a-z] [a-z]* ಉ͡Α͏ʹݟ͍͖ͯ·͠ΐ͏

Slide 83

Slide 83 text

print("TEXT") EOF ؔ਺ݺͼग़͚ͩ͠ϓϩάϥϜ ద༻͞Εͨจ๏نଇ <ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> <ࣜจ> := <ࣜ> "\n" <ࣜ> := <จࣈྻϦςϥϧ> | <ؔ਺ݺͼग़ࣜ͠> <ؔ਺ݺͼग़͠> := <ؔ਺໊> "(" <ࣜ> ")" <ؔ਺໊> := [a-z] [a-z]* <จࣈྻϦςϥϧ>

Slide 84

Slide 84 text

EOF ۭͷϓϩάϥϜ ద༻͞Εͨจ๏نଇ <ϓϩάϥϜ> := <จ>* EOF ࣮͸͜Ε΋จ๏نଇ্͸ଥ౰ͳϓϩάϥϜ

Slide 85

Slide 85 text

EOF ۭͷϓϩάϥϜ ద༻͞Εͨจ๏نଇ <ϓϩάϥϜ> := <จ>* EOF ܁Γฦ͠ճ

Slide 86

Slide 86 text

ෆਖ਼ͳϓϩάϥϜ΋ΈͯΈΑ͏

Slide 87

Slide 87 text

/ INVALID EOF ෆਖ਼ͳϓϩάϥϜ ద༻͞Εͨจ๏نଇ ద༻Ͱ͖Δจ๏نଇͳ͠

Slide 88

Slide 88 text

/ INVALID EOF ෆਖ਼ͳϓϩάϥϜ ద༻͞Εͨจ๏نଇ ͳ͠ ͜ͷίʔυ͸ϓϩάϥϜͷจͷ͍ͣΕʹ΋
 ͋ͯ͸·Βͳ͍ͷͰɺϓϩάϥϜʹ͋ͯ͸·Βͳ͍ ͜ͷঢ়گΛʮߏจΤϥʔʢTZOUBYFSSPSʣʯͱ͍͏

Slide 89

Slide 89 text

จ๏نଇ·ͱΊ w จ๏نଇ͸۩ମྫΛߟ͑ΔͱΘ͔Γ΍͍͢ w จ๏نଇʹ͋ͯ͸·Βͳ͍ͱ͖ߏจΤϥʔʹͳΔ

Slide 90

Slide 90 text

ߏจղੳͷ࣮૷ ͖ͬ͞ͷจ๏نଇʹରԠ͢Δ

Slide 91

Slide 91 text

 จ๏نଇͷࠨଆʢͷ෦෼ʣʹ
 ରԠ͢Δந৅ߏจ໦ͷϊʔυΛఆٛ͢Δ  ఆٛͨ͠ϊʔυ͝ͱʹղੳؔ਺Λ༻ҙ͢Δ ߏจղੳͷ࣮૷खॱ

Slide 92

Slide 92 text

<ϓϩάϥϜ> := <จ>* EOF <จ> := | <ࣜจ> | <ίϝϯτจ> := "if " <ࣜ> " {\n" <จ>* "}" "\n" <ࣜจ> := <ࣜ> "\n" <ίϝϯτจ> := "//" [A-Z_ ]* "\n" <ࣜ> := <จࣈྻϦςϥϧ> | <ؔ਺ݺͼग़ࣜ͠> <จࣈྻϦςϥϧ> := "'" ("\'" | [A-Z_ ])* "'" <ؔ਺ݺͼग़ࣜ͠> := <ؔ਺໊> "(" <ࣜ> ")" <ؔ਺໊> := [a-z] [a-z]* ͜ͷ͝ͱʹந৅ߏจ໦ͷϊʔυΛఆٛ͢Δ

Slide 93

Slide 93 text

1SPHSBN 4UBUFNFOU 4UBUFNFOU # <ϓϩάϥϜ> := <จ>* class ProgramNode(Node): def __init__(self, statement_nodes): # <ϓϩάϥϜ>͸ෳ਺ͷ<จ>͔ΒͳΔͷͰɺ # ؚ·ΕΔ<จ>Λ഑ྻͰอ࣋͢Δɻ self.statements = statement_nodes ϓϩάϥϜʹରԠ͢Δந৅ߏจ໦ͷϊʔυ จͷϊʔυͷ഑ྻ

Slide 94

Slide 94 text

# <ϓϩάϥϜ> := <จ>* class ProgramNode(Node): def __init__(self, statement_nodes): # <ϓϩάϥϜ>͸ෳ਺ͷ<จ>͔ΒͳΔͷͰɺ # ؚ·ΕΔ<จ>Λ഑ྻͰอ࣋͢Δɻ self.statements = statement_nodes 4UBUFNFOU 4UBUFNFOU 1SPHSBN

Slide 95

Slide 95 text

# <ϓϩάϥϜ> := <จ>* class ProgramNode(Node): def __init__(self, statement_nodes): # <ϓϩάϥϜ>͸ෳ਺ͷ<จ>͔ΒͳΔͷͰɺ # ؚ·ΕΔ<จ>Λ഑ྻͰอ࣋͢Δɻ self.statements = statement_nodes 1SPHSBN 4UBUFNFOU 4UBUFNFOU

Slide 96

Slide 96 text

# := "if " <ࣜ> " {\n" จ* "}" "\n" class IfStatementNode(Node): def __init__(self, condition_node, then_statements): # if ͷޙͷ৚݅෦ͷ <ࣜ> Λอ࣋͢Δɻ self.condition_node = condition_node # { ͱ } ͷؒͷෳ਺ͷ <จ> Λ഑ྻͱͯ͠อ࣋͢Δɻ self.then_statements = then_statements JGจʹରԠ͢Δந৅ߏจ໦ͷϊʔυ

Slide 97

Slide 97 text

ಉ༷ʹ͢΂ͯͷʹରԠ͢Δ
 ந৅ߏจ໦ͷϊʔυΛఆٛ͠·͢

Slide 98

Slide 98 text

͢΂ͯͷϊʔυΛఆٛ͠ऴΘͬͨΒɺ
 ͜ΕΛ࡞੒͢Δؔ਺Λॻ͍͍ͯ͘

Slide 99

Slide 99 text

ʹରԠ͢Δؔ਺ͷҾ਺ͱ໭Γ஋ʹ͸ɺ
 Α͋͘Δఆ൪ͷύλʔϯ͕͋Δ ͜ͷύλʔϯʹै͏ͱɺؔ਺Λ
 ૊Έ߹Θͤ΍͘͢ͳΔͷͰ͓֮͑ͯ͜͏

Slide 100

Slide 100 text

͍͖ͳΓϓϩάϥϜʹରԠ͢Δؔ਺Λ
 ॻ͘ͱઆ໌͕೉͍͠ͷͰɺίϝϯτจʹ
 ରԠ͢Δؔ਺͔Βઆ໌͢Δ

Slide 101

Slide 101 text

# <ίϝϯτจ> := "//" [A-Z_ ]* "\n" def parse_comment_statement(text, index): # TODO: ͪΌΜͱ࣮૷͢Δ next_index = 1234 # TODO: Ծͷ࣮૷ node = CommentStatementNode( comment_content=" COMMENT" # TODO: Ծͷ࣮૷ ) return node, next_index ίϝϯτจʹରԠ͢Δؔ਺ͷҾ਺ͱ໭Γ஋Λ֬ೝ͠Α͏ ؔ਺ͷ಺෦͸·ͩԾͷ΋ͷͰɺ͋ͱͰ࣮૷͍ͯ͘͠

Slide 102

Slide 102 text

# <ίϝϯτจ> := "//" [A-Z_ ]* "\n" def parse_comment_statement(text, index): # TODO: ͪΌΜͱ࣮૷͢Δ next_index = 1234 # TODO: Ծͷ࣮૷ node = CommentStatementNode( comment_content=" COMMENT" # TODO: Ծͷ࣮૷ ) return node, next_index ʮQBSTFʯ͸ʮߏจղੳ͢Δʯͷҙຯ

Slide 103

Slide 103 text

# <ίϝϯτจ> := "//" [A-Z_ ]* "\n" def parse_comment_statement(text, index): # TODO: ͪΌΜͱ࣮૷͢Δ next_index = 1234 # TODO: Ծͷ࣮૷ node = CommentStatementNode( comment_content=" COMMENT" # TODO: Ծͷ࣮૷ ) return node, next_index ղੳ͍ͨ͠ςΩετશମ ղੳ͍ͨ͠ςΩετͷҐஔ

Slide 104

Slide 104 text

# <ίϝϯτจ> := "//" [A-Z_ ]* "\n" def parse_comment_statement(text, index): # TODO: ͪΌΜͱ࣮૷͢Δ next_index = 1234 # TODO: Ծͷ࣮૷ node = CommentStatementNode( comment_content=" COMMENT" # TODO: Ծͷ࣮૷ ) return node, next_index ղੳͰ͖ͨίϝϯτจʹ
 ରԠ͢Δந৅ߏจ໦ͷϊʔυ ίϝϯτจ͕ऴΘͬͨҐஔ

Slide 105

Slide 105 text

ͱΓ͋͑ͣؔ਺ͷ࢖ΘΕํΛΈͯΈΑ͏

Slide 106

Slide 106 text

(comment_node, next_index) = parse_comment_statement("// COMMENT\n", 0) ϓϩάϥϜͷઌ಄͔Βղੳ͢Δύλʔϯ ઌ಄ͳͷͰJOEFY͸ ղੳ͕ऴΘͬͨҐஔ ίϝϯτจʹରԠ͢Δந৅ߏจ໦ͷϊʔυ

Slide 107

Slide 107 text

(comment_node, next_index) = parse_comment_statement("'123'\n// COMMENT\n", 6) ϓϩάϥϜͷ్த͔Βղੳ͢Δύλʔϯ ղੳ͕ऴΘͬͨҐஔ ్தͷจࣈ໨͔Βղੳ͢Δ ίϝϯτจʹରԠ͢Δந৅ߏจ໦ͷϊʔυ

Slide 108

Slide 108 text

(comment_node, next_index) = parse_comment_statement("'123'\n/ INVALID", 6) ղੳʹࣦഊ͢Δύλʔϯ ࣦഊͨ͠ΒҐஔ͸ಈ͔͞ͳ͍Ͱͷ··ʹ͢Δ ͜ͷΑ͏ʹɺࣦഊͨ͠ΒԿ΋ͳ͔ͬͨΑ͏ʹ
 ר͖໭Δ͜ͱΛʮόοΫτϥοΫʯͱݺͿ ղੳʹࣦഊͨ͠ͷͰ/POF ్தͷจࣈ໨͔Βղੳ͢Δ

Slide 109

Slide 109 text

Ҿ਺ w ղੳ͢Δจࣈྻશମͱ࢝ΊΔҐஔ ໭Γ஋ w ղੳͰ͖ͨந৅ߏจ໦ͷϊʔυͱऴΘͬͨҐஔ w ࣦഊͨ͠Β/POFΛฦͯ͠ɺ
 Ґஔ͸ಈ͔͞ͳ͍ ͜͜ͰҾ਺ͱ໭Γ஋Λ੔ཧ͠Α͏ɿ

Slide 110

Slide 110 text

Ҿ਺ w ղੳ͢Δจࣈྻશମͱ࢝ΊΔҐஔ ໭Γ஋ w ղੳͰ͖ͨந৅ߏจ໦ͷϊʔυͱऴΘͬͨҐஔ w ࣦഊͨ͠Β/POFΛฦͯ͠ɺ
 Ґஔ͸ಈ͔͞ͳ͍ ͜͜ͰҾ਺ͱ໭Γ஋Λ੔ཧ͠Α͏ɿ ؔ਺͕૊Έ߹Θͤ΍͘͢ͳΔͱ
 ݴ͍ͬͯͨͷ͸͜ͷ෦෼ લͷؔ਺ʹΑΔղੳ͕ऴΘͬͨ
 Ґஔ͔Βɺ࣍ͷؔ਺ʹΑΔղੳΛ
 ࠶։͢ΔΠϝʔδ

Slide 111

Slide 111 text

࣮ࡍͷॲཧͷྲྀΕΛΈͯΈΑ͏ Ҿ਺ͱ໭Γ஋͕ͳΜͱͳ͘Θ͔ͬͨͷͰ

Slide 112

Slide 112 text

<ίϝϯτจ> := "//" [A-Z_ ]* "\n" ίϝϯτจͷจ๏نଇͷಡΈํͷ͓͞Β͍ɿ  ͸͡Ίʹ͕͋Δ  ଓ͚ͯӳେจࣈ͔@͔ۭന͕ճҎ্ଓ͘  ࠷ޙʹվߦ͕͋Δ

Slide 113

Slide 113 text

def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index <ίϝϯτจ> := "//" [A-Z_ ]* "\n"

Slide 114

Slide 114 text

def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index <ίϝϯτจ> := "//" [A-Z_ ]* "\n" ίϝϯτจʹରԠ͢Δؔ਺

Slide 115

Slide 115 text

def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index ͜͜Ͱ͸͕JOEFYͷҐஔʹ͋Δ͔Ͳ͏͔֬ೝ͍ͯ͠Δ FYQFDU@LFZXPSE͸ޙͰઆ໌͢Δ͕ɺΛݟ͚ͭͨΒ
 JOEFYΛͷޙ·ͰҠಈͤ͞Δ <ίϝϯτจ> := "//" [A-Z_ ]* "\n"

Slide 116

Slide 116 text

def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index ͕Έ͔ͭΒͳ͚Ε͹ίϝϯτจͰ͸ͳ͍ͷͰऴྃ <ίϝϯτจ> := "//" [A-Z_ ]* "\n"

Slide 117

Slide 117 text

def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index ͜ͷ഑ྻʹίϝϯτ಺ͷจࣈΛ֨ೲ͍ͯ͘͠ <ίϝϯτจ> := "//" [A-Z_ ]* "\n"

Slide 118

Slide 118 text

def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index ίϝϯτ಺ͷจࣈ͸܁Γฦ͠ͳͷͰɺϧʔϓͰॲཧ͢Δ <ίϝϯτจ> := "//" [A-Z_ ]* "\n"

Slide 119

Slide 119 text

def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index JOEFYͷҐஔʹ<";@>͕͋Δ͔֬ೝ͍ͯ͠Δ FYQFDU@FJUIFSʹ͍ͭͯ͸ޙͰઆ໌͢Δ <ίϝϯτจ> := "//" [A-Z_ ]* "\n"

Slide 120

Slide 120 text

def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index ΋͠<";@>ʹҰக͠ͳ͔ͬͨΒɺίϝϯτͷ
 ಺༰෦෼͕ऴΘͬͨͷͰɺϧʔϓ͔Β୤ग़ <ίϝϯτจ> := "//" [A-Z_ ]* "\n"

Slide 121

Slide 121 text

def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index ΋͠<";@>Ͱ͋Ε͹ɺίϝϯτจࣈྻ͕·ͩଓ͔͘΋
 ͠Εͳ͍ͷͰɺจࣈΛه࿥ͯ͠ϧʔϓΛ࠶։ <ίϝϯτจ> := "//" [A-Z_ ]* "\n"

Slide 122

Slide 122 text

def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index ίϝϯτ಺ͷจࣈ͕ऴΘͬͨͷͰɺ࠷ޙʹ
 վߦ͕͋Δ͔Ͳ͏͔֬ೝ͍ͯ͠Δ <ίϝϯτจ> := "//" [A-Z_ ]* "\n"

Slide 123

Slide 123 text

def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index aO͕ͳ͚Ε͹ɺίϝϯτจͰ͸ͳ͍ͷͰ/POFͱ
 ݩͷJOEFYΛฦ͢ <ίϝϯτจ> := "//" [A-Z_ ]* "\n"

Slide 124

Slide 124 text

def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index ه࿥͓͍ͯͨ͠ίϝϯτ಺ͷจࣈΛ݁߹ͯ͠ɺ
 ίϝϯτͷ಺༰จࣈྻΛ෮ݩ͢Δ <ίϝϯτจ> := "//" [A-Z_ ]* "\n"

Slide 125

Slide 125 text

def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index ෮ݩͨ͠ίϝϯτจࣈྻ͔ΒίϝϯτจʹରԠ͢Δ
 ந৅ߏจ໦ͷϊʔυΛ࡞੒ͯ͠ɺਐΊͨJOEFYͱฦ͢ <ίϝϯτจ> := "//" [A-Z_ ]* "\n"

Slide 126

Slide 126 text

<ίϝϯτจ> := "//" [A-Z_ ]* "\n" def parse_comment_statement(text, index): is_success, next_index = expect_keyword("//", text, index) if not is_success: return None, index comment_content_chars = [] while True: comment_content_char, next_index = \ expect_either(uppercase + [" ", "_"], text, next_index) if comment_content_char is None: break comment_content_chars.append(comment_content_char) is_success, next_index = expect_keyword("\n", text, next_index) if not is_success: return None, index comment_content_chars = "".join(comment_content_chars) return CommentStatementNode(comment_content_chars), next_index ίϝϯτจʹରԠ͢Δؔ਺Λॻ͚ͨ

Slide 127

Slide 127 text

FYQFDUdͳؔ਺ͷ͸ͨΒ͖ ్தͰͰ͖ͯͨFYQFDUd͕ؾʹͳΔํ΁

Slide 128

Slide 128 text

ઌ΄ͲͷQBSTF@DPNNFOU@TUBUFNFOUͷ࣮૷࣌ʹ
 ͋Γ͕ͪͳϛε͕ɺJOEFYͷਐΊ๨Ε΍ਐΊ෯ͷؒҧ͍ FYQFDU@LFZXPSE΍FYQFDU@FJUIFS͸͜ΕΒͷؒҧ͍Λ
 ༧๷͢ΔͨΊͷϢʔςΟϦςΟؔ਺

Slide 129

Slide 129 text

text = "abc" is_success, next_index = expect_keyword("a", text, 0) is_success, next_index = expect_keyword("x", text, 0) Bͷ࣍ͷJOEFYͳͷͰ JOEFYͷҐஔʢͳͷͰઌ಄ʣʹB͕͋ΔͷͰ5SVF ͳ͍৔߹͸JOEFYΛม͑ͳ͍ͷͰ JOEFYͷҐஔʢͳͷͰઌ಄ʣʹY͸ͳ͍ͷͰ'BMTF

Slide 130

Slide 130 text

ൺֱͨ͠จࣈྻͷ௕͚ͩ͞JOEFYΛਐΊΔͷͰɺ
 ਐΊ෯ͷؒҧ͍ͱਐΊ๨ΕΛ๷͛Δ ศརʜ

Slide 131

Slide 131 text

def expect_keyword(expected, text, index): expected_len = len(expected) actual = text[index:index+expected_len] if actual != expected: return False, index return True, index + expected_len def expect_either(expected_list, text, index): for expected in expected_list: is_success, next_index = expect_keyword(expected, text, index) if is_success: return expected, next_index return None, index

Slide 132

Slide 132 text

def expect_keyword(expected, text, index): expected_len = len(expected) actual = text[index:index+expected_len] if actual != expected: return False, index return True, index + expected_len def expect_either(expected_list, text, index): for expected in expected_list: is_success, next_index = expect_keyword(expected, text, index) if is_success: return expected, next_index return None, index ৄࡉͳ࣮૷͸͋ͱͰղಡͯ͠Έ͍ͯͩ͘͞ʂ

Slide 133

Slide 133 text

͜͜·ͰͰίϝϯτจͷ
 ղੳؔ਺Λ࣮૷Ͱ͖ͨ

Slide 134

Slide 134 text

࣍ʹɺจʹର͢Δؔ਺͔Βઌ΄Ͳ
 ࣮૷ͨ͠ίϝϯτจʹରԠ͢Δؔ਺Λ
 ࢖͏ํ๏ΛΈͯΈΑ͏ ϙΠϯτ͸ɺจ๏نଇͷͷӈଆʹ͕
 ͋ͬͨΒରԠ͢Δղੳؔ਺ʹ೚ͤΔ͜ͱ

Slide 135

Slide 135 text

<จ> := | <ࣜจ> | <ίϝϯτจ> จͷจ๏نଇͷಡΈํͷ͓͞Β͍ɿ จ͸ɺJGจɺࣜจɺίϝϯτจͷ͍ͣΕ͔

Slide 136

Slide 136 text

def parse_statement(text, index): if_statement_node, next_index = parse_if_statement(text, index) if if_statement_node is not None: return if_statement_node, next_index expr_statement_node, next_index = parse_expr_statement(text, index) if expr_statement_node is not None: return expr_statement_node, next_index comment_statement_node, next_index = parse_comment_statement(text, index) if comment_statement_node is not None: return comment_statement_node, next_index return None, index <จ> := | <ࣜจ> | <ίϝϯτจ>

Slide 137

Slide 137 text

def parse_statement(text, index): if_statement_node, next_index = parse_if_statement(text, index) if if_statement_node is not None: return if_statement_node, next_index expr_statement_node, next_index = parse_expr_statement(text, index) if expr_statement_node is not None: return expr_statement_node, next_index comment_statement_node, next_index = parse_comment_statement(text, index) if comment_statement_node is not None: return comment_statement_node, next_index return None, index ·ͣɺJGจʹରԠ͢Δؔ਺ͰղੳͰ͖Δ͔Ͳ͏͔ࢼ͢ <จ> := | <ࣜจ> | <ίϝϯτจ>

Slide 138

Slide 138 text

def parse_statement(text, index): if_statement_node, next_index = parse_if_statement(text, index) if if_statement_node is not None: return if_statement_node, next_index expr_statement_node, next_index = parse_expr_statement(text, index) if expr_statement_node is not None: return expr_statement_node, next_index comment_statement_node, next_index = parse_comment_statement(text, index) if comment_statement_node is not None: return comment_statement_node, next_index return None, index ΋͠ɺJGจͱͯ͠ͷղੳʹ੒ޭ͢Ε͹จ͸JGจͩͬͨͱ͍͏͜ͱ JGจʹରԠ͢Δந৅ߏจ໦ͱɺJGจͷղੳͰਐΜͩJOEFYΛฦ͢ <จ> := | <ࣜจ> | <ίϝϯτจ>

Slide 139

Slide 139 text

def parse_statement(text, index): if_statement_node, next_index = parse_if_statement(text, index) if if_statement_node is not None: return if_statement_node, next_index expr_statement_node, next_index = parse_expr_statement(text, index) if expr_statement_node is not None: return expr_statement_node, next_index comment_statement_node, next_index = parse_comment_statement(text, index) if comment_statement_node is not None: return comment_statement_node, next_index return None, index JGจͱͯ͠ͷղੳʹࣦഊͨ͠Βɺ࣍ʹࣜจͱͯ͠ͷղੳΛࢼ͢ <จ> := | <ࣜจ> | <ίϝϯτจ>

Slide 140

Slide 140 text

def parse_statement(text, index): if_statement_node, next_index = parse_if_statement(text, index) if if_statement_node is not None: return if_statement_node, next_index expr_statement_node, next_index = parse_expr_statement(text, index) if expr_statement_node is not None: return expr_statement_node, next_index comment_statement_node, next_index = parse_comment_statement(text, index) if comment_statement_node is not None: return comment_statement_node, next_index return None, index ΋͠ɺࣜจͱͯ͠ͷղੳʹ੒ޭ͢Ε͹จ͸ࣜจͩͬͨͱ͍͏͜ͱ ࣜจʹରԠ͢Δந৅ߏจ໦ͱɺࣜจͷղੳͰਐΜͩJOEFYΛฦ͢ <จ> := | <ࣜจ> | <ίϝϯτจ>

Slide 141

Slide 141 text

def parse_statement(text, index): if_statement_node, next_index = parse_if_statement(text, index) if if_statement_node is not None: return if_statement_node, next_index expr_statement_node, next_index = parse_expr_statement(text, index) if expr_statement_node is not None: return expr_statement_node, next_index comment_statement_node, next_index = parse_comment_statement(text, index) if comment_statement_node is not None: return comment_statement_node, next_index return None, index ࣜจͱͯ͠ͷղੳʹ΋ࣦഊͨ͠Βɺ࠷ޙʹίϝϯτจͱͯ͠ͷղੳΛࢼ͢ <จ> := | <ࣜจ> | <ίϝϯτจ>

Slide 142

Slide 142 text

def parse_statement(text, index): if_statement_node, next_index = parse_if_statement(text, index) if if_statement_node is not None: return if_statement_node, next_index expr_statement_node, next_index = parse_expr_statement(text, index) if expr_statement_node is not None: return expr_statement_node, next_index comment_statement_node, next_index = parse_comment_statement(text, index) if comment_statement_node is not None: return comment_statement_node, next_index return None, index ΋͠ɺίϝϯτจͱͯ͠ͷղੳʹ੒ޭ͢Ε͹จ͸ίϝϯτจͩͬͨͱ͍͏͜ͱ ίϝϯτจʹରԠ͢Δந৅ߏจ໦ͱɺίϝϯτจͷղੳͰਐΜͩJOEFYΛฦ͢ <จ> := | <ࣜจ> | <ίϝϯτจ>

Slide 143

Slide 143 text

def parse_statement(text, index): if_statement_node, next_index = parse_if_statement(text, index) if if_statement_node is not None: return if_statement_node, next_index expr_statement_node, next_index = parse_expr_statement(text, index) if expr_statement_node is not None: return expr_statement_node, next_index comment_statement_node, next_index = parse_comment_statement(text, index) if comment_statement_node is not None: return comment_statement_node, next_index return None, index JGจɺࣜจɺίϝϯτจͷ͍ͣΕͰ΋ͳ͚Ε͹ɺ
 จͰ͸ͳ͍ͷͰɺ/POFͱݩͷJOEFYΛฦͯ͠ऴྃ <จ> := | <ࣜจ> | <ίϝϯτจ>

Slide 144

Slide 144 text

def parse_statement(text, index): if_statement_node, next_index = parse_if_statement(text, index) if if_statement_node is not None: return if_statement_node, next_index expr_statement_node, next_index = parse_expr_statement(text, index) if expr_statement_node is not None: return expr_statement_node, next_index comment_statement_node, next_index = parse_comment_statement(text, index) if comment_statement_node is not None: return comment_statement_node, next_index return None, index <จ> := | <ࣜจ> | <ίϝϯτจ> ͜ͷΑ͏ʹʹରԠ͢Δؔ਺Λఆ͍ٛͯ͘͠ͱɺ
 ࠷ऴతʹϓϩάϥϜʹରԠ͢Δؔ਺ΛఆٛͰ͖Δ ͜ͷϓϩάϥϜʹରԠ͢Δؔ਺͕ɺҰൠతʹ
 ఏڙ͞Ε͍ͯΔߏจղੳثͱݺ͹ΕΔ΋ͷ

Slide 145

Slide 145 text

ࠓճͷઆ໌Ͱ৮Εͳ͔ͬͨ͜ͱ w ࣮༻తͳߏจղੳثʹ͢Δʹ͸ɺந৅ߏจ໦΍
 ߏจΤϥʔʹίʔυ্ͷҐஔ৘ใΛؚΊͨํ͕Α͍ w όοΫτϥοΫ͋Γͷ࣮૷͸ɺ୯७͔͔ͭͳΓ޿͍ൣғͷ
 จ๏نଇΛղੳͰ͖Δ͕ɺܭࢉྔ͸େ͖͍ w ࣮͸Ұ൪೉͍͠ͷ͸όάͷͳ͍จ๏نଇΛߟ͑Δ͜ͱ w όά͕͋Δͱߏจղੳث͕ແݶϧʔϓͨ͠Γ͢Δ

Slide 146

Slide 146 text

ૉ௚ͳ࣮૷ͷ·ͱΊ w ࣮૷͸ҎԼͷεςοϓͰͰ͖Δɿ w ʹରԠ͢Δந৅ߏจ໦Λఆٛ͢Δ w ʹରԠ͢Δؔ਺Λఆٛ͢Δ w จ๏نଇͷӈଆʹ͕͋Δ৔߹͸ɺ
 ͦͷʹରԠ͢Δؔ਺ʹղੳΛ೚ͤΔ

Slide 147

Slide 147 text

1BSTFS$PNCJOBUPSͷҖྗ ΋ͬͱΤϨΨϯτͳํ๏Λνϥݟͤ

Slide 148

Slide 148 text

ࠓճ঺հͨ͠ૉ௚ͳ࣮૷Λ1BSTFS$PNCJOBUPSͰ࣮૷͢Δͱɺ
 ಉ͡ॲཧͳͷʹڻ͘΄Ͳ࣮૷͕୹͘ͳΓɺ͔ͭ࠶ར༻ੑ্͕͕Δɿ parse_comment = sequence( string("//"), sequence( many(char(uppercase + ["_", " "])), string("\n") ) ) ؾʹͳΔਓ͸ɺεϥΠυ຤ඌͷࢀߟจݙ#Λࢀর

Slide 149

Slide 149 text

ߏจղੳͷ·ͱΊ w ߏจղੳ͸ίʔυΛղੳͯ͠ந৅ߏจ໦Λ
 ࡞੒͢Δॲཧ w ͞·͟·ͳߏจղੳͷΞϧΰϦζϜ͕͋Δ w ࠓճ͸όοΫτϥοΫ͋Γͷ
 ࠶ؼԼ߱෼ੳΛૉ௚ʹ࣮૷ͨ͠

Slide 150

Slide 150 text

ந৅ߏจ໦Λॲཧ͢Δ
 ୅දతͳ࣮૷ύλʔϯ ߏจղੳͷ͓࣍͸

Slide 151

Slide 151 text

͜Ε·Ͱ͸ɺந৅ߏจ໦ͷ֓ཁ΍࡞੒ํ๏ΛΈ͖ͯͨ ࣍ʹɺ͜͜Ͱ͸ந৅ߏจ໦Λ͔͋ͭ͏୅දతͳ
 ࣮૷ύλʔϯΛ঺հ͢Δ ΋ͬͱ΋සൟʹ࢖͏࣮૷ύλʔϯͱͯ͠ɺந৅ߏจ໦Λ
 ॱ൪ʹ୳ࡧ͍ͯ͘͠૸ࠪؔ਺Λ঺հ͢Δ

Slide 152

Slide 152 text

૸ࠪؔ਺ ந৅ߏจ໦Λ͔͋ͭ͏୅දతύλʔϯ

Slide 153

Slide 153 text

૸ࠪؔ਺͸ɺந৅ߏจ໦ͷϊʔυΛॱʹḷ͍ͬͯͬͯɺ
 ϊʔυʹ๚ΕΔ཭ΕΔͨͼʹॲཧΛ࣮ߦ͢Δؔ਺ traverse(node, on_enter, on_leave) PO@FOUFSͱPO@MFBWF͸ͲͪΒ΋ؔ਺Λ౉͢ ϊʔυʹ๚ΕΔ཭ΕΔͱ࣮ߦ͞ΕΔ Կ͕ى͜Δ͔Θ͔ΓͮΒ͍ͷͰਤղ͠·͢

Slide 154

Slide 154 text

def print_enter(node): print("enter: {node}".format(node=type(node))) def print_leave(node): print("leave: {node}".format(node=type(node))) traverse(node, print_enter, print_leave) PO@FOUFSͱPO@MFBWF͕Θ͔ΔΑ͏ʹQSJOU͢Δؔ਺Λ༻ҙ

Slide 155

Slide 155 text

͜ͷUSBWFSTFʹΑͬͯQSJOU͞ΕΔ݁ՌΛΈͯΈ·͠ΐ͏ QSJOU݁Ռ 1SPHSBN *G4UBUFNFOU 4USJOH-JUFSBM 'VOD$BMM *EFOUJpFS $PNNFOU

Slide 156

Slide 156 text

*G4UBUFNFOU 4USJOH-JUFSBM 'VOD$BMM *EFOUJpFS $PNNFOU 1SPHSBN ·ͣ͸1SPHSBNʹ๚ΕΔʢFOUFS1SPHSBNΛQSJOUʣ FOUFS1SPHSBN QSJOU݁Ռ

Slide 157

Slide 157 text

1SPHSBN 4USJOH-JUFSBM 'VOD$BMM *EFOUJpFS $PNNFOU *G4UBUFNFOU ࣍ʹ1SPHSBNͷࢠͰ͋Δ*G4UBUFNFOU΁๚ΕΔ FOUFS1SPHSBN FOUFS*G4UBUFNFOU QSJOU݁Ռ

Slide 158

Slide 158 text

1SPHSBN *G4UBUFNFOU 4USJOH-JUFSBM *EFOUJpFS $PNNFOU 'VOD$BMM ࣍ʹ*G4UBUFNFOUͷࢠͰ͋Δ'VOD$BMMΛ๚ΕΔ FOUFS1SPHSBN FOUFS*G4UBUFNFOU FOUFS'VOD$BMM QSJOU݁Ռ

Slide 159

Slide 159 text

1SPHSBN *G4UBUFNFOU 4USJOH-JUFSBM 'VOD$BMM $PNNFOU *EFOUJpFS QSJOU݁Ռ ࣍ʹ'VOD$BMMͷࢠͰ͋Δ*EFOUJpFSΛ๚ΕΔ FOUFS1SPHSBN FOUFS*G4UBUFNFOU FOUFS'VOD$BMM FOUFS*EFOUJpFS

Slide 160

Slide 160 text

1SPHSBN *G4UBUFNFOU 4USJOH-JUFSBM 'VOD$BMM $PNNFOU *EFOUJpFS QSJOU݁Ռ *EFOUJpFSʹࢠ͸͍ͳ͍ͷͰɺ*EFOUJpFS͔Β཭ΕΔ FOUFS1SPHSBN FOUFS*G4UBUFNFOU FOUFS'VOD$BMM FOUFS*EFOUJpFS MFBWF*EFOUJpFS

Slide 161

Slide 161 text

1SPHSBN *G4UBUFNFOU 'VOD$BMM $PNNFOU *EFOUJpFS 4USJOH-JUFSBM QSJOU݁Ռ 'VOD$BMMͷ࣍ͷࢠͰ͋Δ4USJOH-JUFSBMΛ๚ΕΔ FOUFS1SPHSBN FOUFS*G4UBUFNFOU FOUFS'VOD$BMM FOUFS*EFOUJpFS MFBWF*EFOUJpFS FOUFS4USJOH-JUFSBM

Slide 162

Slide 162 text

1SPHSBN *G4UBUFNFOU 'VOD$BMM $PNNFOU *EFOUJpFS 4USJOH-JUFSBM QSJOU݁Ռ 4USJOH-JUFSBMʹࢠ͸͍ͳ͍ͷͰɺ4USJOH-JUFSBM͔Β཭ΕΔ FOUFS1SPHSBN FOUFS*G4UBUFNFOU FOUFS'VOD$BMM FOUFS*EFOUJpFS MFBWF*EFOUJpFS FOUFS4USJOH-JUFSBM MFBWF4USJOH-JUFSBM

Slide 163

Slide 163 text

1SPHSBN *G4UBUFNFOU $PNNFOU *EFOUJpFS 4USJOH-JUFSBM 'VOD$BMM QSJOU݁Ռ 'VOD$BMMͷ͢΂ͯͷࢠΛ๚໰ͨ͠ͷͰɺ'VOD$BMM͔Β཭ΕΔ FOUFS1SPHSBN FOUFS*G4UBUFNFOU FOUFS'VOD$BMM FOUFS*EFOUJpFS MFBWF*EFOUJpFS FOUFS4USJOH-JUFSBM MFBWF4USJOH-JUFSBM MFBWF'VOD$BMM

Slide 164

Slide 164 text

1SPHSBN *G4UBUFNFOU *EFOUJpFS 4USJOH-JUFSBM 'VOD$BMM $PNNFOU QSJOU݁Ռ *G4UBUFNFOUͷ࣍ͷࢠͰ͋Δ$PNNFOUΛ๚ΕΔ FOUFS1SPHSBN FOUFS*G4UBUFNFOU FOUFS'VOD$BMM FOUFS*EFOUJpFS MFBWF*EFOUJpFS FOUFS4USJOH-JUFSBM MFBWF4USJOH-JUFSBM MFBWF'VOD$BMM FOUFS$PNNFOU

Slide 165

Slide 165 text

1SPHSBN *G4UBUFNFOU *EFOUJpFS 4USJOH-JUFSBM 'VOD$BMM $PNNFOU QSJOU݁Ռ $PNNFOUʹࢠ͸͍ͳ͍ͷͰɺ$PNNFOU͔Β཭ΕΔ FOUFS1SPHSBN FOUFS*G4UBUFNFOU FOUFS'VOD$BMM FOUFS*EFOUJpFS MFBWF*EFOUJpFS FOUFS4USJOH-JUFSBM MFBWF4USJOH-JUFSBM MFBWF'VOD$BMM FOUFS$PNNFOU MFBWF$PNNFOU

Slide 166

Slide 166 text

1SPHSBN *EFOUJpFS 4USJOH-JUFSBM 'VOD$BMM $PNNFOU *G4UBUFNFOU QSJOU݁Ռ *G4UBUFNFOUͷ͢΂ͯͷࢠΛ๚໰ͨ͠ͷͰɺ཭ΕΔ FOUFS1SPHSBN FOUFS*G4UBUFNFOU FOUFS'VOD$BMM FOUFS*EFOUJpFS MFBWF*EFOUJpFS FOUFS4USJOH-JUFSBM MFBWF4USJOH-JUFSBM MFBWF'VOD$BMM FOUFS$PNNFOU MFBWF$PNNFOU MFBWF*G4UBUFNFOU

Slide 167

Slide 167 text

*EFOUJpFS 4USJOH-JUFSBM 'VOD$BMM $PNNFOU *G4UBUFNFOU 1SPHSBN QSJOU݁Ռ 1SPHSBNͷ͢΂ͯͷࢠΛ๚໰ͨ͠ͷͰɺ૸ࠪ׬ྃ FOUFS1SPHSBN FOUFS*G4UBUFNFOU FOUFS'VOD$BMM FOUFS*EFOUJpFS MFBWF*EFOUJpFS FOUFS4USJOH-JUFSBM MFBWF4USJOH-JUFSBM MFBWF'VOD$BMM FOUFS$PNNFOU MFBWF$PNNFOU MFBWF*G4UBUFNFOU MFBWF1SPHSBN

Slide 168

Slide 168 text

*EFOUJpFS 4USJOH-JUFSBM 'VOD$BMM $PNNFOU *G4UBUFNFOU 1SPHSBN QSJOU݁Ռ ཁ͢Δʹɺந৅ߏจ໦Λਂ͞༏ઌ୳ࡧ͢Δؔ਺ FOUFS1SPHSBN FOUFS*G4UBUFNFOU FOUFS'VOD$BMM FOUFS*EFOUJpFS MFBWF*EFOUJpFS FOUFS4USJOH-JUFSBM MFBWF4USJOH-JUFSBM MFBWF'VOD$BMM FOUFS$PNNFOU MFBWF$PNNFOU MFBWF*G4UBUFNFOU MFBWF1SPHSBN

Slide 169

Slide 169 text

͜ͷΑ͏ͳந৅ߏจ໦Λ૸ࠪ͢Δؔ਺͕
 ༻ҙ͞Ε͍ͯΔͱɺ͞ΒʹޙͰ঺հ͢Δ
 ੩తݕࠪͷίʔυ͕ͱͯ΋ॻ͖΍͘͢ͳΔ

Slide 170

Slide 170 text

 ͢΂ͯͷந৅ߏจ໦ͷϊʔυʹɺࣗ਎ͷ
 ࢠͷҰཡΛฦؔ͢਺Λ௥Ճ͢Δ  ϊʔυΛ๚ΕͨΒͷࢠͷҰཡΛऔಘͯ͠ɺ
 ࠶ؼతʹ๚Ε͍ͯؔ͘਺Λ࣮૷͢Δ ૸ࠪؔ਺ͷ࣮૷खॱ

Slide 171

Slide 171 text

class Node: def children(self): raise NotImplementedError() class ProgramNode(Node): def __init__(self, statement_nodes): self.statements = statement_nodes def children(self): return self.statements ந৅ߏจ໦ͷϊʔυ͕ࣗ਎ͷࢠΛฦ͢Α͏ʹཁٻ͢ΔجఈΫϥεΛ༻ҙ

Slide 172

Slide 172 text

class Node: def children(self): raise NotImplementedError() class ProgramNode(Node): def __init__(self, statement_nodes): self.statements = statement_nodes def children(self): return self.statements ͦΕͧΕͷந৅ߏจ໦ͷϊʔυʹ࣮૷ͯ͠΋Β͏

Slide 173

Slide 173 text

class Node: def children(self): raise NotImplementedError() class ProgramNode(Node): def __init__(self, statement_nodes): self.statements = statement_nodes def children(self): return self.statements ϓϩάϥϜͷ͢΂ͯͷࢠͷҰཡΛ഑ྻͱͯ͠ฦ͢ ࠓճ͸จͷ഑ྻҎ֎ʹࢠ͸ͳ͍ͷͰͦͷ··ฦͤ͹Α͍

Slide 174

Slide 174 text

class IfStatementNode(Node): def __init__(self, condition_node, then_statements): self.condition_node = condition_node self.then_statements = then_statements def children(self): children = [self.condition_node] return children + self.then_statements ผͷέʔεͱͯ͠ɺJGจͷந৅ߏจ໦ͷϊʔυ΋ΈͯΈΑ͏

Slide 175

Slide 175 text

class IfStatementNode(Node): def __init__(self, condition_node, then_statements): self.condition_node = condition_node self.then_statements = then_statements def children(self): children = [self.condition_node] return children + self.then_statements JGจͷࢠ͸৚݅෦ͷࣜͱɺ\^ͷதͷ
 ෳ਺ͷจͳͷͰɺ·ͱΊͯҰཡʹͯ͠ฦ͢

Slide 176

Slide 176 text

class IfStatementNode(Node): def __init__(self, condition_node, then_statements): self.condition_node = condition_node self.then_statements = then_statements def children(self): children = [self.condition_node] return children + self.then_statements ಉ༷ʹɺ͢΂ͯͷந৅ߏจ໦ͷϊʔυʹDIJMESFOΛ࣮૷ͤ͞Δ

Slide 177

Slide 177 text

४උ͕੔ͬͨͷͰɺ૸ࠪؔ਺ͷ
 ຊମΛ࣮૷͍ͯ͘͠

Slide 178

Slide 178 text

def traverse(node, on_enter=None, on_leave=None): if on_enter is not None: on_enter(node) for child in node.children(): traverse(child, on_enter, on_leave) if on_leave is not None: on_leave(node)

Slide 179

Slide 179 text

def traverse(node, on_enter=None, on_leave=None): if on_enter is not None: on_enter(node) for child in node.children(): traverse(child, on_enter, on_leave) if on_leave is not None: on_leave(node) ந৅ߏจ໦ͷϊʔυΛ๚ΕͨͷͰPO@FOUFSΛ࣮ߦ͢Δ ΋͠PO@FOUFS͕লུ͞Ε͍ͯΔ৔߹͸Կ΋͠ͳ͍

Slide 180

Slide 180 text

def traverse(node, on_enter=None, on_leave=None): if on_enter is not None: on_enter(node) for child in node.children(): traverse(child, on_enter, on_leave) if on_leave is not None: on_leave(node) ந৅ߏจ໦ͷϊʔυ͔ΒࢠͷҰཡΛ
 औಘ͠ɺࢠΛ࠶ؼతʹ૸͍ࠪͯ͘͠

Slide 181

Slide 181 text

def traverse(node, on_enter=None, on_leave=None): if on_enter is not None: on_enter(node) for child in node.children(): traverse(child, on_enter, on_leave) if on_leave is not None: on_leave(node) ࢠͷ૸͕ࠪऴΘͬͨͷͰɺࠓͷϊʔυ͔Βୀग़͢Δ

Slide 182

Slide 182 text

͜͜·ͰͰ؆୯ʹ૸ࠪؔ਺Λ࣮૷Ͱ͖ͨ ૸ࠪؔ਺͸഑ྻͰ͍͏GPS&BDIͷΑ͏ͳ
 جૅతͳؔ਺ͩͱߟ͑ΔͱΘ͔Γ΍͍͢ ͦͷͨΊɺͱͯ΋Ԡ༻ͷൣғ͕޿͍

Slide 183

Slide 183 text

w ৚݅ʹ͋ͬͨந৅ߏจ໦ͷϊʔυͷநग़ w ม਺ؔ਺ͷείʔϓղੳ w ʜ ૸ࠪؔ਺ͰͰ͖Δ͜ͱ

Slide 184

Slide 184 text

found = find_nodes(node, condition) ৚݅ʹ͋ͬͨந৅ߏจ໦ͷϊʔυͷநग़ ୳ࡧ͍ͨ͠ந৅ߏจ໦ ݕࡧ͍ͨ͠৚݅ͷؔ਺ ͜ͷநग़ؔ਺͸૸ࠪؔ਺Λ࢖ͬͯ
 ؆୯ʹ࣮૷Ͱ͖Δ

Slide 185

Slide 185 text

def find_nodes(node, condition): found_nodes = [] def collect_nodes(entered_node): if not condition(entered_node): return found_nodes.append(entered_node) traverse(node, collect_nodes) return found_nodes

Slide 186

Slide 186 text

def find_nodes(node, condition): found_nodes = [] def collect_nodes(entered_node): if not condition(entered_node): return found_nodes.append(entered_node) traverse(node, collect_nodes) return found_nodes ݕࡧ৚݅ʹ͋ͯ͸·Δந৅ߏจ໦ͷϊʔυΛूΊΔ഑ྻ

Slide 187

Slide 187 text

def find_nodes(node, condition): found_nodes = [] def collect_nodes(entered_node): if not condition(entered_node): return found_nodes.append(entered_node) traverse(node, collect_nodes) return found_nodes ந৅ߏจ໦ͷϊʔυΛ๚ΕΔλΠϛϯάͰݕࡧ৚݅ͷ
 ؔ਺Λ࣮૷͠ɺ৚݅ʹ͋ͯ͸·ΔϊʔυΛूΊΔؔ਺

Slide 188

Slide 188 text

def find_nodes(node, condition): found_nodes = [] def collect_nodes(entered_node): if not condition(entered_node): return found_nodes.append(entered_node) traverse(node, collect_nodes) return found_nodes ந৅ߏจ໦ͷϊʔυΛूΊΔؔ਺Λ
 PO@FOUFSʹࢦఆͯ͠૸ࠪΛ։࢝

Slide 189

Slide 189 text

def find_nodes(node, condition): found_nodes = [] def collect_nodes(entered_node): if not condition(entered_node): return found_nodes.append(entered_node) traverse(node, collect_nodes) return found_nodes ݟ͔ͭͬͨந৅ߏจ໦ͷϊʔυͷ഑ྻΛฦ͢

Slide 190

Slide 190 text

def find_nodes(node, condition): found_nodes = [] def collect_nodes(entered_node): if not condition(entered_node): return found_nodes.append(entered_node) traverse(node, collect_nodes) return found_nodes ૸ࠪؔ਺Λ࢖͏͜ͱͰɺͱͯ΋؆୯ʹ࣮૷Ͱ͖ͨ

Slide 191

Slide 191 text

ଞʹ΋ɺ૸ࠪؔ਺Λ࢖͏ͱείʔϓղੳΛ
 ࣮૷͠΍͘͢ͳΔ είʔϓղੳͱ͸ɺม਺ͷఆٛ͞Ε͍ͯΔ
 είʔϓΛղੳ͢Δ͜ͱͰɺະఆٛͷม਺΍
 ະ࢖༻ͷม਺Λݟ͚ͭΔख๏

Slide 192

Slide 192 text

ίʔυ͕͔ͳΓ௕͘ͳΔͷͰɺ࣮ࡍͷίʔυ͸ׂѪ͢Δ͕ɺ
 େ·͔ʹҎԼͷखॱͰείʔϓΛղੳͰ͖Δɿ ؔ਺એݴͷߏจ໦΁ͷPO@FOUFSͰ
 είʔϓΦϒδΣΫτΛ࡞੒͢Δ ࡞੒ͨ͠είʔϓΦϒδΣΫτΛ
 ݱࡏͷείʔϓͷελοΫʹੵΉ ݟ͔ͭͬͨม਺એݴΛελοΫͷઌ಄ͷ
 είʔϓΦϒδΣΫτ΁Ճ͍͑ͯ͘ ؔ਺એݴͷߏจ໦͔ΒͷPO@MFBWFͰ
 ઌ಄ͷείʔϓΦϒδΣΫτΛ
 ελοΫ͔ΒऔΓআ͘    

Slide 193

Slide 193 text

• https://github.com/estools/escope • https://github.com/rubocop-hq/rubocop
 ͷ VariableForce • https://github.com/Kuniwak/vint
 ͷ scope_plugin ࢀߟʹͳΔείʔϓղੳͷ࣮૷

Slide 194

Slide 194 text

૸ࠪؔ਺ͷ࣮૷Ͱઆ໌͠ͳ͔ͬͨ͜ͱ w ૸ࠪͷதஅ΍ࢠͷ୳ࡧͷεΩοϓػೳ w ύϑΥʔϚϯεվળͷͨΊʹॏཁ w ୈڃؔ਺Λ࢖Θͳ͍૸ࠪؔ਺ͷ࣮૷ w ݴޠʹΑͬͯ͸ؔ਺ΛҾ਺ʹ౉ͤͳ͍͜ͱ΋͋Δ w ͦͷ৔߹͸(P'ͷ7JTJUPSύλʔϯͰ୅ସՄೳ

Slide 195

Slide 195 text

૸ࠪؔ਺ͷ·ͱΊ w ந৅ߏจ໦ͷ૸ࠪؔ਺Λఆ͓ٛͯ͘͠ͱศར w ૸ࠪؔ਺ͷ࣮૷͸೉͘͠ͳ͍ w ૸ࠪؔ਺͸͞·͟·ͳॲཧ΁Ԡ༻Ͱ͖Δ

Slide 196

Slide 196 text

؆୯ͳ੩తղੳΛ
 ࣮૷ͯ͠ΈΑ͏ Α͏΍͘ΰʔϧ

Slide 197

Slide 197 text

if isEmpty('') { //CATCH_ME_IF_YOU_CAN } ͓୊͸ɺੜҙؾͳίϝϯτ਺Λใࠂ͢Δ੩తղੳ report_specific_comments(text) # Found 1 namaiki comments!

Slide 198

Slide 198 text

 ߏจղੳͯ͠ந৅ߏจ໦Λ࡞੒͢Δ  ந৅ߏจ໦Λ૸ࠪͯ͠ྫͷίϝϯτΛूΊΔ  ूΊͨίϝϯτΛใࠂ͢Δ ࣮૷ͷྲྀΕ

Slide 199

Slide 199 text

def report_namaiki_comments(text): node = parse_program(text) if node is None: print("Syntax Error!") return namaiki_comments = find_nodes(node, is_namaiki_comment) print("Found {count} comments!".format(count=len(namaiki_comments))) def is_namaiki_comment(entered_node): if not isinstance(entered_node, CommentStatementNode): return False comment_node = entered_node return "CATCH_ME_IF_YOU_CAN" in comment_node.comment_content ίʔυ͔ΒੜҙؾͳίϝϯτΛݟ͚ͭͯ਺Λใࠂ͢Δؔ਺

Slide 200

Slide 200 text

def report_namaiki_comments(text): node = parse_program(text) if node is None: print("Syntax Error!") return namaiki_comments = find_nodes(node, is_namaiki_comment) print("Found {count} comments!".format(count=len(namaiki_comments))) def is_namaiki_comment(entered_node): if not isinstance(entered_node, CommentStatementNode): return False comment_node = entered_node return "CATCH_ME_IF_YOU_CAN" in comment_node.comment_content ίʔυΛߏจղੳͯ͠ந৅ߏจ໦Λ࡞੒͢Δ

Slide 201

Slide 201 text

def report_namaiki_comments(text): node = parse_program(text) if node is None: print("Syntax Error!") return namaiki_comments = find_nodes(node, is_namaiki_comment) print("Found {count} comments!".format(count=len(namaiki_comments))) def is_namaiki_comment(entered_node): if not isinstance(entered_node, CommentStatementNode): return False comment_node = entered_node return "CATCH_ME_IF_YOU_CAN" in comment_node.comment_content ߏจղੳʹࣦഊͨ͠ΒɺߏจΤϥʔΛදࣔ

Slide 202

Slide 202 text

def report_namaiki_comments(text): node = parse_program(text) if node is None: print("Syntax Error!") return namaiki_comments = find_nodes(node, is_namaiki_comment) print("Found {count} comments!".format(count=len(namaiki_comments))) def is_namaiki_comment(entered_node): if not isinstance(entered_node, CommentStatementNode): return False comment_node = entered_node return "CATCH_ME_IF_YOU_CAN" in comment_node.comment_content ૸ࠪؔ਺ͷར༻ྫͱ࣮ͯ͠૷ͨ͠ɺݕࡧؔ਺Λ࢖ͬͯੜҙؾͳίϝϯτΛूΊΔ

Slide 203

Slide 203 text

def report_namaiki_comments(text): node = parse_program(text) if node is None: print("Syntax Error!") return namaiki_comments = find_nodes(node, is_namaiki_comment) print("Found {count} comments!".format(count=len(namaiki_comments))) def is_namaiki_comment(entered_node): if not isinstance(entered_node, CommentStatementNode): return False comment_node = entered_node return "CATCH_ME_IF_YOU_CAN" in comment_node.comment_content ݕࡧؔ਺ͷ৚݅ʹࢦఆͨ͠ɺੜҙؾίϝϯτ͔Ͳ͏͔൑ఆ͢Δؔ਺

Slide 204

Slide 204 text

def report_namaiki_comments(text): node = parse_program(text) if node is None: print("Syntax Error!") return namaiki_comments = find_nodes(node, is_namaiki_comment) print("Found {count} comments!".format(count=len(namaiki_comments))) def is_namaiki_comment(entered_node): if not isinstance(entered_node, CommentStatementNode): return False comment_node = entered_node return "CATCH_ME_IF_YOU_CAN" in comment_node.comment_content ·ͣɺந৅ߏจ໦͕ίϝϯτจͰͳ͚Ε͹ɺ
 ੜҙؾͳίϝϯτͰ͸ͳ͍ͷͰɺ'BMTFΛฦͯ͠ऴྃ

Slide 205

Slide 205 text

def report_namaiki_comments(text): node = parse_program(text) if node is None: print("Syntax Error!") return namaiki_comments = find_nodes(node, is_namaiki_comment) print("Found {count} comments!".format(count=len(namaiki_comments))) def is_namaiki_comment(entered_node): if not isinstance(entered_node, CommentStatementNode): return False comment_node = entered_node return "CATCH_ME_IF_YOU_CAN" in comment_node.comment_content ίϝϯτจͩͬͨ৔߹ɺίϝϯτͷ಺༰ʹੜҙؾͳ
 ΋ͷؚ͕·Ε͍ͯΕ͹5SVFɺͦΕҎ֎͸'BMTFΛฦ͢

Slide 206

Slide 206 text

def report_namaiki_comments(text): node = parse_program(text) if node is None: print("Syntax Error!") return namaiki_comments = find_nodes(node, is_namaiki_comment) print("Found {count} comments!".format(count=len(namaiki_comments))) def is_namaiki_comment(entered_node): if not isinstance(entered_node, CommentStatementNode): return False comment_node = entered_node return "CATCH_ME_IF_YOU_CAN" in comment_node.comment_content ઌ΄Ͳͷؔ਺Ͱ5SVF͕ฦ͞Εͨந৅ߏจ໦ʢੜҙؾͳίϝϯτʣ͕
 Ұཡʹͯ͠ฦ͞ΕΔ

Slide 207

Slide 207 text

def report_namaiki_comments(text): node = parse_program(text) if node is None: print("Syntax Error!") return namaiki_comments = find_nodes(node, is_namaiki_comment) print("Found {count} comments!".format(count=len(namaiki_comments))) def is_namaiki_comment(entered_node): if not isinstance(entered_node, CommentStatementNode): return False comment_node = entered_node return "CATCH_ME_IF_YOU_CAN" in comment_node.comment_content ੜҙؾͳίϝϯτͷ਺Λใࠂͯ͠ऴྃ

Slide 208

Slide 208 text

def report_namaiki_comments(text): node = parse_program(text) if node is None: print("Syntax Error!") return namaiki_comments = find_nodes(node, is_namaiki_comment) print("Found {count} comments!".format(count=len(namaiki_comments))) def is_namaiki_comment(entered_node): if not isinstance(entered_node, CommentStatementNode): return False comment_node = entered_node return "CATCH_ME_IF_YOU_CAN" in comment_node.comment_content ߏจղੳثɾ૸ࠪؔ਺ɾݕࡧؔ਺Λ
 ૊Έ߹Θͤͯ࢖͏͜ͱͰɺͱͯ΋
 ؆୯ʹ੩తݕࠪΛ࣮૷Ͱ͖ͨ

Slide 209

Slide 209 text

؆୯ͳ੩తݕࠪͷ࣮૷·ͱΊ ੩తݕࠪ͸ɺߏจղੳثɾ૸ࠪؔ਺ɾݕࡧؔ਺Λ
 ૊Έ߹ΘͤΔ͜ͱͰɺ͘͝؆୯ʹ࣮૷Ͱ͖Δ

Slide 210

Slide 210 text

ෳࡶͳ੩తղੳΛ
 ෼ׂ͢ΔςΫχοΫ ΰʔϧୡ੒ͷͦͷઌ΁

Slide 211

Slide 211 text

ઌ΄Ͳ͸ͭͷ੩తݕࠪϧʔϧͷΈΛ࣮૷͕ͨ͠ɺ
 ݱ࣮ʹ͸ෳ਺ͷݕࠪϧʔϧΛ࣮૷͢Δ͜ͱ͕ଟ͍ ͜ͷͱ͖ɺͲͷΑ͏ʹίʔυΛ෼ׂ͢Δ͔ʹΑͬͯ
 อकੑ͕େ͖͘มΘΔ

Slide 212

Slide 212 text

ݕࠪϧʔϧʹΑΔ෼ׂΛ঺հ ༗໊ͳ੩తղੳπʔϧͷ൒਺Ҏ্͕࠾༻͍ͯ͠Δ

Slide 213

Slide 213 text

ݕࠪϧʔϧʹΑΔ෼ׂͰ͸ɺͭͷݕࠪϧʔϧ͕
 ͭͷίϯϙʔωϯτʢΫϥεPSؔ਺ʣʹରԠ͢Δ ͜ΕʹΑͬͯݕࠪϧʔϧ͕͓ޓ͍ʹૄʹͳΓɺ
 ݕࠪϧʔϧͷ௥Ճमਖ਼࡟আΛ΍Γ΍͘͢ͳΔ

Slide 214

Slide 214 text

class Policy: def get_violations(self, node): raise NotImplementedError() ݕࠪϧʔϧͷڞ௨ΠϯλʔϑΣʔεΛܾΊΔ

Slide 215

Slide 215 text

class Policy: def get_violations(self, node): raise NotImplementedError() ந৅ߏจ໦ͷϊʔυ͔Βݟ͔ͭͬͨ໰୊Λɺจࣈྻͷ
 ഑ྻͱͯ͠ฦ͢ϝιουɻ͜ͷϝιου͸ɺ΄͔ͷ
 ίϯϙʔωϯτ಺Ͱ૸ࠪؔ਺͔Βݺ͹ΕΔΠϝʔδ

Slide 216

Slide 216 text

class Policy: def get_violations(self, node): raise NotImplementedError() ྫ͑͹ɺҾ਺ʹੜҙؾͳίϝϯτจ͕͖ͨΒ
 ࢦఠϝοηʔδΛฦ࣮͢૷΍ɺJGจ͕͖ͨΒ
 ৚݅෦෼ͷࣜΛݕࠪ͢Δͧɺͱ͍͏࣮૷͕͋Γ͑Δ ॏཁͳͷ͸ɺݕࠪϧʔϧ͕ผͳΒผͷΫϥεʹ
 ෼ׂ࣮ͯ͠૷͢Δ͜ͱɻҰॹʹ͢Δͱอक͕େมʹͳΔ

Slide 217

Slide 217 text

class NamaikiCommentPolicy(Policy): def get_violations(self, node): if not is_namaiki_comment(node): return [] return ["FOUND YOU!"] def is_namaiki_comment(entered_node): if not isinstance(entered_node, CommentStatementNode): return False comment_node = entered_node return "CATCH_ME_IF_YOU_CAN" in comment_node.comment_content લʹ࣮૷ͨ͠ͷͱಉ͡ɺੜҙؾͳίϝϯτจΛࢦఠ͢Δݕࠪϧʔϧ

Slide 218

Slide 218 text

class NamaikiCommentPolicy(Policy): def get_violations(self, node): if not is_namaiki_comment(node): return [] return ["FOUND YOU!"] def is_namaiki_comment(entered_node): if not isinstance(entered_node, CommentStatementNode): return False comment_node = entered_node return "CATCH_ME_IF_YOU_CAN" in comment_node.comment_content Ҿ਺ͷந৅ߏจ໦ͷϊʔυ͕ੜҙؾͳίϝϯτจʼͳΒɺ
 ʮݟ͚ͭͨͧʂʯͱ͍͏ϝοηʔδΛฦ͢Α͏ʹ࣮૷

Slide 219

Slide 219 text

class NamaikiCommentPolicy(Policy): def get_violations(self, node): if not is_namaiki_comment(node): return [] return ["FOUND YOU!"] def is_namaiki_comment(entered_node): if not isinstance(entered_node, CommentStatementNode): return False comment_node = entered_node return "CATCH_ME_IF_YOU_CAN" in comment_node.comment_content ੜҙؾͳίϝϯτจΛ൑ఆ͢Δؔ਺͸લͷ΋ͷΛྲྀ༻

Slide 220

Slide 220 text

class Policies(Policy): def __init__(self, policies): self.policies = policies def get_violations(self, node): return reduce( lambda violations, policy: violations + policy.get_violations(node), self.policies, [] ) ෳ਺ͷݕࠪϧʔϧΛଋͶΔݕࠪϧʔϧΛ४උ

Slide 221

Slide 221 text

class Policies(Policy): def __init__(self, policies): self.policies = policies def get_violations(self, node): return reduce( lambda violations, policy: violations + policy.get_violations(node), self.policies, [] ) ݕࠪϧʔϧͱಉ͡ڞ௨ΠϯλʔϑΣʔεΛ࣮૷͢Δ

Slide 222

Slide 222 text

class Policies(Policy): def __init__(self, policies): self.policies = policies def get_violations(self, node): return reduce( lambda violations, policy: violations + policy.get_violations(node), self.policies, [] ) ಺෦ͷෳ਺ͷݕࠪϧʔϧΛϧʔϓͯ͠ݕࠪͯ͠ɺ݁ՌΛ߹੒ͯ͠ฦ͢

Slide 223

Slide 223 text

def lint(text): node = parse_program(text) if node is None: return ["Syntax Error!"] policies = Policies([NamaikiCommentPolicy()]) violations_buffer = [] def collect_violations(entered_node): violations = policies.get_violations(entered_node) violations_buffer.append(violations) traverse(node, collect_violations) all_violations = [] return reduce(add, violations_buffer, all_violations)

Slide 224

Slide 224 text

def lint(text): node = parse_program(text) if node is None: return ["Syntax Error!"] policies = Policies([NamaikiCommentPolicy()]) violations_buffer = [] def collect_violations(entered_node): violations = policies.get_violations(entered_node) violations_buffer.append(violations) traverse(node, collect_violations) all_violations = [] return reduce(add, violations_buffer, all_violations) ෳ਺ͷݕࠪϧʔϧͰ·ͱΊͯݕࠪ͢Δؔ਺

Slide 225

Slide 225 text

def lint(text): node = parse_program(text) if node is None: return ["Syntax Error!"] policies = Policies([NamaikiCommentPolicy()]) violations_buffer = [] def collect_violations(entered_node): violations = policies.get_violations(entered_node) violations_buffer.append(violations) traverse(node, collect_violations) all_violations = [] return reduce(add, violations_buffer, all_violations) ༩͑ΒΕͯจࣈྻΛߏจղੳͯ͠ந৅ߏจ໦Λ࡞੒

Slide 226

Slide 226 text

def lint(text): node = parse_program(text) if node is None: return ["Syntax Error!"] policies = Policies([NamaikiCommentPolicy()]) violations_buffer = [] def collect_violations(entered_node): violations = policies.get_violations(entered_node) violations_buffer.append(violations) traverse(node, collect_violations) all_violations = [] return reduce(add, violations_buffer, all_violations) ߏจղੳʹࣦഊͨ͠ΒɺߏจղੳࣦഊͷϝοηʔδΛ݁Ռͱͯ͠ฦ͢

Slide 227

Slide 227 text

def lint(text): node = parse_program(text) if node is None: return ["Syntax Error!"] policies = Policies([NamaikiCommentPolicy()]) violations_buffer = [] def collect_violations(entered_node): violations = policies.get_violations(entered_node) violations_buffer.append(violations) traverse(node, collect_violations) all_violations = [] return reduce(add, violations_buffer, all_violations) ෳ਺ͷݕࠪϧʔϧΛଋͶͯɺͭͷݕࠪϧʔϧʹ·ͱΊΔ
 ʢ͜ͷྫͰ͸ɺੜҙؾͳίϝϯτΛݕࠪ͢Δϧʔϧ͚ͩʣ

Slide 228

Slide 228 text

def lint(text): node = parse_program(text) if node is None: return ["Syntax Error!"] policies = Policies([NamaikiCommentPolicy()]) violations_buffer = [] def collect_violations(entered_node): violations = policies.get_violations(entered_node) violations_buffer.append(violations) traverse(node, collect_violations) all_violations = [] return reduce(add, violations_buffer, all_violations) ݕࠪϝοηʔδΛूΊΔ഑ྻΛ४උ

Slide 229

Slide 229 text

def lint(text): node = parse_program(text) if node is None: return ["Syntax Error!"] policies = Policies([NamaikiCommentPolicy()]) violations_buffer = [] def collect_violations(entered_node): violations = policies.get_violations(entered_node) violations_buffer.append(violations) traverse(node, collect_violations) all_violations = [] return reduce(add, violations_buffer, all_violations) ༩͑ΒΕͨந৅ߏจ໦ͷϊʔυ͔ΒɺݕࠪϝοηʔδΛूΊΔؔ਺

Slide 230

Slide 230 text

def lint(text): node = parse_program(text) if node is None: return ["Syntax Error!"] policies = Policies([NamaikiCommentPolicy()]) violations_buffer = [] def collect_violations(entered_node): violations = policies.get_violations(entered_node) violations_buffer.append(violations) traverse(node, collect_violations) all_violations = [] return reduce(add, violations_buffer, all_violations) ந৅ߏจ໦Λ૸ࠪͯ͠ɺݕࠪϝοηʔδΛूΊ͍ͯ͘

Slide 231

Slide 231 text

def lint(text): node = parse_program(text) if node is None: return ["Syntax Error!"] policies = Policies([NamaikiCommentPolicy()]) violations_buffer = [] def collect_violations(entered_node): violations = policies.get_violations(entered_node) violations_buffer.append(violations) traverse(node, collect_violations) all_violations = [] return reduce(add, violations_buffer, all_violations) ू·ͬͨݕࠪϝοηʔδΛͭͷ഑ྻʹ·ͱΊͯฦ͢

Slide 232

Slide 232 text

text = "if isEmpty('') {\n// CATCH_ME_IF_YOU_CAN\n}\n" violations = lint(text) ෳ਺ͷݕࠪϧʔϧͰ੩తղੳͰ͖ΔΑ͏ʹͳͬͨ

Slide 233

Slide 233 text

ݕࠪϧʔϧʹΑΔ෼ׂͷ·ͱΊ w ੩తݕࠪͷݕࠪϧʔϧ͸ݸผͷίϯϙʔωϯτ
 ͱ࣮ͯ͠૷͢Δͱอक͠΍͍͢ w ଟ͘ͷ੩తݕࠪπʔϧ͸͜ͷύλʔϯʹԊͬͯ
 ࣮૷͞Ε͍ͯΔ

Slide 234

Slide 234 text

ଞʹ΋࣮૷ύλʔϯ͸ͨ͘͞Μ͋Δ͕ɺ
 ࣌ؒͷ౎߹ʢͱࠓͷମྗʣͰ͸঺հ͖͠Εͳ͍ ͞Βʹ஌Γ͍ͨํ͸ɺʮ7JNTDSJQUͷ-JOU࡞ऀʹ
 ΑΔ୭ಘσβΠϯύλʔϯʯͱ͍͏هࣄΛࢀর https://qiita.com/Kuniwak/items/d6a2d22711e4d7856edd

Slide 235

Slide 235 text

࣮ࡍͷ੩తݕࠪπʔϧͷ
 ࣮૷ΛಡΜͰΈΑ͏ ීஈ࢖͍ͬͯΔ

Slide 236

Slide 236 text

1ZUIPO w ߏจղੳث w BTUQBSTFʢඪ४ϥΠϒϥϦʣ w ૸ࠪؔ਺ w BTU/PEF7JTJUPSʢඪ४ϥΠϒϥϦʣ w ੩తݕࠪϧʔϧ w $IFDLFS53:ʢQZqBLFTͷQZqBLTDIFDLFSQZʣ

Slide 237

Slide 237 text

3VCZ w ߏจղੳث w 1BSTFS3VCZ
 (JU)VCͷXIJUFRVBSLQBSTFSͷMJCQBSTFSSVCZZ  w ૸ࠪؔ਺ w 3VCPDPQ"455SBWFSTBM
 3VCPDPQͷMJCSVCPDPQBTUUSBWFSTBMSC  w ੩తݕࠪϧʔϧ w 3VCPDPQ$PQ-JOU&NQUZ&OTVSF
 3VCPDPQͷMJCSVCPDPQDPQMJOUFNQUZ@FOTVSFSC

Slide 238

Slide 238 text

+BWB4DSJQU w ߏจղੳث w 1BSTFSʢ(JU)VCͷBDPSOKTBDPSOͷTSDTUBUFKT  w ૸ࠪؔ਺ w 5SBWFSTFUSBWFSTF
 &4-JOUͷMJCVUJMUSBWFSTFKT  w ੩తݕࠪϧʔϧ w SVMFTOPFNQUZGVODUJPO
 &4-JOUͷMJCSVMFTOPFNQUZGVODUJPOKT

Slide 239

Slide 239 text

͜Ε·Ͱͷ஌ࣝʹΑͬͯ
 ࡞ΕΔΑ͏ʹͳΔ΋ͷ కΊ͘͘Γʹ

Slide 240

Slide 240 text

ෳ਺ͷݕࠪϧʔϧʹΑΔ੩తݕࠪ https://github.com/Kuniwak/Vint

Slide 241

Slide 241 text

$44ͷந৅ߏจ໦Λൺֱ͢Δπʔϧ https://github.com/mixi-inc/css-semdiff $ css-astdiff a.css b.css --verbose extra: .extra-1 { border: none; } missing: .missing-1 { border: none; } --------------------------------- 1 extra rules and 1 missing rules

Slide 242

Slide 242 text

؆қతͳߏจղੳͰґଘؔ܎σʔλϕʔεΛ࡞੒ https://twitter.com/orga_chem/status/674847225684475905

Slide 243

Slide 243 text

·ͱΊ ੩తղੳΛߏ੒͢Δجຊతͳߟ͑ํΛ঺հɿ w ந৅ߏจ໦ w ߏจղੳ w ૸ࠪؔ਺ w ݕࠪϧʔϧͷ෼ׂ ੩తղੳ͸ҙ֎ͱ؆୯ʹ࣮૷Ͱ͖·͢

Slide 244

Slide 244 text

ࢀߟจݙ ͍·Ͳ͖ͷϓϩάϥϜݴޠͷ࡞ΓํʢஶSBOEZʣ https://www.amazon.co.jp/dp/4839919232 .POBEJD1BSTFS$PNCJOBUPS http://www.cs.nott.ac.uk/~pszgmh/monparsing.pdf # "