詳説ぺちぺち 闇PHP勉強会 + PHPソースコード   リーディングワークショップ               2012/01/28                   do_aki
do_aki (どぅーあき)• |所属| > 株式会社もしも        (ドロップシッピング・アフィリエイトASP)• |仕事| > インフラ(サーバ管理)兼         Webアプリケーション開発• |出現| > 渋谷・山手線沿線• ...
あじぇんだ•   第1章 ぺちぺち•   第2章 Scanner (字句解析器)•   第3章 Parser (構文解析器)•   まとめ
第1章ぺちぺち
Japanese Programming      Language      らきすた風 画像生成 (ジェネレーター) http://raki.st/
闇鍋的PHP魔改造 2011/09/10 PHPカンファレンス2011                Presented By do_aki
PHPの言語そのものの作りとかよく 知らないし、内部構造もよく分からないけど、オレオレPHPを作って みたくてトライ&エラー繰り返していたら気づいたらPHPを基にした 日本語プログラミング言語ができ ちゃってたから発表してみたよ!       ...
<?php  function HelloPHP() {    echo "Hello PHP World";  }  HelloPHP();                 PHPぺちぺち 関数 はろーぺちぺち() ここから  「"はろー ぺ...
条件分岐もし [条件] ならば  … そうでないならば  …条件おわり
繰り返し繰り返し [条件] の間ここから  …ここまで
変数/条件/演算子変数:ほげ は 0 です1 が 2 より小さい (1<2)1 が 2 より大きい (1>2)1 足す 2 (1+2)10 を 3 で割った余り (10%3)
組み合わせるとぺちぺち変数:ほげ は 1です;繰り返し 変数:ほげ が 10 以下 の間ここから もし 変数:ほげ を 3 で割った余り が 0 に等しい ならば    「 “アホn"」と表示; そうでないならば    「 変数:ほげ,"n"」...
ぺちぺち と PHP の違い・Zend/zend_language_scanner.l            add 98 lines & modify 22 lines・Zend/zend_language_parser.y         ...
第2章Scanner
スキャナの状態  zend_language_scanner.l                               の半分から下あたり<ST_IN_SCRIPTING>"function" {  return T_FUNCTION;}...
スキャナの状態  zend_language_scanner.l                               の半分から下あたり<ST_IN_SCRIPTING>“def" {  return T_FUNCTION;}     ...
ぺちぺちでは<ST_IN_SCRIPTING>“function“|”関数” {<ST_IN_SCRIPTING>"function" {  return T_FUNCTION;}<ST_IN_SCRIPTING>“{“ { ここから” {<S...
スキャナの状態•   INITIAL•   ST_IN_SCRIPTING•   ST_LOOKING_FOR_PROPERTY•   ST_LOOKING_FOR_VARNAME•   ST_VAR_OFFSET•   ST_DOUBLE_Q...
ほとんどはこの状態             スキャナの状態•   INITIAL                   初期状態•   ST_IN_SCRIPTING           基本状態•   ST_LOOKING_FOR_PROPER...
ぺちぺち動かずぺちぺち  echo "petipeti!n";   OKぺちぺち                    NG  echo "petipeti!n";
<INITIAL>"<?php"([ t]|{NEWLINE})<INITIAL>("<?php"|"ぺちぺち")([ t]|{NEWLINE}) {<ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*"...
落とし穴• “変数”の扱いは少し複雑 – 3カ所 + 隠し1カ所 (Parser 側からのみ参照)• 複雑な処理をしているところも – HEREDOC , NOWDOC – __CLASS__• 簡単にセグる
<ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>"$"{LABEL} {   zend_copy_value(zendlval, (yytext+1...
<ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>"$"{LABEL} {   zend_copy_value(zendlval, (yytext+1...
第2章 Scanner まとめ• 元々あるキーワードの変更/追加は簡単• スキャナの状態もほとんど意識する必要  はない• ところどころ Cで無理矢理処理してる部分  があるので注意
第2章Scanner   完
第3章Parser
Scanner によるトークンへの分解<?php              T_OPEN_TAG                   T_VARIABLE    $x = $a + 1;   ‘=‘    ++$x;          T_VA...
Syntax Error                 T_LNUMBER                 ‘=’1 = $a;          T_VARIABLE                 ‘;‘Perser にトークンの並びが定...
zend_language_parser.y                                      ルール名fully_qualified_class_name:   namespace_name { $$ = $1; } ...
zend_language_parser.y     拡張するために    新たにルールを作る          BAD 処理をどう書けばいいのか分    からない orz
似ているルールを真似る
T_VARIABLE      $a + 1                  ‘+’                              T_LNUMBERexpr + expr { zend_do_binary_op(ZEND_ADD...
IF 文T_IF ( expr )       { zend_do_if_cond(&$3, &$4); }statement               { zend_do_if_after_statement(&$4, 1); }elsei...
落とし穴• 突然現れる ‘$’ – Scanner で T_VARIABLE として処理されてな   い!?• 本気でやるなら opecode / ZendAPI の知識  が必須• コンパイルしてみないと分からない
Parser は 複雑なパズル    解きやすくするツール・方法あったら教えてほしいなー
第3章 Parser   完
まとめ
Phpをいじり倒す10の方法 (2009) http://www.slideshare.net/moriyoshi/php10
言いたかったこと• オレオレPHP作るの難しくないよ!• 拡張作るのも良いけど、言語そのものに  コミットメントしてもいいんじゃないか  な• PHPを楽しむ人が増えて、PHP がより一層  面白いものになってくれたらいいな
改造のお供に• GNU GLOBAL  (http://www.gnu.org/software/global/)  – 静的にソースコードを解析するのに便利!  – PHP のソースを展開したディレクトリで      htags -Ffgna...
最後に• ぺちぺちは github においてあります• http://git.io/petipeti
ありがとうございました• 質疑応答?
Upcoming SlideShare
Loading in …5
×

詳説ぺちぺち

1,496 views

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,496
On SlideShare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
3
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

詳説ぺちぺち

  1. 1. 詳説ぺちぺち 闇PHP勉強会 + PHPソースコード リーディングワークショップ 2012/01/28 do_aki
  2. 2. do_aki (どぅーあき)• |所属| > 株式会社もしも (ドロップシッピング・アフィリエイトASP)• |仕事| > インフラ(サーバ管理)兼 Webアプリケーション開発• |出現| > 渋谷・山手線沿線• |特性| > PHPer http://do-aki.net/
  3. 3. あじぇんだ• 第1章 ぺちぺち• 第2章 Scanner (字句解析器)• 第3章 Parser (構文解析器)• まとめ
  4. 4. 第1章ぺちぺち
  5. 5. Japanese Programming Language らきすた風 画像生成 (ジェネレーター) http://raki.st/
  6. 6. 闇鍋的PHP魔改造 2011/09/10 PHPカンファレンス2011 Presented By do_aki
  7. 7. PHPの言語そのものの作りとかよく 知らないし、内部構造もよく分からないけど、オレオレPHPを作って みたくてトライ&エラー繰り返していたら気づいたらPHPを基にした 日本語プログラミング言語ができ ちゃってたから発表してみたよ! ・・・というもの
  8. 8. <?php function HelloPHP() { echo "Hello PHP World"; } HelloPHP(); PHPぺちぺち 関数 はろーぺちぺち() ここから 「"はろー ぺちぺち わーるど"」と表示; ここまで ぺちぺち はろーぺちぺち();
  9. 9. 条件分岐もし [条件] ならば … そうでないならば …条件おわり
  10. 10. 繰り返し繰り返し [条件] の間ここから …ここまで
  11. 11. 変数/条件/演算子変数:ほげ は 0 です1 が 2 より小さい (1<2)1 が 2 より大きい (1>2)1 足す 2 (1+2)10 を 3 で割った余り (10%3)
  12. 12. 組み合わせるとぺちぺち変数:ほげ は 1です;繰り返し 変数:ほげ が 10 以下 の間ここから もし 変数:ほげ を 3 で割った余り が 0 に等しい ならば 「 “アホn"」と表示; そうでないならば 「 変数:ほげ,"n"」と表示; 条件おわり 変数:ほげ に 変数:ほげ 足す 1 を代入;ここまで
  13. 13. ぺちぺち と PHP の違い・Zend/zend_language_scanner.l add 98 lines & modify 22 lines・Zend/zend_language_parser.y add 65 lines & modify 1 line
  14. 14. 第2章Scanner
  15. 15. スキャナの状態 zend_language_scanner.l の半分から下あたり<ST_IN_SCRIPTING>"function" { return T_FUNCTION;} この文字列 このトークンを 返す が来たら<ST_IN_SCRIPTING>“{“ { yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); return {;}
  16. 16. スキャナの状態 zend_language_scanner.l の半分から下あたり<ST_IN_SCRIPTING>“def" { return T_FUNCTION;} この文字列 このトークンを <?php返す が来たら<ST_IN_SCRIPTING>“{“ { の代わりに def function def hello() { echo “like ruby?”; yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); return {; なんちゃって ruby のでき }} あがり
  17. 17. ぺちぺちでは<ST_IN_SCRIPTING>“function“|”関数” {<ST_IN_SCRIPTING>"function" { return T_FUNCTION;}<ST_IN_SCRIPTING>“{“ { ここから” {<ST_IN_SCRIPTING>“{“|” yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); return {;}
  18. 18. スキャナの状態• INITIAL• ST_IN_SCRIPTING• ST_LOOKING_FOR_PROPERTY• ST_LOOKING_FOR_VARNAME• ST_VAR_OFFSET• ST_DOUBLE_QUOTES• ST_BACKQUOTE• ST_HEREDOC• ST_NOWDOC• ST_END_HEREDOC
  19. 19. ほとんどはこの状態 スキャナの状態• INITIAL 初期状態• ST_IN_SCRIPTING 基本状態• ST_LOOKING_FOR_PROPERTY ->これ• ST_LOOKING_FOR_VARNAME ${ これ}• ST_VAR_OFFSET $xxx[これ]• ST_DOUBLE_QUOTES “これ”• ST_BACKQUOTE `これ`• ST_HEREDOC <<<“DOC” の後• ST_NOWDOC <<<‘DOC’ の後• ST_END_HEREDOC DOC の終わり
  20. 20. ぺちぺち動かずぺちぺち echo "petipeti!n"; OKぺちぺち NG echo "petipeti!n";
  21. 21. <INITIAL>"<?php"([ t]|{NEWLINE})<INITIAL>("<?php"|"ぺちぺち")([ t]|{NEWLINE}) {<ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*">"){NEWLINE}? {<ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*">"|"ぺちぺちおしまい"){NEWLINE}? { これだけじゃ足りない orz <INITIAL>{ANY_CHAR} ???
  22. 22. 落とし穴• “変数”の扱いは少し複雑 – 3カ所 + 隠し1カ所 (Parser 側からのみ参照)• 複雑な処理をしているところも – HEREDOC , NOWDOC – __CLASS__• 簡単にセグる
  23. 23. <ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>"$"{LABEL} { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; return T_VARIABLE; } <ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>(“$“|”変数:”){LABEL} { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; } return T_VARIABLE; NG
  24. 24. <ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>"$"{LABEL} { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; return T_VARIABLE; } 変数名をコ ピーして保持 <ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>”変数:” {LABEL} { zend_copy_value(zendlval, (yytext+7), (yyleng-7)); zendlval->type = IS_STRING; return T_VARIABLE; }
  25. 25. 第2章 Scanner まとめ• 元々あるキーワードの変更/追加は簡単• スキャナの状態もほとんど意識する必要 はない• ところどころ Cで無理矢理処理してる部分 があるので注意
  26. 26. 第2章Scanner 完
  27. 27. 第3章Parser
  28. 28. Scanner によるトークンへの分解<?php T_OPEN_TAG T_VARIABLE $x = $a + 1; ‘=‘ ++$x; T_VARIABLE ‘+’ T_LNUMBER ‘;’ T_INC T_VARIABLE ‘;’
  29. 29. Syntax Error T_LNUMBER ‘=’1 = $a; T_VARIABLE ‘;‘Perser にトークンの並びが定義さ れていない
  30. 30. zend_language_parser.y ルール名fully_qualified_class_name: namespace_name { $$ = $1; } | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); } | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), …(省略) };トークンの 処理(C言語+α) 並び
  31. 31. zend_language_parser.y 拡張するために 新たにルールを作る BAD 処理をどう書けばいいのか分 からない orz
  32. 32. 似ているルールを真似る
  33. 33. T_VARIABLE $a + 1 ‘+’ T_LNUMBERexpr + expr { zend_do_binary_op(ZEND_ADD, &$$, &$1, &$3 TSRMLS_CC); } New! T_VARIABLE $a 足す 1 T_JA_PLUS T_LNUMBERexpr T_JA_PLUS expr { zend_do_binary_op(ZEND_ADD, &$$, &$1, &$3 TSRMLS_CC); }
  34. 34. IF 文T_IF ( expr ) { zend_do_if_cond(&$3, &$4); }statement { zend_do_if_after_statement(&$4, 1); }elseif_list else_single { zend_do_if_end(); }else_single: /* empty */ | T_ELSE statement PHPT_JA_IF expr T_NARABA { zend_do_if_cond(&$2, &$3); }inner_statement_list { zend_do_if_after_statement(&$3, 1); }ja_else_single T_OWARI { zend_do_if_end(); }ja_else_single: /* empty */ ぺちぺち | T_JA_ELSE inner_statement_list
  35. 35. 落とし穴• 突然現れる ‘$’ – Scanner で T_VARIABLE として処理されてな い!?• 本気でやるなら opecode / ZendAPI の知識 が必須• コンパイルしてみないと分からない
  36. 36. Parser は 複雑なパズル 解きやすくするツール・方法あったら教えてほしいなー
  37. 37. 第3章 Parser 完
  38. 38. まとめ
  39. 39. Phpをいじり倒す10の方法 (2009) http://www.slideshare.net/moriyoshi/php10
  40. 40. 言いたかったこと• オレオレPHP作るの難しくないよ!• 拡張作るのも良いけど、言語そのものに コミットメントしてもいいんじゃないか な• PHPを楽しむ人が増えて、PHP がより一層 面白いものになってくれたらいいな
  41. 41. 改造のお供に• GNU GLOBAL (http://www.gnu.org/software/global/) – 静的にソースコードを解析するのに便利! – PHP のソースを展開したディレクトリで htags -Ffgnasv – CGI 使えれば検索も可能
  42. 42. 最後に• ぺちぺちは github においてあります• http://git.io/petipeti
  43. 43. ありがとうございました• 質疑応答?

×